Курс на Си. Подбельский. Курс программирования на Си. В., Фомин С. С. Курс программирования на языке Си Учебник
Скачать 1.57 Mb.
|
Глава 1 16 БАЗОВЫЕ ПОНЯТИЯ ЯЗЫКА 16 1.1.Алфавит, идентификаторы, служебные слова 17 1.2.Литералы 20 1.3.Переменные и именованные 27 константы 27 1.4. Операции 35 1.5. Разделители 44 1.6.Выражения 49 Контрольные вопросы 59 Глава 2 61 ВВЕДЕНИЕ 61 В ПРОГРАММИРОВАНИЕ НА СИ 61 2.1.Структура и компоненты простой программы 61 2.2.Элементарные средства 71 программирования 71 2.3. Операторы цикла 92 2.4. Массивы и вложение 108 операторов цикла 108 2.5.Функции 123 2.6.Переключатели 135 Контрольные вопросы 139 Глава 3 140 ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА 140 3.1.Стадии и директивы препроцессорной обработки 141 HUB 143 3.2.Замены в тексте 145 3.3.Включение текстов из файлов 150 3.4.Условная компиляция 152 3.5.Макроподстановки средствами 157 препроцессора 157 3.6.Вспомогательные директивы 163 3.7.Встроенные макроимена 165 Контрольные вопросы 167 Глава 4 169 УКАЗАТЕЛИ, МАССИВЫ, СТРОКИ 169 4.1.Указатели на объекты 169 4.2.Указатели и массивы 178 4.3. Символьная информация и строки 193 Контрольные вопросы 201 Глава 5 204 ФУНКЦИИ 204 5.1. Общие сведения о функциях 204 5.2.Указатели в параметрах функций 209 5.3.Массивы и строки 214 как параметры функций 214 5.4.Указатели на функции 223 5.5.Функции с переменным 237 количеством аргументов 237 5.6.Рекурсивные функции 249 5.7.Классы памяти 252 и организация программ 252 5.8. Параметры функции main( ) 259 Контрольные вопросы 262 Глава 6 264 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ 264 6.1.Структурные типы и структуры 264 6.2.Структуры, массивы и указатели 278 6.3.Структуры и функции 289 6.4.Динамические информационные структуры 293 6.5.Объединения и битовые поля 300 Контрольные вопросы 309 Глава 7 312 ВВОД И ВЫВОД 312 7.1. Потоковый ввод-вывод 312 7.2. Ввод-вывод нижнего уровня 349 Контрольные вопросы 359 Глава 8 360 ПОДГОТОВКА И ВЫПОЛНЕНИЕ 360 ПРОГРАММ 360 8.1.Схема подготовки программ 360 8.2.Подготовка программ 362 в операционной системе UNIX 362 8.3. Утилита make 364 8.4. Библиотеки объектных модулей 368 Контрольные вопросы 375 Приложение 1 376 ТАБЛИЦЫ КОДОВ ASCII 376 HUB 381 Приложение 2 384 Константы предельных значений 384 Приложение 3 386 Стандартная библиотека функций языка Си 386 Приложение 4 397 МОДЕЛИ ПРЕДСТАВЛЕНИЯ 397 ЧИСЕЛ НА РАЗЛИЧНЫХ 397 КОМПЬЮТЕРНЫХ ПЛАТФОРМАХ 397 Литература 400 Предметный указатель 401 for( c=0.0, p=1.0, i=1; i <= n; i++ ) Содержание 3 ПРЕДИСЛОВИЕ 12 Глава 1 16 БАЗОВЫЕ ПОНЯТИЯ ЯЗЫКА 16 1.1.Алфавит, идентификаторы, служебные слова 17 1.2.Литералы 20 1.3.Переменные и именованные 27 константы 27 1.4. Операции 35 1.5. Разделители 44 1.6.Выражения 49 Контрольные вопросы 59 Глава 2 61 ВВЕДЕНИЕ 61 В ПРОГРАММИРОВАНИЕ НА СИ 61 2.1.Структура и компоненты простой программы 61 2.2.Элементарные средства 71 программирования 71 2.3. Операторы цикла 92 2.4. Массивы и вложение 108 операторов цикла 108 2.5.Функции 123 2.6.Переключатели 135 Контрольные вопросы 139 Глава 3 140 ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА 140 3.1.Стадии и директивы препроцессорной обработки 141 HUB 143 3.2.Замены в тексте 145 3.3.Включение текстов из файлов 150 3.4.Условная компиляция 152 3.5.Макроподстановки средствами 157 препроцессора 157 3.6.Вспомогательные директивы 163 3.7.Встроенные макроимена 165 Контрольные вопросы 167 Глава 4 169 УКАЗАТЕЛИ, МАССИВЫ, СТРОКИ 169 4.1.Указатели на объекты 169 4.2.Указатели и массивы 178 4.3. Символьная информация и строки 193 Контрольные вопросы 201 Глава 5 204 ФУНКЦИИ 204 5.1. Общие сведения о функциях 204 5.2.Указатели в параметрах функций 209 5.3.Массивы и строки 214 как параметры функций 214 5.4.Указатели на функции 223 5.5.Функции с переменным 237 количеством аргументов 237 5.6.Рекурсивные функции 249 5.7.Классы памяти 252 и организация программ 252 5.8. Параметры функции main( ) 259 Контрольные вопросы 262 Глава 6 264 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ 264 6.1.Структурные типы и структуры 264 6.2.Структуры, массивы и указатели 278 6.3.Структуры и функции 289 6.4.Динамические информационные структуры 293 6.5.Объединения и битовые поля 300 Контрольные вопросы 309 Глава 7 312 ВВОД И ВЫВОД 312 7.1. Потоковый ввод-вывод 312 7.2. Ввод-вывод нижнего уровня 349 Контрольные вопросы 359 Глава 8 360 ПОДГОТОВКА И ВЫПОЛНЕНИЕ 360 ПРОГРАММ 360 8.1.Схема подготовки программ 360 8.2.Подготовка программ 362 в операционной системе UNIX 362 8.3. Утилита make 364 8.4. Библиотеки объектных модулей 368 Контрольные вопросы 375 Приложение 1 376 ТАБЛИЦЫ КОДОВ ASCII 376 HUB 381 Приложение 2 384 Константы предельных значений 384 Приложение 3 386 Стандартная библиотека функций языка Си 386 Приложение 4 397 МОДЕЛИ ПРЕДСТАВЛЕНИЯ 397 ЧИСЕЛ НА РАЗЛИЧНЫХ 397 КОМПЬЮТЕРНЫХ ПЛАТФОРМАХ 397 Литература 400 Предметный указатель 401 printf("\n Сумма c=%f",c); } Для защиты от неверных исходных данных использован цикл (строки 9-15), в заголовке которого после while записано заведомо истинное выражение 1, то есть цикл может быть прерван только за счет выполнения операторов его тела. В строке 13 оператор break выполняется в случае истинности условия «n>0». При этом цикл заканчивается, и следует переход к оператору строки 16. Таким образом, сообщение об ошибке, выводимое функцией printf( ) из строки 14, печатается для каждого неположительного значения n. Вычисляя сумму ряда (строки 16-20), очередной его член получаем, умножая предыдущий на g (строка 18). Тем самым устранена необходимость явного возведения в степень. В выражении_1 оператора for формируются начальные значения переменных, изменяемых при выполнении цикла. В строках 18, 19 использованы составные операции присваивания. Приведем результаты выполнения программы:
Полученное значение суммы довольно трудно прочесть. По-види- мому, в этой задаче следует применять печать результата в экспоненциальной форме, то есть в printf( ) из строки 21 использовать спецификацию преобразования %е. При этом получится такой результат: Введите значение n=15 Сумма с=1.658167е+14. Оператор continue. Еще одну возможность влиять на выполнение операторов тела цикла обеспечивает оператор перехода к следующей итерации цикла continue (см. рис. 2.4). Оператор continue позволяет в любой точке тела цикла прервать текущую итерацию и перейти к проверке условий продолжения цикла, определенных в предложениях for или while. В соответствии с результатами проверки выполнение цикла либо заканчивается, либо начинается новая итерация. Оператор continue удобен, когда от итерации к итерации изменяется последовательность выполняемых операторов тела цикла, то есть когда тело цикла содержит ветвления. Рассмотрим пример. Суммирование положительных чисел. Вводя последовательность чисел, заканчивающуюся нулем, получить сумму и количество только положительных из них. Следующая программа решает эту задачу: #include /* Сумма положительных чисел */ void main( ) { double s,x; /*x — очередное число, s - сумма*/ int k; /*k - количество положительных */ printf("ХпВведите последоват. чисел c 0 в конце:\n"); for( x=1.0, s=0.0, k=0; x != 0.0; ) { scanf("%lf",&x); if( x <= 0.0 ) continue; k++; s+=x; } printf("\n Сумма=%Т, колич. положит.=%d",s,k); } Результат выполнения программы: Введите последовательность чисел с 0 в конце: 6 -3.0 14.0 -5 -4 10 0.0 Сумма=30.000000, колич. Положит.=3 Недостаток приведенной программы состоит в том, что нет защиты от неверно введенных данных. Например, не предусмотрены действия, когда в последовательности отсутствует нулевой элемент. 2.4. Массивы и вложение операторов цикла Массивы и переменные с индексами. Математическим понятием, которое привело к появлению в языках программирования понятия «массив», являются матрица и ее частные случаи: вектор-столбец или вектор-строка. Элементы матриц в математике принято обозначать с использованием индексов. Существенно, что все элементы матриц либо вещественные, либо целые и т. п. Такая «однородность» элементов свойственна и массиву, определение которого описывает тип элементов, имя массива и его размерность, то есть число индексов, необходимое для обозначения конкретного элемента. Кроме того, в определении указывается количество значений, принимаемых каждым индексом. Например, int a[10]; определяет массив из 10 элементов a[0], a[1], ..., a[9]. float z[13][[6]; определяет двумерный массив, первый индекс которого принимает 13 значений от 0 до 12, второй индекс принимает 6 значений от 0 до 5. Таким образом, элементы двумерного массива z можно перечислить так: Z[0][0], Z[0][1], Z[0][2],...,Z[12][4], Z[12][5] В соответствии с синтаксисом Си в языке существуют только одномерные массивы, однако элементами одномерного массива, в свою очередь, могут быть массивы. Поэтому двумерный массив определяется как массив массивов. Таким образом, в примере определен массив z из 13 элементов-массивов, каждый из которых, в свою очередь, состоит из 6 элементов типа float. Обратите внимание, что нумерация элементов любого массива всегда начинается с 0, то есть индекс изменяется от 0 до п-1, где n - количество значений индекса. Ограничений на размерность массивов, то есть на число индексов у его элементов, в языке Си теоретически нет. Стандарт языка Си требует, чтобы транслятор мог обрабатывать определения массивов с размерностью до 31. Однако чаще всего используются одномерные и двумерные массивы. Продемонстрируем на простых вычислительных задачах некоторые приемы работы с массивами. Вычисление среднего и дисперсии. Введя значение n из диапазона (0 /* Вычисление среднего и дисперсии */ #include void main ( ) { /*п — количество элементов */ int i,j,n; /*b — среднее, d — оценка дисперсии; */ float a, b, d,x[100],е; /*a,e — вспомогательные*/ while (1) Содержание 3 ПРЕДИСЛОВИЕ 12 Глава 1 16 БАЗОВЫЕ ПОНЯТИЯ ЯЗЫКА 16 1.1.Алфавит, идентификаторы, служебные слова 17 1.2.Литералы 20 1.3.Переменные и именованные 27 константы 27 1.4. Операции 35 1.5. Разделители 44 1.6.Выражения 49 Контрольные вопросы 59 Глава 2 61 ВВЕДЕНИЕ 61 В ПРОГРАММИРОВАНИЕ НА СИ 61 2.1.Структура и компоненты простой программы 61 2.2.Элементарные средства 71 программирования 71 2.3. Операторы цикла 92 2.4. Массивы и вложение 108 операторов цикла 108 2.5.Функции 123 2.6.Переключатели 135 Контрольные вопросы 139 Глава 3 140 ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА 140 3.1.Стадии и директивы препроцессорной обработки 141 HUB 143 3.2.Замены в тексте 145 3.3.Включение текстов из файлов 150 3.4.Условная компиляция 152 3.5.Макроподстановки средствами 157 препроцессора 157 3.6.Вспомогательные директивы 163 3.7.Встроенные макроимена 165 Контрольные вопросы 167 Глава 4 169 УКАЗАТЕЛИ, МАССИВЫ, СТРОКИ 169 4.1.Указатели на объекты 169 4.2.Указатели и массивы 178 4.3. Символьная информация и строки 193 Контрольные вопросы 201 Глава 5 204 ФУНКЦИИ 204 5.1. Общие сведения о функциях 204 5.2.Указатели в параметрах функций 209 5.3.Массивы и строки 214 как параметры функций 214 5.4.Указатели на функции 223 5.5.Функции с переменным 237 количеством аргументов 237 5.6.Рекурсивные функции 249 5.7.Классы памяти 252 и организация программ 252 5.8. Параметры функции main( ) 259 Контрольные вопросы 262 Глава 6 264 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ 264 6.1.Структурные типы и структуры 264 6.2.Структуры, массивы и указатели 278 6.3.Структуры и функции 289 6.4.Динамические информационные структуры 293 6.5.Объединения и битовые поля 300 Контрольные вопросы 309 Глава 7 312 ВВОД И ВЫВОД 312 7.1. Потоковый ввод-вывод 312 7.2. Ввод-вывод нижнего уровня 349 Контрольные вопросы 359 Глава 8 360 ПОДГОТОВКА И ВЫПОЛНЕНИЕ 360 ПРОГРАММ 360 8.1.Схема подготовки программ 360 8.2.Подготовка программ 362 в операционной системе UNIX 362 8.3. Утилита make 364 8.4. Библиотеки объектных модулей 368 Контрольные вопросы 375 Приложение 1 376 ТАБЛИЦЫ КОДОВ ASCII 376 HUB 381 Приложение 2 384 Константы предельных значений 384 Приложение 3 386 Стандартная библиотека функций языка Си 386 Приложение 4 397 МОДЕЛИ ПРЕДСТАВЛЕНИЯ 397 ЧИСЕЛ НА РАЗЛИЧНЫХ 397 КОМПЬЮТЕРНЫХ ПЛАТФОРМАХ 397 Литература 400 Предметный указатель 401 24 a=x[j]-b; 25 d+=a*a; 26 } /* Оценка дисперсии*/ 27 d/=n; 28 printf("\n Среднее =%f, дисперсия %f'", b, d); 29 } В программе определен (строка 6) массив x со 100 элементами, хотя в каждом конкретном случае используются только первые n из них. Ввод значения n сопровождается проверкой допустимости вводимого значения (строки 7-13). В качестве условия после while записано заведомо истинное выражение 1, поэтому выход из цикла (оператор break) возможен только при вводе правильного значения n, удовлетворяющего неравенству 0
Вложенные циклы. В теле цикла разрешены любые исполнимые операторы, в том числе и циклы, то есть можно конструировать вложенные циклы. В математике вложенным циклам соответствуют, например, кратные суммы или произведения. В качестве примера рассмотрим фрагмент программы для получения суммы такого вида: Введем следующие обозначения: a - двумерный массив, содержащий значения элементов матрицы; p - произведение элементов строки матрицы; c - сумма их значений; s - искомая сумма (результат). Опустив определения переменных и операторы ввода-вывода, запишем текст на языке Си: double a[10][5]; for( s=0.0,j=0; j<10; j++) { for( p=1.0,c=0.0,i=0; i<5; i++) { p*=a[j][i]; c+=a[j][i]; } s+=c+p; } При работе с вложенными циклами следует обратить внимание на правила выполнения операторов break и continue. Каждый из них действует только в том операторе, в теле которого он непосредственно использован. Оператор break прекращает выполнение ближайшего внешнего для него оператора цикла. Оператор continue передает управление на ближайшую внешнюю проверку условия продолжения цикла. Для иллюстрации рассмотрим фрагмент другой программы для вычисления суммы произведений элементов строк той же матрицы: 1 double a[10][5]; 2 for (j=0,s=0.0; j<10; j++) { for (i=0,p=1.0; i<5; i++) { if (a[j][i] == 0.0) break; p*=a[j][i]; Содержание 3 ПРЕДИСЛОВИЕ 12 Глава 1 16 БАЗОВЫЕ ПОНЯТИЯ ЯЗЫКА 16 1.1.Алфавит, идентификаторы, служебные слова 17 1.2.Литералы 20 1.3.Переменные и именованные 27 константы 27 1.4. Операции 35 1.5. Разделители 44 1.6.Выражения 49 Контрольные вопросы 59 Глава 2 61 ВВЕДЕНИЕ 61 В ПРОГРАММИРОВАНИЕ НА СИ 61 2.1.Структура и компоненты простой программы 61 2.2.Элементарные средства 71 программирования 71 2.3. Операторы цикла 92 2.4. Массивы и вложение 108 операторов цикла 108 2.5.Функции 123 2.6.Переключатели 135 Контрольные вопросы 139 Глава 3 140 ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА 140 3.1.Стадии и директивы препроцессорной обработки 141 HUB 143 3.2.Замены в тексте 145 3.3.Включение текстов из файлов 150 3.4.Условная компиляция 152 3.5.Макроподстановки средствами 157 препроцессора 157 3.6.Вспомогательные директивы 163 3.7.Встроенные макроимена 165 Контрольные вопросы 167 Глава 4 169 УКАЗАТЕЛИ, МАССИВЫ, СТРОКИ 169 4.1.Указатели на объекты 169 4.2.Указатели и массивы 178 4.3. Символьная информация и строки 193 Контрольные вопросы 201 Глава 5 204 ФУНКЦИИ 204 5.1. Общие сведения о функциях 204 5.2.Указатели в параметрах функций 209 5.3.Массивы и строки 214 как параметры функций 214 5.4.Указатели на функции 223 5.5.Функции с переменным 237 количеством аргументов 237 5.6.Рекурсивные функции 249 5.7.Классы памяти 252 и организация программ 252 5.8. Параметры функции main( ) 259 Контрольные вопросы 262 Глава 6 264 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ 264 6.1.Структурные типы и структуры 264 6.2.Структуры, массивы и указатели 278 6.3.Структуры и функции 289 6.4.Динамические информационные структуры 293 6.5.Объединения и битовые поля 300 Контрольные вопросы 309 Глава 7 312 ВВОД И ВЫВОД 312 7.1. Потоковый ввод-вывод 312 7.2. Ввод-вывод нижнего уровня 349 Контрольные вопросы 359 Глава 8 360 ПОДГОТОВКА И ВЫПОЛНЕНИЕ 360 ПРОГРАММ 360 8.1.Схема подготовки программ 360 8.2.Подготовка программ 362 в операционной системе UNIX 362 8.3. Утилита make 364 8.4. Библиотеки объектных модулей 368 Контрольные вопросы 375 Приложение 1 376 ТАБЛИЦЫ КОДОВ ASCII 376 HUB 381 Приложение 2 384 Константы предельных значений 384 Приложение 3 386 Стандартная библиотека функций языка Си 386 Приложение 4 397 МОДЕЛИ ПРЕДСТАВЛЕНИЯ 397 ЧИСЕЛ НА РАЗЛИЧНЫХ 397 КОМПЬЮТЕРНЫХ ПЛАТФОРМАХ 397 Литература 400 Предметный указатель 401 Внутренний цикл по i прерывается, если (строка 6) обнаруживается нулевой элемент матрицы. В этом случае произведение элементов столбца заведомо равно нулю, и его не нужно вычислять. Во внешнем цикле (строка 9) проверяется значение i. Если i<5, то есть элемент a[j][i] оказался нулевым, то оператор continue передает управление на ближайший оператор цикла (строка 4), и, таким образом, не происходит увеличение s (строка 10) на величину «недосчитанного» значения p. Если внутренний цикл завершен естественно, то i равно 5 и оператор continue не может выполняться. Упорядочение в одномерных массивах. Задаче упорядочения или сортировки посвящены многочисленные работы математиков и программистов. Для демонстрации некоторых особенностей вложения циклов и работы с массивами рассмотрим простейшие алгоритмы сортировки. Необходимо, введя значение переменной 1 /* Упорядочение элементов массива */ #include main( ) { int n,i,j; double a[100],b; while(1) { printf("\n Введите количество элементов n="); scanf("%d",&n); if (n > 1 && n <= 100) break; printf("Ошибка! Необходимо 1 } printf("\n Введите значения элементов " "массива:\n"); for(j=0; j { printf("a[%d]=", j+1); scanf("%lf",&a[j]); } for(i=0; i for(j=i+1; j if(a[i]>a[j]) { b=a[i]; a[i]=a[j]; a[j]=b; } printf("\n Упорядоченный массив: \n"); for(j=0; j printf("a[%d]=%f\n",j+1,a[j]); } Результаты выполнения программы: Введите количество элементов n=-15 Введите количество элементов n=3 Введите значения элементов массива: a[1] = 88.8 a[2] = -3.3 a[3] = 0.11 Упорядоченный массив: Содержание 3 ПРЕДИСЛОВИЕ 12 Глава 1 16 БАЗОВЫЕ ПОНЯТИЯ ЯЗЫКА 16 1.1.Алфавит, идентификаторы, служебные слова 17 1.2.Литералы 20 1.3.Переменные и именованные 27 константы 27 1.4. Операции 35 1.5. Разделители 44 1.6.Выражения 49 Контрольные вопросы 59 Глава 2 61 ВВЕДЕНИЕ 61 В ПРОГРАММИРОВАНИЕ НА СИ 61 2.1.Структура и компоненты простой программы 61 2.2.Элементарные средства 71 программирования 71 2.3. Операторы цикла 92 2.4. Массивы и вложение 108 операторов цикла 108 2.5.Функции 123 2.6.Переключатели 135 Контрольные вопросы 139 Глава 3 140 ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА 140 3.1.Стадии и директивы препроцессорной обработки 141 HUB 143 3.2.Замены в тексте 145 3.3.Включение текстов из файлов 150 3.4.Условная компиляция 152 3.5.Макроподстановки средствами 157 препроцессора 157 3.6.Вспомогательные директивы 163 3.7.Встроенные макроимена 165 Контрольные вопросы 167 Глава 4 169 УКАЗАТЕЛИ, МАССИВЫ, СТРОКИ 169 4.1.Указатели на объекты 169 4.2.Указатели и массивы 178 4.3. Символьная информация и строки 193 Контрольные вопросы 201 Глава 5 204 ФУНКЦИИ 204 5.1. Общие сведения о функциях 204 5.2.Указатели в параметрах функций 209 5.3.Массивы и строки 214 как параметры функций 214 5.4.Указатели на функции 223 5.5.Функции с переменным 237 количеством аргументов 237 5.6.Рекурсивные функции 249 5.7.Классы памяти 252 и организация программ 252 5.8. Параметры функции main( ) 259 Контрольные вопросы 262 Глава 6 264 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ 264 6.1.Структурные типы и структуры 264 6.2.Структуры, массивы и указатели 278 6.3.Структуры и функции 289 6.4.Динамические информационные структуры 293 6.5.Объединения и битовые поля 300 Контрольные вопросы 309 Глава 7 312 ВВОД И ВЫВОД 312 7.1. Потоковый ввод-вывод 312 7.2. Ввод-вывод нижнего уровня 349 Контрольные вопросы 359 Глава 8 360 ПОДГОТОВКА И ВЫПОЛНЕНИЕ 360 ПРОГРАММ 360 8.1.Схема подготовки программ 360 8.2.Подготовка программ 362 в операционной системе UNIX 362 8.3. Утилита make 364 8.4. Библиотеки объектных модулей 368 Контрольные вопросы 375 Приложение 1 376 ТАБЛИЦЫ КОДОВ ASCII 376 HUB 381 Приложение 2 384 Константы предельных значений 384 Приложение 3 386 Стандартная библиотека функций языка Си 386 Приложение 4 397 МОДЕЛИ ПРЕДСТАВЛЕНИЯ 397 ЧИСЕЛ НА РАЗЛИЧНЫХ 397 КОМПЬЮТЕРНЫХ ПЛАТФОРМАХ 397 Литература 400 Предметный указатель 401 Обратите внимание, что при заполнении массива и при печати результатов его упорядочения индексация элементов выполнена от 1 до n, как это обычно принято в математике. В программе на Си это соответствует изменению индекса от 0 до (n-1). В программе реализован алгоритм прямого упорядочения - каждый элемент a[i], начиная с a[0] и заканчивая a[n-2], сравнивается со всеми последующими, и на место a[i] выбирается минимальный. Таким образом, a[0] принимает минимальное значение, a[1] - минимальное из оставшихся и т. д. Недостаток этого алгоритма состоит в том, что в нем фиксированное число сравнений, независимое от исходного расположения значений элементов. Даже для уже упорядоченного массива придется выполнить то же самое количество итераций (n-1)*n/2, так как условия окончания циклов не связаны со свойствами, то есть с размещением элементов массива. Алгоритм попарного сравнения соседних элементов позволяет в ряде случаев уменьшить количество итераций при упорядочении. В цикле от 0 до n-2 каждый элемент a[i] массива сравнивается с последующим a[i+1] (0a[i+1], то значения этих элементов меняются местами. Упорядочение заканчивается, если оказалось, что a[i] не больше a[i+1] для всех i. Пусть k - количество перестановок при очередном просмотре. Тогда упорядочение можно осуществить с помощью такой последовательности операторов: do { for (i=0,k=0; i b=a[i]; a[i]=a[i+1]; a[i+1]=b; k=k+1; } n--; } while( k > 0 ); Здесь количество повторений внешнего цикла зависит от исходного расположения значений элементов массива. После первого завершения внутреннего цикла элемент a[n-1] становится максимальным. После второго окончания внутреннего цикла на место a[n-2] выбирается максимальный из оставшихся элементов и т. д. Таким образом, после j-го выполнения внутреннего цикла элементы a[n-j], ...,a[n-1] уже упорядочены, и следующий внутренний цикл достаточно выполнить только для 0 В случае упорядоченности исходного массива внешний цикл повторяется только один раз, при этом выполняется (n-1) сравнений, k остается равным 0. Для случая, когда исходный массив упорядочен по убыванию, количество итераций внешнего цикла равно (n-1), а внутренний цикл последовательно выполняется (n-1)*n/2 раз. Имеется возможность улучшить и данный вариант алгоритма упорядочения (см., например, Кнут Д. Искусство программирования. Т. 3: Сортировка и поиск. - 2-е изд. - М.: Вильямс, 2007), однако рассмотренных примеров вполне достаточно для знакомства с особенностями применения массивов и индексированных переменных. Инициализация массивов. При определении массивов возможна их инициализация, то есть присваивание начальных значений их элементам. По существу (точнее, по результату), инициализация - это объединение определения объекта с одновременным присваиванием ему конкретного значения. Использование инициализации позволяет изменить формат определения массива. Например, можно явно не указывать количество элементов одномерного массива, а только перечислить их начальные значения в списке инициализации: double d[ ]={1.0, 2.0, 3.0, 4.0, 5.0}; В данном примере длину массива компилятор вычисляет по количеству начальных значений, перечисленных в фигурных скобках. После такого определения элемент d[0] равен 1.0, d[1] равен 2.0 и т. д. до d[4], который равен 5.0. Если в определении массива явно указан его размер, то количество начальных значений не может быть больше количества элементов в массиве. Если количество начальных значений меньше, чем объявленная длина массива, то начальные значения получат только первые элементы массива (с меньшими значениями индекса): int m[8]={8,4,2}; В данном примере определены значения только переменных m[0], m[1] и m[2], равные соответственно 8, 4 и 2. Элементы m[3], ..., m[7] не инициализируются. Правила инициализации многомерных массивов соответствуют определению многомерного массива как одномерного, элементами которого служат массивы, размерность которых на единицу меньше, чем у исходного массива. Одномерный массив инициализируется заключенным в фигурные скобки списком начальных значений. В свою очередь, начальное значение, если оно относится к массиву, также представляет собой заключенный в фигурные скобки список начальных значений. Например, присвоить начальные значения вещественным элементам двумерного массива a, состоящего из трех «строк» и двух «столбцов», можно следующим образом: double a[3][2]={{10,20}, {30,40}, {50,60}}; Эта запись эквивалентна последовательности операторов присваивания: a[0][0]=10; a[0][1]=20; a[1][0]=30; a[1][1]=40; a[2][0]=50; a[2][1]=60;. Тот же результат можно получить с одним списком инициализации: double a[3][2]={10,20,30,40,50,60}; С помощью инициализации можно присваивать значения не всем элементам многомерного массива. Например, чтобы инициализировать только элементы первого столбца матрицы, ее можно описать так: double z[4][6]={{1}, {2}, {3}, {4}}; Следующее описание формирует «треугольную» матрицу в целочисленном массиве из 5 строк и 4 столбцов: int x[5][4]={{1}, {2,3}, {4,5,6}, {7,8,9,10} }; В данном примере последняя, пятая строка x[4] остается незаполненной. Первые три строки заполнены не до конца. Схема размещения элементов массива изображена на рис. 2.5. Рис. 2.5. Схема «треугольного» заполнения матрицы Функции Определение функций. Как уже было отмечено, каждая программа на языке Си - это совокупность функций. В определении функции указываются последовательность действий, выполняемых при обращении к функции, имя функции, тип результата (возвращаемого значения) и совокупность параметров, заменяемых при обращении к функции аргументами. Действия, выполняемые при обращении к функции, задает ее тело - составной оператор (блок), обязательным элементом которого служат внешние фигурные скобки { }. Имя функции, тип результата, совокупность параметров и их свойства задают заголовок функции. В этой главе будем рассматривать функции, возвращающие значения целого или вещественного типа. Таким образом, типом результата может быть char, int, long, float, double или long double. Могут быть добавлены signed и unsigned. Если тип результата не указан, то по умолчанию предполагается целый тип int. Допустимы функции, не возвращающие результата. В этом случае для них должен быть использован тип void. Имя неглавной функции - это произвольно выбираемый идентификатор. Имя функции не должно совпадать со служебными словами, именами библиотечных функций и с другими именами в программе. Список параметров - набор идентификаторов, отделяемых друг от друга запятыми. Спецификация параметров определяет их свойства и во многом подобна определениям и описаниям. В данной главе будем считать, что параметр может быть специфицирован либо как простая переменная целого или вещественного типа, либо как одномерный массив (целый или вещественный). Структура определения функции: тип_результата имя_функции (спецификация_параметров) { определения_объектов; исполняемые_операторы; } Пример функции: double f (int a, float b, double d) {/*тело функции*/} Принципиально важным оператором тела функции является оператор возврата из функции в точку ее вызова: return выражение; или return; Выражение в операторе возврата задает возвращаемое функцией значение. Для функции типа void, не возвращающей никакого значения, выражение в операторе return отсутствует. В теле такой функции оператор return может вообще отсутствовать. В этом случае компилятор предполагает, что оператор return находится в самом конце тела функции. Применение оператора return допустимо и в функции main( ). Если программист явно не поместил в функцию main( ) оператор return, то компилятор поместит его в конце текста функции main( ). В отличие от «неглавных» функций, откуда возврат выполняется в вызывающую функцию, выполнение оператора return; или return выражение; в функции main( ) приводит к завершению программы. Управление при таком выходе передается вызывающей программе, например операционной системе, которая может анализировать значение выражения, использованного в операторе возврата. Приведем примеры определения функций и проиллюстрируем некоторые их особенности. Функция для вычисления объема цилиндра. Пусть у функции имеются два параметра, значение большего из которых считается радиусом цилиндра, а меньший определяет значение высоты цилиндра. Пусть g и h - параметры; тогда объем цилиндра равен g*g*h*PI, если g>h, или g*h*h*PI, если g |