Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
153
Добавлен:
11.05.2015
Размер:
328.83 Кб
Скачать

}

else printf(“ Надо было ввести заглавную букву\n”);

}

# include < stdio.h > /* Пример 13 */ main()

{

char ch;

printf(“ Введите заглавную букву русского алфавита ”); ch=getchar();

if ( ch >= ‘А’ && ch <=’Я’) switch (ch)

{

case ‘А’: printf(“Андреев\n”);

case ‘Б’: printf(“Булгаков\n”);

case ‘В’: printf(“Волошин\n”);

case ‘Г’: printf(“Гоголь\n”);

default:

printf(“Достоевский, Зощенко и другие \n”);

}

else printf(“ Надо было ввести заглавную букву\n”);

}

Предположим, вы запустили первую программу и ввели букву Б. Результатом выполнения программы будет следующая строка:

Булгаков Выполняется только один оператор, соответствующий метке ‘Б’. В

случае запуска следующей программы получим такой результат: Булгаков Волошин Гоголь

Достоевский, Зощенко и другие Выполнились все операторы, начиная с метки ‘Б’, включая тот кото-

рый следует за словом default.

31

3.3. Операторы циклов

Циклы необходимы, когда необходимо повторить некоторые действия несколько раз, как правило, пока выполняется некоторое условие. В языке С имеются три оператора цикла: for, while и do-while.

Основная форма цикла for имеет следующий вид:

for ( инициализация; проверка условия; изменение) оператор;

В более общем виде:

for ( выражение1; выражение1; выражение1 ) оператор;

В простейшей форме инициализация используется для присвоения начального значения параметру цикла. Проверка условия – обычно условное выражение, которое определяет, когда цикл должен быть завершен. Изменение обычно используется для изменения значения параметра цикла каждый раз при его повторении. Эти три раздела, определяющие заголовок цикла, должны разделяться точкой с запятой. Оператор (возможно составной) определяет тело цикла. Тело цикла выполняется до тех пор , пока проверка условия дает значение “ истинно”. Как только проверка условия даст значение “ ложно”, начинает выполняться следующий за оператором for оператор.

Простой пример оператора for

for ( i=0; i<10; i++) printf(“%d\n”,i);

В результате выполнения этого оператора будут напечатаны в столбик цифры от 0 до 9. Для печати этих цифр в обратном порядке можно использовать следующий оператор:

for ( i=9; i>=0; i—) printf(“%d\n”,i);

Цикл for похож на аналогичные операторы цикла в других языках программирования, но в тоже время является более гибким и мощным по своим возможностям. В качестве параметра цикла можно использовать данные типа char, например:

unsigned char ch;

for ( ch=’A’; ch<=’Я’; ch++) printf(“%c”,ch); Следующий фрагмент программы

for ( ch=’0’; ch!=N; ) scanf(“%c”,&ch);

будет выполняться до тех пор, пока с клавиатуры не будет введен символ ‘N’. Заметим, что место в заголовке цикла, где должно быть изменение параметра цикла, пусто. При программировании, случайно или

32

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

Приведем примеры:

for ( ; ; ) printf(“ Бесконечный цикл ”);

for ( i=1; 1; i++ ) printf(“ Бесконечный цикл ”); for ( j=12; j>8; j++ ) printf(“ Бесконечный цикл ”);

Когда один цикл находится внутри другого, то говорят, что это вложенные циклы. Необходимость такой вложенности характерна для программирования многих задач, в частности, для заполнения различных таблиц. Рассмотрим программу печати таблицы умножения чисел от 1 до 9:

# include < stdio.h > /* Пример 14 */ main()

{

int i,j;

for ( i=1; i<10; i++);

{

for ( j=1; j<10; j++) printf(“%d * %d = %d”,i,j,i*j); printf(“\n”);

}

}

Результатом выполнения этой программы будет построчная печать результатов умножения 1 на все числа от 1 до 9, на следующей строке – результаты умножения 2 на все числа от 1 до 9 и так далее.

Необходимо помнить, что при использовании цикла for опасно изменять параметр цикла внутри тела цикла. Изменение значения параметра цикла внутри тела цикла может привести к мало понятному поведению программы.

Следующий оператор цикла в языке С – это цикл while. Основная его форма имеет следующий вид:

While ( условие ) оператор;

оператор может быть простым, составным или пустым оператором (тело цикла while). Условие – это просто некоторое выражение. Цикл выполняется до тех пор, пока условие принимает значение “ истинно”. Когда условие принимает значение “ ложно”, программа передает управление следующему оператору программы. Также как и в цикле for, в цикле

33

while сначала проверяется условие, а затем выполняется оператор. Это так называемый цикл с предусловием.

В цикле do-while условие проверяется в конце оператора цикла. Основная форма оператора do-while следующая:

do {

последовательность операторов } while ( условие );

Фигурные скобки необязательны, если внутри них находится один оператор. Тем не менее их лучше ставить для удобства чтения программы. Оператор do-while называется оператором цикла с постусловием. Какое бы условие ни стояло в конце оператора, набор операторов в фигурных скобках( тело цикла do-while ) один (первый) раз выполнится обязательно. В циклах for и while тело цикла может не выполниться ни разу. Рассмотрим пример программы с использованием цикла do-while.

#include < stdio.h >

#include < stdlib.h >

#include < time.h > /* Пример 15 */

/* Угадываем число, заданное в диапазоне от 1 до 100 */ main()

{

int s,x; int n=0;

randomize();

s=random(100)+1; /* генерация случайного числа */ do {

printf(“ Введите число от 1 до 100:“); scanf(“%d”, &x);

n++;

if ( s<x ) printf(“ Заданное число меньше\n”); if ( s>x ) printf(“ Заданное число больше\n”); } while ( s-x );

printf(“ Вы угадали число \n”);

printf(“ Затратили на угадывание %d попыток\n”,n);

}

В отличие от оператора for, в теле цикла операторов while и do-while (если оно не пустой оператор) обязательны действия, направленные на

34

изменения значения условия. Если таких действий нет, то циклы while и do-while могут стать бесконечными. В вышеуказанном примере это действия, связанные с изменением значения переменной x.

3.4. Операторы break и continue

Оператор break имеет два применения. Первое – окончание case в операторе switch. Второе – немедленное окончание цикла, не связанное с проверкой обычного условия окончания цикла. Когда оператор break встречается внутри оператора цикла (является частью тела цикла), то происходит немедленный выход из цикла и переход к выполнению оператора, следующего за оператором цикла:

# include < stdio.h > /* Пример 16 */ main()

{

int i;

for ( i=0; i<1000; i++)

{

printf(“%d - %d\n”,i,i*i*i); if ( i*i*i > 10000 ) break

}

}

В данном примере выход из цикла произойдет, когда значение куба переменной i превысит величину 10000.

Еще один полезный оператор – continue. Если оператор continue встретился в теле цикла, то он передает управление на начало следующей итерации цикла. В циклах while и do-while на проверку условия, в цикле for – на изменение параметра цикла. Этот оператор необходим, когда надо закончить текущую итерацию цикла и не выполнять оставшиеся операторы, входящие в тело цикла

# include < stdio.h > /* Пример 17 */ main()

{

int i;

for ( i=7; i<1000; i++)

{

35

if ( i%7 != 0 ) continue; printf(“%d”,i);

}

}

При выполнении данной программы производится печать целых чисел, кратных 7 и не превышающих величину 1000. Если переменная i не кратна 7, осуществляется переход на следующую итерацию с новым значением переменной i.

3.5. Оператор безусловного перехода

Оператор безусловного перехода имеет форму: goto метка;

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

36

4.МАССИВЫ И УКАЗАТЕЛИ

4.1.Понятие массива, объявление массива

На основе базовых (встроенных) типов данных язык С позволяет строить другие типы данных и структуры данных. Массив – одна из наиболее простых и часто используемых структур данных. Под массивом понимают набор данных одного и того же типа, собранных под одним именем. Каждый элемент массива определяется именем массива и порядковым номером элемента, который называется индексом. Индекс в языке С всегда целое число.

Основная форма объявления массива размерности N такова: тип <имя массива>[размер1][размер2]…[размерN]

Чаще всего используются одномерные массивы: тип <имя массива>[размер];

Тип – базовый тип элементов массива, размер – количество элементов одномерного массива. При описании двумерного массива его объявление имеет следующий вид:

тип <имя массива>[размер1][размер2];

В этом описании можно трактовать объявление двумерного массива как объявление массива массивов, т. е. массив размера [размер2], элементами которого являются одномерные массивы <имя массива>[размер1].

Размер массива в языке С может задаваться константой или константным выражением. Нельзя задать массив переменного размера. Для этого существует отдельный механизм ( динамическое выделение памяти).

Сначала обсудим более подробно одномерные массивы. В языке С индекс всегда начинается с нуля. Когда речь идет о первом элементе массива, то имеем в виду элемент с индексом 0. Если объявляется массив int a[100]; , то это значит, что массив содержит 100 элементов от a[0] до a[99]. Для одномерного массива легко определить, сколько байт в памяти будет занимать этот массив:

37

Количество байт=<размер базового типа>*<количество элементов> .

В языке С под массив всегда выделяется непрерывное место в памяти. В языке С не проверяется выход значения индекса за пределы массива. Поэтому, при написании и отладке программ с использованием массивов, этот момент необходимо учитывать.

4.2. Массивы символов, строки. Функции работы со строками

Массивы типа char – символьные массивы – занимают особое место. Во многих языках программирования есть специальный тип данных – строка символов (string). В языке С такого типа нет, а работа со строками реализована путем использования одномерных массивов типа char. В языке С символьная строка – это одномерный массив типа char, заканчивающийся нулевым байтом. Для нулевого байта определена специальная символьная константа – ‘\0’. Это необходимо учитывать при описании соответствующего символьного массива. Так, если строка должна содержать N символов, то в описании массива необходимо указать N+1 элемент.

Например, описание int str[12], предполагает, что строка содержит 11 символов, а последний байт зарезервирован под нулевой байт.

Хотя в языке С нет специального типа строки, язык допускает строковые константы. Строковая константа – это список литер, заключенных в двойные кавычки. Например,

“Borland C++”, “Строковая константа”.

В конец строковой константы не надо ставить символ ‘\0’. Это сделает сам компилятор, и строка “Borland C++” в памяти будет выглядеть так:

B

o

r

l

a

n

d

 

C

+

+

\0

 

 

 

 

 

 

 

 

 

 

 

 

Есть два простых способа ввести строку с клавиатуры. Первый способ – воспользоваться функцией scanf() со спецификатором ввода %s. Надо помнить , что функция scanf() вводит символы до первого пробельного символа. Второй способ – воспользоваться функцией gets(), объявленной в файле stdio.h. Функция gets() позволяет вводить строки, содержащие пробелы. Ввод заканчивается нажатием клавиши Enter. Обе функции автоматически ставят в конце строки нулевой байт. В качестве параметра в этих функциях используется имя массива.

38

Вывод строк производится с помощью функций printf() и puts(). Обе функции выводят содержимое массива до первого нулевого байта. Функция puts() добавляет в конце выводимой строки символ новой строки. В функции printf() переход на новую строку надо предусматривать в строке формата самим.

Рассмотрим пример:

# include < stdio.h > /* Пример 18 */

/* Ввод строки с клавиатуры и вывод ее на экран */ main()

{

char str[80];

printf(“Введите строку длиной не более 80 символов”); gets(str);

printf(“ Вы ввели строку %s\n”,str); printf(“Введите еще одну строку ”); scanf(“%s”,str);

printf(“ Вы ввели строку ”); puts(str);

}

Для работы со строками существует специальная библиотека, описание которой находится в файле string.h. Рассмотрим их подробнее.

Вызов функции strcpy() имеет вид – strcpy(s1,s2). Эта функция используется для копирования содержимого строки s2 в строку s1. Массив s1 должен быть достаточно большим, чтобы в него поместилась s2. Если места мало, то компилятор не выдаст соответствующего сообщения об ошибке, также это не приведет к прерыванию выполняемой программы, но может привести к порче других данных, что отразится на результате.

Вызов функции strcat() имеет вид – strcat(s1,s2). Эта функция присоединяет строку s2 к строке s1 и помещает ее в массив, где находится строка s1, при этом строка s2 не изменяется. Нулевой байт, который завершал строку s1, будет заменен первым символом строки s2. И в функции strcpy(), и в функции strcat() полученная строка автоматически завершается нулевым байтом. Рассмотрим пример использования этих функций:

39

#include < stdio.h >

#include < string.h > /* Пример 19 */ main()

{

char s1[20], s2[20]; strcpy(s1,” Hello, “); strcpy(s2,” World !”); puts(s1); puts(s2); strcat(s1,s2); puts(s1); puts(s2);

}

Вызов функции strcmp() имеет вид – strcmp(s1,s2). Эта функция сравнивает строки s1 и s2 и возвращает значение ноль, если строки равны, т. е. содержат одно и то же число одинаковых символов. Под сравнением строк понимается сравнение в лексикографическом смысле. Если s1 лексикографически больше s2, то функция strcmp() возвращает положительное значение, если меньше – отрицательное.

Вызов функции strlen() возвращает длину строки s, при этом завершающий нулевой байт не учитывается. Вызов strlen(“hello”) вернет значение 5. Рассмотрим пример программы, в которой определяется длина строки, вводимой с клавиатуры:

#include < stdio.h >

#include < string.h > /* Пример 20 */ main()

{

char s[80];

printf(“ Введите строку: ”); gets(s);

printf(“строка \n%s\n имеет длину %d символов\n”,s,strlen(s));

}

40