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

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

Мы потихоньку втягиваемся в длинные и часто яростно оспариваемые вопросы стиля, которые, впрочем, часто не имеют большого значения. Мы объявляем указатель следующим образом:

char* p; // p — указатель на переменную типа char

Мы не принимаем стиль, продемонстрированный ниже.

char *p; /* p — нечто, что можно разыменовать, чтобы получить символ */

Пробел совершенно игнорируется компилятором, но для программиста он имеет значение. Наш стиль (общепринятый среди программистов на языке С++) подчеркивает тип объявляемой переменной, в то время как альтернативный стиль (общепринятый среди программистов на языке С) делает упор на использовании переменной. Мы не рекомендуем объявлять несколько переменных в одной строке.

char c, *p, a[177], *f; /*
разрешено, но может ввести в заблуждение */

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

char c = 'a'; /* символ завершения ввода для функции f */

char* p = 0; /* последний символ, считанный функцией f */

char a[177]; /* буфер ввода */

char* f; /* считывает данные в буфер a;

возвращает указатель
на первый считанный символ */

Кроме того, выбирайте осмысленные имена.

27.6. Ввод-вывод: заголовок stdio

В языке С нет потоков ввода-вывода

iostream
, поэтому мы используем стандартный механизм ввода-вывода языка С, определенный в заголовочном файле
<stdio.h>
. Эквивалентами потоков ввода и вывода
cin
и
cout
из языка С++ в языке С являются потоки
stdin
и
stdout
. Стандартные средства ввода-вывода языка С и потоки
iostream
могут одновременно использоваться в одной и той же программе (для одних и тех же потоков ввода-вывода), но мы не рекомендуем это делать. Если вам необходимо совместно использовать эти механизмы, хорошенько разберитесь в них (обратите особое внимание на функцию
ios_base::sync_with_stdio
), используя хороший учебник. См. также раздел Б.10.

27.6.1. Вывод

Наиболее популярной и полезной функцией библиотеки

stdio
является функция
printf
. Основным предназначением функции
printf
является вывод С-строки.

#include<stdio.h>

void f(const char* p)

{

printf("Hello, World!\n");

printf(p);

}

Это не очень интересно. Намного интереснее то, что функция

printf
может получать любое количество аргументов и начальную управляющую строку, которая определяет, как вывести дополнительные аргументы. Объявление функции
printf
в языке C выглядит следующим образом:

int printf(const char* format, ...);

Многоточие (

...
) означает “и, возможно, остальные аргументы”. Мы можем вызвать функцию
printf
так:

void f1(double d, char* s, int i, char ch)

{

printf("double %g string %s int %d char %c\n", d, s, i, ch);

}

где символы

%g
означают: “Напечатать число с плавающей точкой, используя универсальный формат”, символы
%s
означают: “Напечатать С-строку”, символы
%d
означают: “Напечатать целое число, используя десятичные цифры,” а символы
%c
означают: “Напечатать символ”. Каждый такой спецификатор формата связан со следующим, до поры до времени не используемым аргументом, так что спецификатор
%g
выводит на экран значение переменной
d
;
%s
— значение переменной
s
,
%d
— значение переменной
i
, а
%c
— значение переменной
ch
. Полный
список форматов функции
printf
приведен в разделе Б.10.2.

К сожалению, функция
printf
не является безопасной с точки зрения типов. Рассмотрим пример.

char a[] = { 'a', 'b' }; /* нет завершающего нуля */

void f2(char* s, int i)

{

printf("goof %s\n", i); /* неперехваченная ошибка */

printf("goof %d: %s\n", i); /* неперехваченная ошибка */

printf("goof %s\n", a); /* неперехваченная ошибка */}

Интересен эффект последнего вызова функции printf: она выводит на экран каждый байт участка памяти, следующего за элементом a[1], пока не встретится нуль. Такой вывод может состоять из довольно большого количества символов.

Недостаток проверки типов является одной из причин, по которым мы предпочитаем потоки

iostream
, несмотря на то, что стандартный механизм ввода-вывода, описанный в библиотеке
stdio
языков C и C++, работает одинаково. Другой причиной является то, что функции из библиотеки
stdio
не допускают расширения: мы не можем расширить функцию
printf
так, чтобы она выводила на экран значения переменных вашего собственного типа. Для этого можно использовать потоки
iostream
. Например, нет никакого способа, который позволил бы вам определить свой собственный спецификатор формата
%Y
для вывода структуры
struct Y
.

Существует полезная версия функции

printf
, принимающая в качестве первого аргумента дескриптор файла.

int fprintf(FILE* stream, const char* format, ...);

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

fprintf(stdout,"Hello, World!\n"); // идентично

// printf("Hello,World!\n");

FILE* ff = fopen("My_file","w"); // открывает файл My_file

// для записи

fprintf(ff,"Hello, World!\n"); // запись "Hello,World!\n"

// в файл My_file

Дескрипторы файлов описаны в разделе 27.6.3.

27.6.2. Ввод

Ниже перечислены наиболее популярные функции из библиотеки

stdio
.

int scanf(const char* format, ...); /* форматный ввод из потока stdin */

int getchar(void); /* ввод символа из потока stdin */

int getc(FILE* stream); /* ввод символа из потока stream*/

char* gets(char* s); /* ввод символов из потока stdin */

Простейший способ считывания строки символов — использовать функцию

gets
. Рассмотрим пример.

char a[12];

gets(a); /* ввод данных в массив символов a вплоть до символа '\n' */

Никогда не делайте этого! Считайте, что функция
gets
отравлена. Вместе со своей ближайшей “родственницей” — функцией
scanf("%s")
— функция
gets
является мишенью для примерно четверти успешных хакерских атак. Она порождает много проблем, связанных с безопасностью. Как в тривиальном примере, приведенном выше, вы можете знать, что до следующей новой строки будет введено не более 11 символов? Вы не можете этого знать. Следовательно, функция
gets
почти наверное приведет к повреждению памяти (байтов, находящихся за буфером), а повреждение памяти является основным инструментом для хакерских атак. Не считайте, что можете угадать максимальный размер буфера, достаточный на все случаи жизни. Возможно, что “субъект” на другом конце потока ввода — это программа, не соответствующая вашим критериям разумности.

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

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Охота на попаданку. Бракованная жена

Герр Ольга
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Охота на попаданку. Бракованная жена

Кай из рода красных драконов

Бэд Кристиан
1. Красная кость
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Кай из рода красных драконов

Хозяйка Проклятой Пустоши. Книга 2

Белецкая Наталья
2. Хозяйка Проклятой Пустоши
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка Проклятой Пустоши. Книга 2

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Потусторонний. Книга 2

Погуляй Юрий Александрович
2. Господин Артемьев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Потусторонний. Книга 2

Чапаев и пустота

Пелевин Виктор Олегович
Проза:
современная проза
8.39
рейтинг книги
Чапаев и пустота

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

Лютая

Шёпот Светлана Богдановна
Любовные романы:
любовно-фантастические романы
6.40
рейтинг книги
Лютая

Ведьмак (большой сборник)

Сапковский Анджей
Ведьмак
Фантастика:
фэнтези
9.29
рейтинг книги
Ведьмак (большой сборник)

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4

Ученик

Губарев Алексей
1. Тай Фун
Фантастика:
фэнтези
5.00
рейтинг книги
Ученик

Начальник милиции. Книга 5

Дамиров Рафаэль
5. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 5