Чтение онлайн

на главную

Жанры

Язык программирования Си. Издание 3-е, исправленное

Ритчи Деннис М.

Шрифт:

/* подсчет строк, слов и символов */

main

{

 int с, nl, nw, nc, state;

 state = OUT;

 nl = nw = nc = 0;

 while ((с = getchar) != EOF) {

++nc;

if (c == '\n')

++nl;

if (c == ' ' || c == '\n' || c == '\t')

state = OUT;

else if (state == OUT) {

state = IN;

++nw;

}

 }

 printf("%d %d %d\n", nl, nw, nc);

}

Каждый

раз, встречая первый символ слова, программа изменяет значение счетчика слов на 1. Переменная state фиксирует текущее состояние - находимся мы внутри или вне слова. Вначале ей присваивается значение OUT, что соответствует состоянию "вне слова". Мы предпочитаем пользоваться именованными константами IN и OUT, а не собственно значениями 1 и 0, чтобы сделать программу более понятной. В такой маленькой программе этот прием мало что дает, но в большой программе увеличение ее ясности окупает незначительные дополнительные усилия, потраченные на то, чтобы писать программу в таком стиле с самого начала. Вы обнаружите, что большие изменения гораздо легче вносить в те программы, в которых магические числа встречаются только в виде именованных констант.

Строка

nl = nw = nc = 0;

устанавливает все три переменные в нуль. Такая запись не является какой-то особой конструкцией и допустима потому, что присваивание есть выражение со своим собственным значением, а операции присваивания выполняются справа налево. Указанная строка эквивалентна

nl = (nw = (nc = 0));

Оператор || означает ИЛИ, так что строка

if (c == ' ' || c == '\n' || c == '\t')

читается как "если c есть пробел, или c есть новая строка, или c есть табуляция". (Напомним, что видимая эскейп-последовательность \t обозначает символ табуляции.) Существует также оператор &&, означающий И. Его приоритет выше, чем приоритет ||. Выражения, связанные операторами && или ||, вычисляются слева направо; при этом гарантируется, что вычисления сразу прервутся, как только будет установлена истинность или ложность условия. Если c есть пробел, то дальше проверять, является значение c символом новой строки или же табуляции, не нужно. В этом частном случае данный способ вычислений не столь важен, но он имеет значение в более сложных ситуациях, которые мы вскоре рассмотрим.

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

if (выражение)

 инструкция1

else

 инструкция2

В конструкции if-else выполняется одна и только одна из двух инструкций. Если выражение истинно, то выполняется инструкция1, если нет, то - инструкция2. Каждая из этих двух инструкций

представляет собой либо одну инструкцию, либо несколько, заключенных в фигурные скобки. В нашей программе после else стоит инструкция if, управляющая двумя такими инструкциями.

Упражнение 1.11. Как протестировать программу подсчета слов? Какой ввод вероятнее всего обнаружит ошибки, если они были допущены?

Упражнение 1.12. Напишите программу, которая печатает содержимое своего ввода, помещая по одному слову на каждой строке.

1.6 Массивы

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

#include ‹stdio.h›

/* подсчет цифр, символов-разделителей и прочих символов */

main

{

 int с, i, nwhite, nother;

 int ndigit[10];

 nwhite = nother = 0;

 for (i = 0; i ‹ 10, ++i)

ndigit[i]= 0;

 while ((c = getchar)!= EOF)

if (c ›='0' && с ‹= '9')

++ndigit[c - '0'];

else if (c == ' ' || c == '\n' || c == '\t')

++nwhite;

else

++nother;

 printf("цифры =");

 for (i = 0; i ‹ 10; ++i)

printf("%d", ndigit[i]);

 printf(", символы-разделители =%d, прочие =%d\n", nwhite, nother);

}

В результате выполнения этой программы будет напечатан следующий результат:

цифры = 9 3 0 0 0 0 0 0 0 1, символы-разделители = 123, прочие = 345

Объявление

int ndigit[10];

объявляет ndigit массивом из 10 значений типа int. В Си элементы массива всегда нумеруются начиная с нуля, так что элементами этого массива будут ndigit[0], ndigit[1], …, ndigit[9], что учитывается в for– циклах (при инициализации и печати массива).

Индексом может быть любое целое выражение, образуемое целыми переменными (например i) и целыми константами.

Приведенная программа опирается на определенные свойства кодировки цифр. Например, проверка

 if (c ›= '0' && c ‹= '9') …

определяет, является ли находящийся в c символ цифрой. Если это так, то

c -'0'

есть числовое значение цифры. Сказанное справедливо только в том случае, если для ряда значений '0','1',…, '9' каждое следующее значение на 1 больше предыдущего. К счастью, это правило соблюдается во всех наборах символов.

Поделиться:
Популярные книги

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Маяк надежды

Кас Маркус
5. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Маяк надежды

Великий перелом

Ланцов Михаил Алексеевич
2. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Великий перелом

Сопротивляйся мне

Вечная Ольга
3. Порочная власть
Любовные романы:
современные любовные романы
эро литература
6.00
рейтинг книги
Сопротивляйся мне

Инквизитор Тьмы 2

Шмаков Алексей Семенович
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы 2

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Бандит 2

Щепетнов Евгений Владимирович
2. Петр Синельников
Фантастика:
боевая фантастика
5.73
рейтинг книги
Бандит 2

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни

"Дальние горизонты. Дух". Компиляция. Книги 1-25

Усманов Хайдарали
Собрание сочинений
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Дальние горизонты. Дух. Компиляция. Книги 1-25

Ох уж этот Мин Джин Хо 2

Кронос Александр
2. Мин Джин Хо
Фантастика:
попаданцы
5.00
рейтинг книги
Ох уж этот Мин Джин Хо 2

Энфис 6

Кронос Александр
6. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 6