|
5.2. Массивы и строки.
До сих пор мы рассматривали только переменные простых (скалярных) типов: int, long, float, char и т.д. сейчас впервые рассмотрим, как в Си используются массивы. Массивы – это представители структурированных типов данных, к которому так же относятся записи и файлы. Массив состоит из нескольких элементов одного и того же типа. Ко всему массиву можно обращаться по имени. Кроме того, можно использовать любой элемент массива, если знать его индекс, который указывает на его относительную позицию в массиве. Число элементов массива задаётся при его объявлении и в дальнейшем не меняется. К любому элементу объявленного массива можно добраться следующим образом: указать имя массива и индекс элемента в квадратных скобках. В Си массивы объявляются так же, как и переменные. Давайте рассмотрим для сравнения как объявляются массивы на Паскале, и на Си.
Как видно в языке Паскаль возможны две формы описания табличных величин. Вторая форма удобна в том случае, если в процессе решения задачи, возникает необходимость использовать несколько массивов одного и того же типа и формата. При объявлении массива в языке Паскаль, индексация элементов начинается от первого указанного индекса. Например: a[1]…a[100]. Однако имеет смысл подробней рассмотреть описание на Си. В первой строке объявлен массив из 100 элементов целого типа. Надо заметить, что здесь индексация всегда начинается от 0: a[0], a[1], … a[99]. Во второй строке объявлен массив типа char, и в третьей – float. Если на Паскале при объявлении двумерного массива используют запись a:array [1..10,1..20] of char;, то на Си объявление такого массива будет выглядеть так: char a[10][20]. При работе с массивом можно установить и большее число измерений. Как уже известно, элементы двухмерного массива хранятся по строкам, т.е. если проходить по строкам в порядке их расположения в памяти, то быстрее всего изменяется крайний правый индекс. Например: обращение к девятому элементу пятой строки запишется так: a[5][9]. В языке Си существует сильная взаимосвязь между указателями и массивами. Любое действие, которое достигается индексированием массива, может быть выполнено также с помощью указателей, причём быстрее. Объявление int a[5]; определяет массив из 5 элементов: a[0], a[1], a[2], a[3], a[4]. Если объект *y объявлен как int *y;, то оператор y=&a[0]; присвоит переменной y адрес элемента a[0]. Если переменная y указывает на очередной элемент массива, то y+1 указывает на следующий элемент, здесь выполняется соответствующее масштабирование для приращения адреса с учётом длины объекта (для типа int – 2 байта, long – 4 байта и т.п.). Т.к. само имя массива есть адрес, его нулевого элемента, то инструкцию y=&a[0]; можно записать в виде: y=a;. Тогда элемент a[i] представим как *(a+i). Если же y – указатель, то следующие записи: y[i] и *(y+i) – эквивалентны. Таким образом, любой массив и индексное выражение можно представить посредством указателей. В тоже время, между именем массива и соответствующим указателем есть одно отличие. Указатель – это переменная и y=a; или y++; - допустимые операции. Имя же массива – константа. Поэтому конструкции вида a=y; a++; z=&a; использовать нельзя, т.к. значение константы не может быть изменено. При адресации элементов одного массива, указатели можно сравнивать. Но нельзя сравнивать, либо применять в арифметических операциях, указатели на разные массивы. Также допускается проверка элементов массива на равенство или неравенство со значением NULL, которое записывается вместо нуля. Теперь рассмотрим программы использования массивов, на языках Паскаль и Си.
В данных программах описаны таблица символьных величин, которые выводят элементы массива в обратном порядке. Предположим, что в качестве ввода введена строка абвгдежзий, тогда результатом работы наших программ будет строка йизжедгвба. Кстати говоря, вместо букв, может быть введена строка чисел: 9876543210. Результатом выполнения будет обратная строка чисел. Обратите внимание, что в обеих программах, строка символов вводится целиком, без пробелов. Предположим, что требуется ввести строку из десяти целых чисел, которые надо упорядочить так, чтобы любое правое число было не меньше левого. Такую строку представим в виде одномерного массива m, из 10-и элементов. Попробуем выполнить эту сортировку методом “пузырька”, когда при переборе элементов массива, больший по значению элемент “всплывает” в конец массива.
Как видно, решения этой задачи на Паскале и Си, по своей структуре, очень похожи. Существенным отличием является, то, что для описания массива, на Си, не требуется никаких дополнительных записей. Замечание! В языке Си существует сильная взаимосвязь между указателями и массивами. В языке Си допускаются массивы указателей. |