
- •Экзаменационные вопросы по дисциплине
- •«Программирование на языках высокого уровня»
- •Среда программирования языка Си.
- •Алфавит языка.
- •Данные и типы данных в Си.
- •Int (целый);
- •Константы и переменные.
- •Перечень операций в Си. Приоритет операций.
- •Структура программы.
- •Int scanf(char *управляющая строка);
- •Массивы в Си.
- •Массивы указателей. Массивы динамической памяти.
- •Представление символа и строки в памяти эвм. Ввод-вывод символов и строк.
- •Понятие функции в Си. Определение и описание. Вызов функции.
- •Передача параметров функции по значению.
- •Передача параметров функции по ссылке.
- •Рекурсивные функции.
- •Определение структур. Инициализация и присваивание структур.
- •Доступ к элементам структур
- •Двоичный режим обмена с файлами. Строковый обмен с файлами.
- •Использование макросов в Си.
Массивы в Си.
Как известно, массив - это конечная совокупность данных одного типа. Можно говорить о массивах целых чисел, массивов символов и.т.д. Мы можем даже определить масссив, элементы которого - массивы( массив массивов), определяя, таким образм, многомерные массивы. Любой массив в программе должен быть описан: после имени массива добаляют квадратные скобки [], внутри которых обычно стоит число, показывающее количество элементов массива. Например, запись int x[10]; определяет x как массив из 10 целых чисел. В случае многомерных массивов показывают столько пар скобок , какова размерность массива, а число внутри скобок показывает размер массива по данному измерению. Например, описание двумерного массива выглядит так: int a[2][5];. Такое описание можно трактовать как матрицу из 2 строк и 5 столбцов. Для обрщения к некоторому элементу массива указывают его имя и индекс, заключенный в квадратные скобки(для многомерног массива - несколько индексов , заключенные в отдельные квадратные скобки): a[1][3], x[i] a[0][k+2]. Индексы массива в Си всегда начинаются с 0, а не с 1, т.е. описание int x[5]; порождает элементы x[0], x[1], x[2], x[3], x[4], x[5]. Индекс может быть не только целой константой или целой переменной, но и любым выражением целого типа. Переменная с индексами в программе используется наравне с простой переменной (например, в операторе присваивания, в функциях ввода- вывода). Начальные значения массивам в языке Си могут быть присвоены при компиляции только в том случае, если они объявлены с классом памяти extern или static, например:
static int a[6]={5,0,4,-17,49,1};
обеспечивает присвоения a[0]=5; a[1]=0; a[2]=4 ... a[5]=1. Как видите, для начального присвоения значений некоторому массиву надо в описании поместить справа от знака = список инициирующих значений, заключенные в фигурные скобки и разделенные запятыми. Двумерный массив можно инициировать так:
static int matr[2][5] = {{3,4,0,1,2},{6,5,1,4,9}};
Матрица хранится в памяти построчно, т.е. самый правый индекс в наборе индексов массива меняется наиболее быстро.
Пусть, например, в заданном массиве из 10 целых чисел надо изменить порядок следования его элементов на обратный без привлечения вспомогательного массива.
Инициализация массивов - это умение присваивать элементам массива некоторые начальные значения. В Си для этих целей предусмотрены некоторые специальные возможности. Самый простой спосб инициализации состоит в том, что при объвлении массива в фигурных скобках указывается список конкретных значений элементов массива. Их, то есть конкретные значения элементов массива, называют инициализаторами.
Например:
Одномерный массив семи вещественных чисел - инициализаторов: 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, обозначенный как float bonn[i] (где i=0, ..., 6), можно инициализировать так: float bonn[7]={1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7}; Это же самое можно записать, используя обычные операторы присвоения: bonn[0]=1.1; bonn[1]=2.2; bonn[2]=3.3; bonn[3]=4.4; bonn[4]=5.5; bonn[5]=6.6; bonn[7]=7.7. Этими спобобами Вы можете задавать начальные значения элементам массива, иначе говоря, так можно вводить массив в память компьютера в Си.
Двумерный массив целочисленных элементов - инициализаторов: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, обозначенный как int s[i][j] (где i=0, 2, ..., 3; j=0, 2, ..., 4), можно инициализировать как: int s[4][5]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}. По аналогии с первым случаем это соответствует набору следующих операторов присвоения:
int s[0][0]=1; int s[0][1]=2; int s[0][2]=3; int s[0][3]=4; int s[0][4]=5;
int s[1][0]=6; int s[1][1]=7; int s[1][2]=8; int s[1][3]=9; int s[1][4]=10;
int s[2][0]=11; int s[2][1]=12; int s[2][2]=13; int s[2][3]=14; int s[2][4]=15;
int s[3][0]=16; int s[3][1]=17; int s[3][2]=18; int s[3][3]=19; int s[3][4]=20;
Вообще многомерные массивы, в том числе и двумерные, можно инициализировать как массив массивов. Например, две следующие инициализации равны между собой:
int s[3][5]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; и
int s[3][5]={{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};
Во втором случае авторы ввели дополнительные фигурные скобки для записи элементов каждой строки двумерного массива. Если при этом количество элементов в строке не совпадает с числом столбцов в массиве, то соответствующие пропущенные элементы строки считаются неопределенными, так как они не определены.
Символьные массивы могут инициализироваться как обычный массив
Например: char srt[15]={'B', 'o', 'r', 'l', 'a', 'n', 'd', ' ', 'C', '+', '+'} или могут вводиться как строка символов char str[15]='Borland C++'
Отличие этих способов состоит в том, что во втором способе будет добавлен еще и нулевой байт. К тому же второй способ по количеству используемых символов значительно короче.
Допускается так же объявление и инициализация массивов без явного указания размера массива. Например, обычно Вы должны знать количество символов в строке или указать заведомо большой размер массива
char str[80]='Уроки программирования на Си'. При инициализации массива без указания его размера Вы делаете это так:
char str[ ]='Уроки программирования на Си'. Компилятор Си сам определит необходимое количество элементов массива, включая и нулевой байт. Можно определять таким способом массивы любого типа, в том числе и многомерные массивы.
Например:
int mass[]={1, 2, 3, 4, 5};
При объявлении массивов с неизвестным количеством элементов можно не указывать размер только в самых левых квадратных скобках:
int arr[][3]={1, 2, 3,
5, 6, 7,
8, 9, 0};
Упорядочение в одномерных массивах.
Адреса и указатели. Операции над указателями. Индексирование массива.
В языке C массивы и указатели тесно связаны друг с другом. Например, когда объявляется массив в виде int a[25], то при этом не только выделяется память для 25 элементов массива, но и формируется указатель с именем a, значение которого равно адресу первого по счету (нулевого) элемента массива. Доступ к элементам массива может осуществляться через указатель с именем a. С точки зрения синтаксиса языка указатель a является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя.
Поскольку имя массива является указателем-константой, допустимо, например, такое присваивание:
int a[25];
int *ptr;
ptr=a;
В этом примере в переменную-указатель ptr записывается адрес начала массива a, т. е. адрес первого элемента массива.
Также справедливы следующие соотношения: например, имеется массив a[N], тогда истинными будут следующие сравнения:
a==&a[0];
*a==a[0].
Указатели можно увеличивать или уменьшать на целое число:
ptr=a+1;
Теперь указатель ptr будет указывать на второй элемент массива a, что эквивалентно &a[1].
При увеличении указателя на единицу адрес, который он представляет, увеличивается на размер объекта связанного с ним типа, например:
int a[25];
int *ptr=a;
ptr+=3;
Первоначально указатель ptr указывал на начало массива a. После прибавления к переменной ptr числа 3 значение указателя увеличилось на 3*sizeof(int), а указатель ptr теперь будет указывать на четвертый элемент массива a. Указатель можно индексировать точно так же, как и массив. На самом деле компилятор преобразует индексацию в арифметику указателей, например, ptr[3]=10 представляется как *(ptr+3)=10.
К указателям типа void арифметические операции применять нельзя, так как им не ставится в соответствие размер области памяти.
Таким образом, в языке C для доступа к элементам массива существует два различных способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, a[7]=3 или a[i+2]=5. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Первое из этих выражений должно быть указателем, а второе – выражением целого типа. Указатель, используемый в индексном выражении, не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная-указатель. В частности, после выполнения присваивания ptr=a доступ к седьмому элементу массива можно получить как с помощью константы-указателя a в форме a[7], так и переменной-указателя ptr в форме ptr[7].
Второй способ доступа к элементам массива связан с использованием адресных выражений и операции косвенной адресации в форме *(a+3)=10 или *(a+i+2)=5.
При реализации на компьютере первый способ приводится ко второму, т. е. индексное выражение приводится к адресному. Для приведенных примеров обращение к элементу массива a[3] преобразуется в *(a+3).
Для доступа к начальному элементу массива, т. е. к элементу с нулевым индексом, можно использовать просто значение указателя a или ptr, поэтому любое из присваиваний
*a=2;
a[0]=2;
*(a+0)=2;
*ptr=2;
ptr[0]=2;
*(ptr+0)=2;
присваивает начальному элементу массива значение 2.
Многомерные массивы в языке C – это массивы массивов, т. е. массивы, элементами которых, в свою очередь, являются массивы. При объявлении таких массивов в памяти компьютера создается несколько различных объектов. Например, при выполнении объявления двумерного массива int a2[4][3] в программе создается указатель a2, который определяет в памяти местоположение первого элемента массива и, кроме того, является указателем на массив из четырех указателей. Каждый из этих четырех указателей содержит адрес одномерного массива, представляющего собой строку двумерного массива и состоящего из трех элементов типа int, и позволяет обратиться к соответствующей строке массива.
Таким образом, объявление a2[4][3] порождает в программе три разных объекта: указатель с идентификатором a2, безымянный массив из четырех указателей и безымянный массив из двенадцати чисел типа int. Для доступа к безымянным массивам используются адресные выражения с указателем a2. Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме a2[2] или *(a2+2). Для доступа к элементам двумерного массива чисел типа int должны быть использованы два индексных выражения в форме a2[1][2] или эквивалентных ей *(*(a2+1)+2) и (*(a2+1))[2]. Следует учитывать, что с точки зрения синтаксиса языка C указатель a2 и указатели a2[0], a2[1], a2[2], a2[3] являются константами, и их значения нельзя изменять во время выполнения программы.
Размещение трехмерного массива происходит аналогично. Так, например, объявление float a3[3][4][5] порождает в программе, кроме самого трехмерного массива из 60 чисел типа float, массив из четырех указателей на тип float, массив из трех указателей на массив указателей на float и указатель на массив массивов указателей на float.
При размещении элементов многомерных массивов они располагаются в памяти подряд по строкам, т. е. быстрее всего изменяется последний индекс, а медленнее – первый. Такой порядок дает возможность обращаться к любому элементу многомерного массива, используя адрес его начального элемента и только одно индексное выражение.
Например, обращение к элементу a2[1][2] можно осуществить при помощи указателя ptr2, объявленного в форме int *ptr2=a2[0], как обращение ptr2[1×3+2] (здесь 1 и 2 – это индексы используемого элемента, а 3 – число элементов в строке) или как ptr2[5]. Заметим, что внешне похожее обращение a2[6] выполнить невозможно, так как указателя с индексом 6 не существует.
Для обращения к элементу a3[2][3][4] из трехмерного массива тоже можно использовать указатель, описанный как float *ptr3=a3[0][0], с одним индексным выражением в форме ptr3[2×20+3×5+4] или ptr3[59].