Вызов 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
, более полную информацию можно найти в хороших учебниках по языку С, например в книге
Б.10.3. Строки в стиле языка С
Строки в стиле языка C представляют собой массивы элементов типа char
, завершающиеся нулем. Эти строки обрабатываются функциями, описанными в заголовках
(или
; примечание:
) и
.
Эти функции оперируют строками в стиле языка С с помощью указателей 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, описаны в заголовке
, а функции выделения памяти — в заголовке
.
См. также раздел 27.5.2.
Б.10.5. Дата и время
В заголовке
можно найти несколько типов и функций, связанных с датами и временем.
Структура tm
определяется примерно так:
struct tm {
int tm_sec; // секунда минуты [0:61]; 60 и 61
//"високосные" секунды
int tm_min; // минута часа [0,59]
int tm_hour; // час дня [0,23]
int tm_mday; // день месяца [1,31]
int tm_mon; // месяц года [0,11]; 0 — январь (примечание: не [1:12])
int tm_year; // год с 1900- го года ; 0 — 1900-й год,
// 102 — 2002-й год
int tm_wday; // дни, начиная с воскресенья [0,6]; 0 — воскресенье
int tm_yday; // дней после 1 января [0,365]; 0 — 1 января
int tm_isdst; // часы летнего времени
};
Функции для работы с датами и временем
clock_t clock; // количество тактов таймера после старта программы
time_t time(time_t* pt); // текущее календарное
// время
double difftime(time_t t2, time_t t1); // t2–t1 в секундах
tm* localtime(const time_t* pt); // локальное время для *pt
tm* gmtime(const time_t* pt); // время по Гринвичу (GMT) tm для
// *pt или 0