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

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

Уважаемые читатели!
Тут можно читать бесплатно Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган. Жанр: Программирование. Так же Вы можете читать полную версию (весь текст) онлайн книги без регистрации и SMS на сайте Knigi-online.info (книги онлайн) или прочесть краткое содержание, описание, предисловие (аннотацию) от автора и ознакомиться с отзывами (комментариями) о произведении.
Описание онлайн-книги Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган:
Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.Для программистов, преподавателей и студентов.Издание подготовлено при участии издательства "Финансы и статистика"
Читем онлайн Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 39 40 41 42 43 44 45 46 47 ... 81

/* minprintf: минимальный printf с переменным числом аргументов */

void minprintf(char *fmt, …)

{

 va_list ap; /* указывает на очередной безымянный аргумент */

 char *p, *sval;

 int ival;

 double dval;

 va_start(ap, fmt); /* устанавливает ap на 1-й безымянный аргумент */

 for (p=fmt; *p; p++) {

  if (*p !='%') {

   putchar(*p);

   continue;

  }

  switch (*++p) {

  case 'd':

   ival = va_arg(ap, int);

   printf ("%d", ival);

   break;

  case 'f':

   dval = va_arg(ap, double);

   printf("%f", dval);

   break;

  case 's':

    for (sval = va_arg(ap, char *); *sval; sval++)

     putchar(*sval);

    break;

  default:

   putchar(*p);

   break;

  }

 }

 va_end(ap); /* очистка, когда все сделано */

}

Упражнение 7.3. Дополните minprintf другими возможностями printf.

7.4 Форматный ввод (scanf)

Функция scanf, обеспечивающая ввод, является аналогом printf; она выполняет многие из упоминавшихся преобразований, но в противоположном направлении. Ее объявление имеет следующий вид:

int scanf(char *format, …)

Функция scanf читает символы из стандартного входного потока, интерпретирует их согласно спецификациям строки format и рассылает результаты в свои остальные аргументы. Аргумент format мы опишем позже; другие аргументы, каждый из которых должен быть указателем, определяют, где будут запоминаться должным образом преобразованные данные. Как и для printf, в этом параграфе дается сводка наиболее полезных, но отнюдь не всех возможностей данной функции.

Функция scanf прекращает работу, когда оказывается, что исчерпался формат или вводимая величина не соответствует управляющей спецификации. В качестве результата scanf возвращает количество успешно введенных элементов данных. По исчерпании файла она выдает EOF. Существенно то, что значение EOF не равно нулю, поскольку нуль scanf выдает, когда вводимый символ не соответствует первой спецификации форматной строки. Каждое очередное обращение к scanf продолжает ввод символа, следующего сразу за последним обработанным.

Существует также функция sscanf, которая читает из строки (а не из стандартного ввода).

int sscanf(char *string, char *format, arg1, arg2,…)

Функция sscanf просматривает строку string согласно формату format и рассылает полученные значения в arg1, arg2 и т. д. Последние должны быть указателями.

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

• Пробелы или табуляции, которые игнорируются.

• Обычные символы (исключая %), которые, как ожидается, совпадут с очередными символами, отличными от символов-разделителей входного потока.

• Спецификации преобразования, каждая из которых начинается со знака % и завершается символом-спецификатором типа преобразования. В промежутке между этими двумя символами в любой спецификации могут располагаться, причем в том порядке, как они здесь указаны: знак * (признак подавления присваивания); число, определяющее ширину поля; буква h, l или L, указывающая на размер получаемого значения; и символ преобразования (o, d, x).

Спецификация преобразования управляет преобразованием следующего вводимого поля. Обычно результат помещается в переменную, на которую указывает соответствующий аргумент. Однако если в спецификации преобразования присутствует *, то поле ввода пропускается и никакое присваивание не выполняется. Поле ввода определяется как строка без символов-разделителей; оно простирается до следующего символа-разделителя или же ограничено шириной поля, если она задана. Поскольку символ новой строки относится к символам-разделителям, то sscanf при чтении будет переходить с одной строки на другую. (Символами-разделителями являются символы пробела, табуляции, новой строки, возврата каретки, вертикальной табуляции и перевода страницы.)

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

Перед символами-спецификаторами d, l, o, u и x может стоять буква h, указывающая на то, что соответствующий аргумент должен иметь тип short * (а не int *),или l (латинская ell), указывающая на тип long *. Аналогично, перед символами-спецификаторами e, f и g может стоять буква l, указывающая, что тип аргумента - double * (а не float *).

Таблица 7.2 Основные преобразования scanf

Символ Вводимые данные; тип аргумента d десятичное целое: int * i целое: int *. Целое может быть восьмеричным (с 0 слева) или шестнадцатеричным (с 0x или 0X слева) o восьмеричное целое (с нулем слева или без него); int * u беззнаковое десятичное целое; unsigned int * x шестнадцатеричное целое (с 0x или 0X слева или без них); int * c символы; char *. Следующие символы ввода (по умолчанию один) размещаются в указанном месте. Обычный пропуск символов- разделителей подавляется; чтобы прочесть очередной символ, отличный от символа-разделителя, используйте %1s s Строка символов(без обрамляющих кавычек); char *, указывающая на массив символов, достаточный для строки и завершающего символа '', который будет добавлен e, f, g число с плавающей точкой, возможно, со знаком; обязательно присутствие либо десятичной точки, либо экспоненциальной части, а возможно, и обеих вместе; float * % сам знак %, никакое присваивание не выполняется

Чтобы построить первый пример, обратимся к программе калькулятора из главы 4, в которой организуем ввод с помощью функции scanf:

#include ‹stdio.h›

main() /* программа-калькулятор */ {

 double sum, v;

 sum = 0;

 while (scanf ("%lf", &v) == 1)

  printf("t%.2fn", sum += v);

 return 0;

}

Предположим, что нам нужно прочитать строки ввода, содержащие данные вида

25 дек 1988

Обращение к scanf выглядит следующим образом:

int day, year; /* день, год */

char monthname[20]; /* название месяца */

scanf ("%d %s %d", &day, monthname, &year);

Знак & перед monthname не нужен, так как имя массива есть указатель.

В строке формата могут присутствовать символы, не участвующие ни в одной из спецификаций; это значит, что эти символы должны появиться на вводе. Так, мы могли бы читать даты вида mm/dd/yy с помощью следующего обращения к scanf:

int day, month, year; /* день, месяц, год */

scanf("%d/%d/%d", &day, &month, &year);

В своем формате функция scanf игнорирует пробелы и табуляции. Кроме того, при поиске следующей порции ввода она пропускает во входном потоке все символы- разделители (пробелы, табуляции, новые строки и т.д.). Воспринимать входной поток, не имеющий фиксированного формата, часто оказывается удобнее, если вводить всю строку целиком и для каждого отдельного случая подбирать подходящий вариант sscanf. Предположим, например, что нам нужно читать строки с датами, записанными в любой из приведенных выше форм. Тогда мы могли бы написать:

while (getline(line, sizeof(line)) › 0) {

 if (sscanf(line, "%d %s %d", &day, monthname, &year) == 3)

  printf("вepно: %sr", line); /* в виде 25 дек 1968 */

 else if (sscanf(line, "%d/%d/%d", &month, &day, &year) == 3)

  printf("вepно: %sn", line); /* в виде mm/dd/yy */

1 ... 39 40 41 42 43 44 45 46 47 ... 81
На этой странице вы можете бесплатно читать книгу Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган бесплатно.
Похожие на Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган книги

Оставить комментарий

Рейтинговые книги