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

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

Жанры

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

Нулевая или слишком маленькая ширина поля никогда не приводит к усечению вывода; дополнение вывода нулями или пробелами производится только тогда, когда заданная ширина поля превышает реальную.

Поскольку в языке C нет пользовательских типов в смысле языка C++, в нем нет возможностей для определения форматов вывода для таких классов, как

complex
,
vector
или
string
.

Стандартный поток вывода

stdout
в языке C соответствует потоку
cout
. Стандартный поток ввода
stdin
в языке С соответствует потоку
cin
.
Стандартный поток сообщений об ошибках
stderr
в языке С соответствует потоку
cerr
. Эти соответствия между стандартными потоками ввода-вывода в языке C и C++ настолько близки, что потоки ввода-вывода как в стиле языка С, так и стиле языка С++ могут использовать один и тот ж буфер. Например, для создания одного и того же потока вывода можно использовать комбинацию операций над объектами
cout
и
stdout
(такая ситуация часто встречается в смешанном коде, написанном на языка С и С++). Эта гибкость требует затрат. Для того чтобы получить более высокую производительность, не смешивайте операции с потоками из библиотек
stdio
и
iostream
при работе с одним и тем же потоком, вместо этого вызывайте функцию
ios_base::sync_with_stdio(false)
перед выполнением первой операции ввода-вывода. В библиотеке
stdio
определена функция
scanf
, т.е. операция ввода, похожая на функцию
printf
. Рассмотрим пример.

int x;

char s[buf_size];

int i = scanf("Значение x равно '%d', а значение s равно '%s'\n",&x,s);

Здесь функция

scanf
пытается считать целое число в переменную
x
и последовательность символов, не являющихся разделителями, в массив
s
. Неформатные символы указывают, что они должны содержаться в строке ввода. Рассмотрим пример.

"Значение x равно '123', а значение s равно 'string '\n"

Программа введет число

123
в переменную
x
и строку "
string
", за которой следует
0
, в массив
s
. Если вызов функции
scanf
завершает работу успешно, результирующее значение (
i
в предыдущем вызове) будет равно количеству присвоенных аргументов-указателей (в данном примере это число равно
2
); в противном случае оно равно
EOF
. Этот способ индикации ввода уязвим для ошибок (например, что произойдет, если вы забудете вставить пробел после строки "
string
" в строке ввода?). Все аргументы функции
scanf
должны быть указателями. Мы настоятельно рекомендуем не использовать эту функцию.

Как же ввести данные, если мы вынуждены использовать библиотеку

stdio
? Один и из распространенных ответов гласит: “Используйте стандартную библиотечную функцию
gets
”.

// очень опасный код:

char s[buf_size];

char* p = gets(s); // считывает строку в массив s

Вызов

p=gets(s)
будет вводить символы в массив
s
, пока не обнаружится символ перехода на новую строку или не будет достигнут конец файла. В этом случае в конец строки
s
после последнего символа будет вставлен
0
. Если обнаружен конец файла или возникла ошибка, то указатель p устанавливается равным
NULL
(т.е.
0
); в противном случае он устанавливается равным
s
. Никогда не используйте функцию
gets(s)
или ее эквивалент
scanf("%s",s))!
За прошедшие годы создатели вирусов облюбовали их слабые места: генерируя вводную строку, переполняющую буфер ввода (в данном примере строку
s
), они научились взламывать программы и атаковать компьютеры. Функция
sprintf
страдает от таких же проблем, связанных с переполнением буфера.

Библиотека

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

Обратите внимание на то, что результатом этих функций является число типа

int
(а не переменная типа
char
или макрос
EOF
). Рассмотрим типичный цикл ввода в программе на языке С.

int ch; /* но не char ch; */

while ((ch=getchar)!=EOF) { /* какие-то действия */ }

Не применяйте к потоку два последовательных вызова

ungetc
. Результат такого действия может оказаться непредсказуемым, а значит, программа не будет переносимой.

Мы описали не все функции из библиотеки

stdio
, более полную информацию можно найти в хороших учебниках по языку С, например в книге K&R.

Б.10.3. Строки в стиле языка С

Строки в стиле языка C представляют собой массивы элементов типа

char
, завершающиеся нулем. Эти строки обрабатываются функциями, описанными в заголовках
<cstring>
(или
<string.h>
; примечание: но не
<string>
) и
<cstdlib>
.

Эти функции оперируют строками в стиле языка С с помощью указателей

char*
(указатели
const char*
ссылаются на ячейки памяти, предназначенные исключительно для чтения).

Обратите внимание на то, что в языке C++ функции

strchr
и
strstr
дублируются, чтобы обеспечить безопасность типов (они не могут преобразовать тип
const char*
в тип
char*
, как их аналоги в языке C); см. также раздел 27.5.

Функции извлечения символов просматривают строку в стиле языка С в поисках соответственно форматированного представления числа, например "

124
" и "
1.4
". Если такое представление не найдено, функция извлечения возвращает
0
. Рассмотрим пример.

int x = atoi("fortytwo"); /* x становится равным 0 */

Б.10.4. Память

Функции управления памятью действуют в “голой памяти” (без известного типа) с помощью указателей типа

void*
(указатели
const void*
ссылаются на ячейки памяти, предназначенные только для чтения).

Функции

malloc
и ей подобные не вызывают конструкторы, а функция
free
не вызывает деструкторы. Не применяйте эти функции к типам, имеющим конструкторы или деструкторы. Кроме того, функция
memset
также никогда не должна применяться к типам, имеющим конструктор.

Функции, начинающиеся с приставки mem, описаны в заголовке

<cstring>
, а функции выделения памяти — в заголовке
<cstdlib>
.

См. также раздел 27.5.2.

Б.10.5. Дата и время

В заголовке

<ctime>
можно найти несколько типов и функций, связанных с датами и временем.

Структура

tm
определяется примерно так:

struct tm {

int tm_sec; // секунда минуты [0:61]; 60 и 61

//"високосные" секунды

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

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Сердце Дракона. Том 10

Клеванский Кирилл Сергеевич
10. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.14
рейтинг книги
Сердце Дракона. Том 10

Последний Паладин. Том 4

Саваровский Роман
4. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 4

Низший

Михайлов Дем Алексеевич
1. Низший!
Фантастика:
боевая фантастика
7.90
рейтинг книги
Низший

Разведчик. Заброшенный в 43-й

Корчевский Юрий Григорьевич
Героическая фантастика
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.93
рейтинг книги
Разведчик. Заброшенный в 43-й

Император

Рави Ивар
7. Прометей
Фантастика:
фэнтези
7.11
рейтинг книги
Император

Темный Лекарь

Токсик Саша
1. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь

Возвращение Безумного Бога 5

Тесленок Кирилл Геннадьевич
5. Возвращение Безумного Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Возвращение Безумного Бога 5

Рядовой. Назад в СССР. Книга 1

Гаусс Максим
1. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Рядовой. Назад в СССР. Книга 1

Его темная целительница

Крааш Кира
2. Любовь среди туманов
Фантастика:
фэнтези
5.75
рейтинг книги
Его темная целительница

Теневой Перевал

Осадчук Алексей Витальевич
8. Последняя жизнь
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Теневой Перевал

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 18

Сапфир Олег
18. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 18

По дороге пряностей

Распопов Дмитрий Викторович
2. Венецианский купец
Фантастика:
фэнтези
героическая фантастика
альтернативная история
5.50
рейтинг книги
По дороге пряностей