Массивы переменных как однородные статические структуры данных. Строки символов. Инициализация переменных и массивов
Вид материала | Лекция |
- Вопросы по дисциплине, 14.43kb.
- Лекция 19. Предел и непрерывность функции нескольких переменных, 34.61kb.
- Значение формулы логики предикатов, 9.17kb.
- России Бориса Николаевича Ельцина Кафедра "Информационные технологии и автоматизация, 903.27kb.
- Внутренняя среда организации, 464.17kb.
- § Массивы. Определение, 40.82kb.
- Задача прогнозирования значений временного ряда чаще всего предполагает использование, 148.11kb.
- Урок №24 10 класс Тема урока: «Линейные массивы», 41.5kb.
- Примерная программа государственного экзамена по направлению подготовки дипломированных, 196.44kb.
- Календарно-тематический план учебная дисциплина: «Математика», 35.73kb.
ЛЕКЦИЯ 3
Массивы переменных как однородные статические структуры данных. Строки символов. Инициализация переменных и массивов. Управляющие конструкции языка Си: синтаксис и семантика.
$ 1. МАССИВЫ ПЕРЕМЕННЫХ КАК ОДНОРОДНЫЕ СТАТИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ.
Мы рассмотрели простые переменные, являющиеся носителями одного единственного значения, будь то число или внутреннее машинное представление некоторого символа ASCII. Однако при решении большинства практических задач на ЭВМ приходится иметь дело с наборами данных, представимых в виде векторов, таблиц, строк или абстрактных множеств с неупорядоченной структурой.
Наиболее простой логической структурой данных является ограниченный вектор элементов фиксированного типа. Элементы вектора считаются пронумерованными последовательно отрезком ряда натуральных чисел и доступ к каждому из них может осуществляться по его индивидуальному номеру. Простота подобных структур состоит в том, что они самым естественным образом отображаются на линейную структуру памяти ЭВМ.
Структурным аналогом векторов в языке Си ( как и в большинстве языков программирования) являются массивы переменных, т.е. упорядоченные последовательности элементов данных одного типа. С каждым таким массивом связывается его имя, тип элементов (а следовательно и объем машинной памяти, требуемой для размещения одного элемента) и их количество (т.е. длина массива). В общем виде описание массивов в языке Си следующее:
[класс памяти] тип имя[константное арифметическое выражение];
Например:
int mas[10];
char z[20];
определяют два массива: массив mas, состоящий из 10 элементов типа int, и массив символов z, длина которого равна 20.
Для обращения в программе к элементу всякого массива следует указать его имя и порядковый номер, заключенный в квадратные скобки:
c = 2*mas[5] + 7;
Отметим, что компилятор Си нумерует элементы массивов начиная с нуля (а не с единицы, как это принято во многих языках программирования). Поэтому в приведенном примере одним из операндов арифметического выражения является шестой а не пятый элемент массива mas. Соответственно, последний элемент этого массива будет иметь индекс 9. В общем случае порядковые номера элементов могут задаваться произвольными арифметическими выражениями целого типа, которые будем называть индексными выражениями.
Язык Си не обеспечивает возможности работы с массивами переменных как с единым целым: в качестве операндов выражений могут выступать лишь отдельные элементы. Однако ссылка на имя массива без следующего за ним индекса элемента все же имеет определенный смысл, так как отождествляется с адресом размещения в памяти первого элемента этого массива.
$ 2. СТРОКИ СИМВОЛОВ
Мы уже познакомились с понятием символьной строки как последовательности, состоящей из одного или более символов ASCII. Рассмотрим вопрос размещения строк в памяти ЭВМ и их использование в программе. Дело в том, что в языке Си нет специального типа, который можно было бы использовать для описания строк. Вместо этого они представляются в виде массивов элементов типа char. Такое решение проблемы означает, что символы строки располагаются в соседних ячейках памяти - по одному символу в байте.
В то же время, столь упрощенное представление о строках несколько затрудняет практическую работу с ними, поскольку в большинстве случаев строки интересуют нас как целостные в логическом отношении единицы информации, а не как наборы символов, из которых они состоят. Частичный выход из создавшейся ситуации достигается путем помещения ноль-символа (Esc-последовательность \0) в конец всякой строки. Это означает, что под строкой следует понимать последовательность символов, начинающуюся в нулевом элементе массива типа char и заканчивающуюся символом \0. При этом нужно помнить, что описывая массив символов для хранения строки необходимо резервировать одну дополнительную ячейку памяти под нуль-символ. Так, например, для представления строки, содержащей 40 символов, в программе необходимо иметь описание вида:
char string[41];
Тем не менее, ввиду того, что в языке Си нет средств для работы с массивами как с единым целым, то и не существует возможности манипулировать строками как неделимыми единицами информации. Это затруднение снимается за счет использования функций стандартной библиотеки языка (
strlen(s) - определение длины строки s до ноль-символа
strcmp(s1,s2) - сравнение строк
strncmp(s1,s2,n) - сравнение строк длиной n
strcpy(s1,s2) - копирование строки s2 в s1
strncpy(s1,s2,n) - копирование n символов из строки s2 в s1
strcat(s1,s2) - добавление строки s2 k s1 (s1=s1+s2)
strncat(s1,s2,n) - добавление к строке s1 n символов из s2
strchr(s,c) - поиск первого появления символа с в строке s
strcspn(s1,s2) - поиск первого появления символа из s2 в s1
strnset(s,c,n) - инициализация строки n символами с
strrev(s) - разворот строки
strrchr(s,c) - поиск последнего появления символа с в s
strlwr(s) - преобразование строки в нижний регистр
strupr(s) - преобразование строки в верхний регистр
Для ввода/вывода строк на стандартные устройства могут использоваться функции gets(s) и puts(s) или scanf и printf с форматным кодом %s.
Отметим, что функция sizeof s возвращает значение в количестве байт, необходимых для размещения всего символьного массива.
$ 3 ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ И МАССИВОВ
Под инициализацией произвольных элементов данных понимается присвоение им некоторых значений перед началом работы программы. Это можно сделать, вводя инициализирующие выражения непосредственно в инструкции описания переменных.
для простых переменных инициализатор имеет следующий формат:
<тип> имя переменной = произвольное константное выражение;
Например:
char sym = 0x73, slash = '/';
int n = 10, k = 2;
float x = 2.5, y = 0.12e3;
В случае инициализации массивов последовательность инициализирующих выражений заключается в фигурные скобки и разделяется запятыми. Например:
int mas[5] = 0, 1, 2, 3, 4 ;
char string[5] = 'm','a','r','t','\0';
float val[10] = 1.2, 1.7, 4.1;
Инициализация массивов допустима лишь при их описании на внешнем уровне программы, т.е. вне тела какой бы то ни было функции, или при явном назначении класса памяти static.
Переменные и массивы, для которых начальные значения явным образом не заданы, инициализируются нулем при их определении на внешнем уровне или при наличии описателя класса памяти static, и остаются неопределенными для автоматических и регистровых переменных. Исключение составляет случай, когда размерность массива не указана:
int mas[] = { 1, 2, 3} ;
В этом примере длина массива определяется по числу инициализирующих значений. Инициализация символьной строки может быть выполнена следующим образом:
char string[] = "mart";
что эквивалентно предыдущему примеру.
С другой стороны, описание
char rob[80] = "строка";
объявляет массив, состоящий из 80 элементов типа char, но лишь 6 из них отличны от нуль-символа.
$ 4. УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ ЯЗЫКА СИ.
К ним относятся : условный оператор, переключатель, несколько разновидностей оператора цикла и операторы передачи управления.
4.1. Условный оператор if-else
Является простейшим и эффективным средством, позволяющим программировать разветвляющиеся алгоритмы. Его формальный синтаксис задается следующей формулой:
if(выражение) оператор1;
[else оператор2;]
причем else-часть не является обязательной и может быть опущена. В скобках после if -произвольное выражение, приводимое к логическому значению. Если результатом вычисления выражения является логическое значение "истина"(отличное от нуля), то выполняются действия, отвечающие оператору1. В противном случае осуществляется переход к оператору2 в else-части условного оператора, а при отсутствии ее - к оператору, непосредственно следующему за оператором if. Пример:
if(i>0) y=x/i;
else
x=i/2; y=x+5;
Если один оператор if вложен в другой, то else-часть связывается с ближайшим предыдущим оператором if. Чтобы изменить это соглашение, необходимо использовать фигурные скобки.
if(n > 0) if(n > 0)
if(a > b) { if(a > b)
z = a; z = a; }
else else
z = b; z = b;
4.2. Оператор-переключатель switch
Переключатель является специальным случаем условного оператора и позволяет осуществить многовариантный выбор, заменяя группу вложенных операторов if-else. В общем случае он имеет следующий формат:
switch(выражение)
{ [case константное выражение: [операторы ][break;]]
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
[case константное выражение: [операторы ][break;]]
[default: [операторы][break;]]
}
где любая case- или default-часть может отсутствовать, а также могут быть опущены операторы в любой из этих частей. В скобках после switch -произвольное выражение целого тапа. Константное выражение в case обрабатывается в период компиляции программы. Никакие два константных выражения в одном операторе-переключателе не могут иметь одинаковых значений.
Семантика. Предварительно вычисленное выражение в круглых скобках сравнивается с константой во всех вариантах case и управление передается той группе операторов, которая соответствует найденному значению. Если значение ни одного из константных выражений не совпало со значением (выражения), то выполняются операторы, связанные с меткой default, а при ее отсутствии - оператор, непосредственно следующий за оператором switch.
В следующем примере значение переменной ор, имеющей тип char, определяет ту арифметическую операцию, которая должна быть выполнена над переменными х и у:
switch( op )
{case '+': z = x + y;
break;
case '-': z = x - y;
break;
case '*': z = x * y;
break;
case '/': z = x / y;
}
Ключевое слово case вместе с константой служат просто меткой соответствующих операторов, и если будут выполняться операторы для некоторого варианта case, то далее будут выполняться операторы всех последующих вариантов до тех пор, пока не встретится оператор break. Поэтому, если нескольким различным значениям (выражения) должны соответствовать одни и те же действия, можно воспользоваться следующей конструкцией:
switch(key)
{ case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
printf("Это цифрв"); }
4.3. Оператор цикла while
Позволяет циклически выполнять оперделенную последовательность операторов до тех пор, пока истинно некоторое условие, проверяемое перед началом очередной итерации цикла ( цикл с предусловием ).
while(выражение)
оператор
4.4. Опреатор цикла do while
Условие проверяется после завершения очередной итерации (цикл с постусловием)
do
оператор
while(выражение)