Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_СП_2004_1_00.doc
Скачиваний:
69
Добавлен:
04.11.2018
Размер:
882.69 Кб
Скачать

Лекция 3

Массивы переменные как однородные статические структуры данных. Строки символов. Инициализация переменных и массивов. Управляющие конструкции языка Си: синтаксис и семантика.

$ 1. Массивы переменных как однородные статические структуры данных

В начале предыдущей лекции мы познакомились с основными типами данных языка Си и правилами описания переменных в программах. Однако до сих пор нам приходилось иметь дело лишь с простыми переменными, являющимися носителями одного единственного значения, будь то число или внутреннее машинное представление некоторого символа ASCII. Однако при решении на ЭВМ большинства практических задач приходится иметь дело с наборами данных, представимых в виде векторов, таблиц, строк или абстрактных множеств с неупорядоченной структурой. Для размещения перечисленных объектов в памяти ЭВМ аппарат простых переменных оказывается явно недостаточным, приводя к неоправданной громоздкости и логической сложности программ. Наиболее простой логической структурой данных является ограниченный вектор элементов фиксированного типа. Элементы вектора считаются занумерованными последовательно отрезком ряда натуральных чисел и доступ к каждому из них может осуществляться по его индивидуальному номеру. Простота подобных структур данных состоит в том, что они самым естественным образом отображаются на линейную структуру памяти ЭВМ.

Структурным аналогом векторов в языке Си (как и в большинстве других языков программирования) являются массивы переменных, т.е. упорядоченные последовательности элементов данных одного типа. С каждым таким массивом связывается его имя, тип элементов (а следовательно и объем машинной памяти, требуемой для размещения одного элемента) и их количество (т.е. длина массива). Для описания массивов в Си-программах используются инструкции, подобные тем, которые были введены для описания простых переменных. Различие состоит лишь в том, что теперь эти инструкции должны содержать информацию о длине массива и в общем случае имеют следующий формат:

<sc-specifier> type-specifier identifier[const-expression] <, ... >;

где sc-specifier есть описатель класса памяти (см. Лекцию 7, $ 2);

type-specifier - имя типа данных, которому принадлежат элементы массива;

identifier - имя переменной, объявляемой массивом;

const-expression - константное арифметическое выражение, определяющее количество элементов в массиве (т.е. его длину). Например, инструкции

int f[10];

char b[5];

определяют два массива: массив f, состоящий из десяти элементов типа int, и массив символов b, длина которого равна пяти. Для обращения в программе к индивидуальному элементу всякого массива следует указывать его имя и порядковый номер, заключенный в квадратные скобки:

c = 2*f[5] + 4;

причем последние в данном случае рассматриваются как символ операции взятия элемента, имеющей максимально высокий приоритет. Важно заметить, что компилятор языка Си нумерует элементы массивов, начиная с нуля (а не с единицы, как это принято во многих языках программирования). Поэтому в приведенном выше примере одним из операндов арифметического выражения в правой части является шестой (а не пятый!) элемент массива f. Последний же элемент этого массива должен индексироваться числом 9. В общем случае порядковые номера элементов могут задаваться произвольными арифметическими выражениями целого типа, которые будем называть индексными выражениями. Язык Си не обеспечивает возможности работы с массивами переменных как с единым целым: в качестве операндов выражений могут выступать лишь отдельные элементы. Однако ссылка на имя массива без следующего за ним индекса элемента все же имеет определенный смысл, поскольку отождествляется с адресом размещения в памяти самого первого элемента этого массива. Подробный разговор об использовании адресов и адресной арифметике пойдет в следующей лекции.

$ 2. Строки символов

В $ 3 предыдущей лекции, посвященном рассмотрению констант в языке Си, мы уже познакомились с понятием символьной строки как последовательности, состоящей из одного или более символов ASCII. Теперь нам предстоит обсудить вопрос о размещении строк в памяти ЭВМ и об их использовании в программах. Дело в том, что в языке Си нет специального типа, который можно было бы использовать для описания строк. Вместо этого они представляются в виде массивов элементов типа char. Такое решение проблемы означает, что символы строки располагаются в соседних ячейках памяти - по одному символу в ячейке. В то же время, столь упрощенное представление о строках несколько затрудняет рактическую работу с ними, поскольку в большинстве случаев строки интересуют нас как целостные в логическом отношении единицы информации, а не как наборы символов, из которых они состоят. Частичный выход из создавшейся ситуации достигается путем помещения нуль- символа (Esc-последовательность \0) в конец всякой строки. Это означает, что под строкой следует понимать последовательность символов, начинающуюся в нулевом элементе массива типа char и заканчивающуюся символом \0. При этом нужно помнить, что описывая символьный массив необходимо резервировать одну дополнительную ячейку памяти под хранение нуль- символа. Так, например, для представления строки, содержащей 40 символов, в программе необходимо иметь описание вида

char string[41];

т.е. размерность массива должна быть по крайней мере на единицу больше истинной длины строки. Тем не менее, ввиду того, что в языке Си нет средств для работы с массивами как с единым целым, то и не существует возможности манипулировать строками как неделимыми единицами информации. Это затруднение снимается за счет использования функций из стандартной библиотеки языка. Ниже приведены примеры некоторых из них.

Имя функции и назначение: strcat - добавление строки string2 в конец строки string1

Формат и описание аргументов:

char *strcat(string1, string2)

char *string1; /* Указатель на строку-приемник */

char *string2; /* Указатель на строку-источник */

Возвращаемое значение равно адресу начала стороки string1, т.е. указателю на эту строку.

Имя функции и назначение: strchr - поиск первого вхождения символа sym в строку string

Формат и описание аргументов:

char *strchr(string, sym)

const char *string; /* Указатель на строку */

int sym; /* Символ поиска */

Возвращаемое значение является указателем на первое вхождение символа sym в строку string и равно NULL, если этот символ в составе строки не найден.

Имя функции и назначение: strcmp - сравнение строк string1 и string2, считая различными большие и малые буквы латинского алфавита

Формат и описание аргументов:

int strcmp(string1, string2)

const char *string1; /* Указатель на первую строку */

const char *string2; /* Указатель на вторую строку */

Возвращаемое значение равно нулю для идентичных строк и отлично от нуля в противном случае.

Имя функции и назначение: strcmpi - сравнение строк string1 и string2, не делая различия между большими и малыми буквами латинского алфавита

Формат и описание аргументов:

int strcmpi(string1, string2)

const char *string1; /* Указатель на первую строку */

const char *string2; /* Указатель на вторую строку */

Возвращаемое значение равно нулю для идентичных строк и отлично от нуля в противном случае.

Имя функции и назначение: strcpy - копирование строки string2 в строку string1

Формат и описание аргументов:

char *strcpy(string1, string2)

char *string1; /* Указатель на строку-приемник */

const char *string2; /* Указатель на строку-источник */

Возвращаемое значение равно адресу начала строки string1, т. е. является указателем на эту строку.

Имя функции и назначение: strlen - определение длины строки string

Формат и описание аргументов:

int strlen(string)

const char *string; /* Указатель на строку */

Возвращаемое значение равно количеству символов в строке string, исключая завершающий нуль-символ.

Имя функции и назначение: strlwr - замена всех больших букв латинского алфавита в составе строки string соответствующими им малыми буквами

Формат и описание аргументов:

char *strlwr(string)

char *string; /* Указатель на преобразуемую строку */

Возвращаемое значение равно адресу начала строки string, т. е. указателю на эту строку.

Имя функции и назначение: strstr - поиск первого вхождения подстроки string2 в строку string1

Формат и описание аргументов:

char *strstr(string1, string2)

const char *string1; /* Указатель на строку */

const char *string2; /* Указатель на подстроку */

Возвращаемое значение является указателем на первое вхождение подстроки string2 в строку string1 и равно NULL, если подстрока поиска не обнаружена в составе строки string1.

Имя функции и назначение: strupr - замена всех малых букв латинского алфавита в составе строки string соответствующими им большими буквами

Формат и описание аргументов:

char *strupr(string)

char *string; /* Указатель на преобразуемую строку */

Возвращаемое значение равно адресу начала строки string, т. е. указателю на эту строку.

Предварительные описания всех этих функций (см. Лекцию 5, $ 3) помещены в файл string.h и при их использовании последний должен быть включен в состав исходного текста программы с помощью директивы препроцессора #include (см. Лекцию 7, $ 4 и примеры программ). Встречающееся в этом параграфе понятие указателя будет подробно рассмотрено в Лекции 4.