Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное
- Название:Язык программирования Си. Издание 3-е, исправленное
- Автор:
- Жанр:
- Издательство:Невский Диалект
- Год:2001
- Город:Санкт-Петербург
- ISBN:0-13-110362-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное краткое содержание
Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.
Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.
Для программистов, преподавателей и студентов.
Издание подготовлено при участии издательства "Финансы и статистика"
Язык программирования Си. Издание 3-е, исправленное - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
После такого проектирования программы ее "деталировка" оказывается очевидной. Мы имеем представление о программе в целом и знаем, как взаимодействуют ее части. В нашей программе образец для поиска задается строкой-литералом, что снижает ее универсальность. В главе 5 мы еще вернемся к проблеме инициализации символьных массивов и покажем, как образец сделать параметром, устанавливаемым при запуске программы. Здесь приведена несколько измененная версия функции getline , и было бы поучительно сравнить ее с версией, рассмотренной в главе 1.
#include ‹stdio.h›
#define MAXLINE 1000 /* максимальный размер вводимой строки */
int getline(char line[], int max);
int strindex(char source[], char searchfor[]);
char pattern[] ="ould"; /* образец для поиска */
/* найти все строки, содержащие образец */
main()
{
char line[MAXLINE];
int found = 0;
while (getline(line, MAXLINE) › 0)
if (strindex(line, pattern) ›= 0) {
printf ("%s", line);
found++;
}
return found;
}
/* getline: читает строку в s, возвращает длину */
int getline(char s[], int lim)
{
int c, i;
i = 0;
while (--lim › 0 && (c=getchar()) != EOF && с != '\n') /* I.B.: misprint was here -lim instead of --lim */
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
/* strindex: вычисляет место t в s или выдает -1, если t нет в s */
int strindex (char s[], char t[])
{
int i, j, k;
for (i = 0; s[i] != '\0'; i++) {
for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
;
if (k › 0 && t[k] == '\0')
return i;
}
return -1;
}
Определение любой функции имеет следующий вид:
тип-результата имя-функции ( объявления аргументов )
{
объявления и инструкции
}
Отдельные части определения могут отсутствовать, как, например, в определении "минимальной" функции
dummy() {}
которая ничего не вычисляет и ничего не возвращает. Такая ничего не делающая функция в процессе разработки программы бывает полезна в качестве "хранителя места". Если тип результата опущен, то предполагается, что функция возвращает значение типа int .
Любая программа - это просто совокупность определений переменных и функций. Связи между функциями осуществляются через аргументы, возвращаемые значения и внешние переменные. В исходном файле функции могут располагаться в любом порядке; исходную программу можно разбивать на любое число файлов, но так, чтобы ни одна из функций не оказалась разрезанной.
Инструкция returnреализует механизм возврата результата от вызываемой функции к вызывающей. За словом return может следовать любое выражение:
return выражение ;
Если потребуется, выражение будет приведено к возвращаемому типу функции. Часто выражение заключают в скобки, но они не обязательны.
Вызывающая функция вправе проигнорировать возвращаемое значение. Более того, выражение в returnможет отсутствовать, и тогда вообще никакое значение не будет возвращено в вызывающую функцию. Управление возвращается в вызывающую функцию без результирующего значения также и в том случае, когда вычисления достигли "конца" (т. е. последней закрывающей фигурной скобки функции). Не запрещена (но должна вызывать настороженность) ситуация, когда в одной и той же функции одни returnимеют при себе выражения, а другие - не имеют. Во всех случаях, когда функция "забыла" передать результат в return, она обязательно выдаст "мусор".
Функция main в программе поиска по образцу возвращает в качестве результата количество найденных строк. Это число доступно той среде, из которой данная программа была вызвана.
Механизмы компиляции и загрузки Си-программ, расположенных в нескольких исходных файлах, в разных системах могут различаться. В системе UNIX, например, эти работы выполняет упомянутая в главе 1 команда cc . Предположим, что три функции нашего последнего примера расположены в трех разных файлах: main.с , getline.c и strindex.c . Тогда команда
cc main.с getline.c strindex.c
скомпилирует указанные файлы, поместив результат компиляции в файлы объектных модулей main.o , getline.o и strindex.o , и затем загрузит их в исполняемый файл a.out . Если обнаружилась ошибка, например в файле main.с , то его можно скомпилировать снова и результат загрузить ранее полученными объектными файлами, выполнив следующую команду:
cc main.с getline.o strindex.o
Команда cc использует стандартные расширения файлов ".с" и ".о", чтобы отличать исходные файлы от объектных.
Упражнение 4.1. Напишите функцию strindex(s, t), которая выдает позицию самого правого вхождения t в s или -1, если вхождения не обнаружено.
4.2 Функции, возвращающие нецелые значения
В предыдущих примерах функции либо вообще не возвращали результирующих значений ( void), либо возвращали значения типа int. А как быть, когда результат функции должен иметь другой тип? Многие вычислительные функции, как, например, sqrt, sin и cos, возвращают значения типа double; другие специальные функции могут выдавать значения еще каких-то типов. Чтобы проиллюстрировать, каким образом функция может возвратить нецелое значение, напишем функцию atof(s) , которая переводит строку s в соответствующее число с плавающей точкой двойной точности. Функция atof представляет собой расширение функции atoi , две версии которой были рассмотрены в главах 2 и 3. Она имеет дело со знаком (которого может и не быть), с десятичной точкой, а также с целой и дробной частями, одна из которых может отсутствовать. Наша версия не является высококачественной программой преобразования вводимых чисел; такая программа потребовала бы заметно больше памяти. Функция atof входит в стандартную библиотеку программ: ее описание содержится в заголовочном файле ‹stdlib.h›.
Прежде всего отметим, что объявлять тип возвращаемого значения должна сама atof , так как этот тип не есть int . Указатель типа задается перед именем функции.
#include ‹ctype.h›
/*atof: преобразование строки s в double */
double atof (char s[])
{
double val, power;
int i, sign;
for (i = 0; isspace(s[i]); i++)
; /* игнорирование левых символов-разделителей */
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s.[i] - '0');
power *= 10.0;
}
return sign * val / power;
}
Кроме того, важно, чтобы вызывающая программа знала, что atof возвращает нецелое значение. Один из способов обеспечить это - явно описать atof в вызывающей программе. Подобное описание демонстрируется ниже в программе простенького калькулятора (достаточного для проверки баланса чековой книжки), который каждую вводимую строку воспринимает как число, прибавляет его к текущей сумме и печатает ее новое значение.
Читать дальшеИнтервал:
Закладка: