Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное
- Название:Язык программирования Си. Издание 3-е, исправленное
- Автор:
- Жанр:
- Издательство:Невский Диалект
- Год:2001
- Город:Санкт-Петербург
- ISBN:0-13-110362-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное краткое содержание
Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.
Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.
Для программистов, преподавателей и студентов.
Издание подготовлено при участии издательства "Финансы и статистика"
Язык программирования Си. Издание 3-е, исправленное - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Программу копирования можно написать более сжато. В Си любое присваивание, например
c = getchar()
трактуется как выражение со значением, равным значению левой части после присваивания. Это значит, что присваивание может встречаться внутри более сложного выражения. Если присваивание переменной c расположить в проверке условия цикла while , то программу копирования можно будет записать в следующем виде:
#include ‹stdio.h›
/* копирование ввода на вывод; 2-я версия */
main()
{
int c;
while ((с = getchar()) != EOF)
putchar(c);
}
Цикл while , пересылая в c полученное от getchar значение, сразу же проверяет: не является ли оно "концом файла". Если это не так, выполняется тело цикла while и печатается символ. По окончании ввода завершается работа цикла while , а тем самым и main .
В данной версии ввод "централизован". - в программе имеется только одно обращение к getchar . В результате она более компактна и легче воспринимается при чтении. Вам часто придется сталкиваться с такой формой записи, где присваивание делается вместе с проверкой. (Чрезмерное увлечение ею, однако, может запутать программу, поэтому мы постараемся пользоваться указанной формой разумно.)
Скобки внутри условия, вокруг присваивания, необходимы. Приоритет != выше, чем приоритет =, из чего следует, что при отсутствии скобок проверка!= будет выполняться до операции присваивания =. Таким образом, запись
c = getchar() != EOF
эквивалентна записи
c = (getchar() != EOF)
А это совсем не то, что нам нужно: переменной c будет присваиваться 0 или 1 в зависимости от того, встретит или не встретит getchar признак конца файла. (Более подробно об этом см. в главе 2.)
Упражнение 1.6. Убедитесь в том, что выражение getchar()!= EOF получает значение 0 или 1.
Упражнение 1.7. Напишите программу, печатающую значение EOF .
1.5.2 Подсчет символов
Следующая программа занимается подсчетом символов; она имеет много сходных черт с программой копирования.
#include ‹stdio.h›
/* подсчет вводимых символов; 1-я версия */
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
Инструкция
++nc;
представляет новый оператор ++, который означает увеличить на единицу . Вместо этого можно было бы написать nc=nc+1 , но ++nc намного короче, а часто и эффективнее. Существует аналогичный оператор --, означающий уменьшить на единицу . Операторы ++и --могут быть как префиксными ( ++nc ), так и постфиксными ( nc++ ). Как будет показано в главе 2, эти две формы в выражениях имеют разные значения, но и ++nc , и nc++ добавляют к nc единицу. В данном случае мы остановились на префиксной записи.
Программа подсчета символов накапливает сумму в переменной типа long . Целые типа long имеют не менее 32 битов. Хотя на некоторых машинах типы int и long имеют одинаковый размер, существуют, однако, машины, в которых int занимает 16 бит с максимально возможным значением 32767, а это - сравнительно маленькое число, и счетчик типа int может переполниться. Спецификация %ld в printf указывает, что соответствующий аргумент имеет тип long .
Возможно охватить еще больший диапазон значений, если использовать тип double (т. е. float с двойной точностью). Применим также инструкцию for вместо while , чтобы продемонстрировать другой способ написания цикла.
#include ‹stdio.h›
/* подсчет вводимых символов; 2-й версия */
main()
{
double nc;
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%.0f\n", nc);
}
В printf спецификатор %f применяется как для float , так и для double ; спецификатор %.0f означает печать без десятичной точки и дробной части (последняя в нашем случае отсутствует).
Тело указанного for -цикла пусто, поскольку кроме проверок и приращений счетчика делать ничего не нужно. Но правила грамматики Си требуют, чтобы for - цикл имел тело. Выполнение этого требования обеспечивает изолированная точка с запятой, называемая пустой инструкцией . Мы поставили точку с запятой на отдельной строке для большей наглядности.
Наконец, заметим, что если ввод не содержит ни одного символа, то при первом же обращении к getchar условие в while или for не будет выполнено и программа выдаст нуль, что и будет правильным результатом. Это важно. Одно из привлекательных свойств циклов while и for состоит в том, что условие проверяется до того, как выполняется тело цикла. Если ничего делать не надо, то ничего делаться и не будет, пусть даже тело цикла не выполнится ни разу. Программа должна вести себя корректно и при нулевом количестве вводимых символов. Само устройство циклов while и for дает дополнительную уверенность в правильном поведении программы в случае граничных условий.
1.5.3 Подсчет строк
Следующая программа подсчитывает строки. Как упоминалось выше, стандартная библиотека обеспечивает такую модель ввода-вывода, при которой входной текстовый поток состоит из последовательности строк, каждая из которых заканчивается символом новой строки. Следовательно, подсчет строк сводится к подсчету числа символов новой строки.
#include ‹stdio.h›
/* подсчет строк входного потока */
main()
{
int c, nl;
nl = 0;
while ((с = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
}
Тело цикла теперь образует инструкция if , под контролем которой находится увеличение счетчика nl на единицу. Инструкция if проверяет условие в скобках и, если оно истинно, выполняет следующую за ним инструкцию (или группу инструкций, заключенную в фигурные скобки). Мы опять делаем отступы в тексте программы, чтобы показать, что чем управляется.
Двойной знак равенства в языке Си обозначает оператор "равно" (он аналогичен оператору = в Паскале и .EQ. в Фортране). Удваивание знака = в операторе проверки на равенство сделано для того, чтобы отличить его от единичного = , используемого в Си для обозначения присваивания. Предупреждаем: начинающие программировать на Си иногда пишут = , а имеют в виду == . Как мы увидим в главе 2, в этом случае результатом будет обычно вполне допустимое по форме выражение, на которое компилятор не выдаст никаких предупреждающих сообщений (Современные компиляторы, как правило, выдают предупреждение о возможной ошибке. - Примеч. ред. ).
Символ, заключенный в одиночные кавычки, представляет собой целое значение, равное коду этого символа (в кодировке, принятой на данной машине). Это так называемая символьная константа . Существует и другой способ для написания маленьких целых значений. Например, 'A' есть символьная константа, в наборе символов ASCII ее значение равняется 65 - внутреннему представлению символа A . Конечно, 'A' в роли константы предпочтительнее, чем 65, поскольку смысл первой записи более очевиден, и она не зависит от конкретного способа кодировки символов.
Читать дальшеИнтервал:
Закладка: