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

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

                                   // в файл My_file

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

<p id="AutBody_Root558"><strong>27.6.2. Ввод</strong></p>

Ниже перечислены наиболее популярные функции из библиотеки 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 почти наверное приведет к повреждению памяти (байтов, находящихся за буфером), а повреждение памяти является основным инструментом для хакерских атак. Не считайте, что можете угадать максимальный размер буфера, достаточный на все случаи жизни. Возможно, что “субъект” на другом конце потока ввода — это программа, не соответствующая вашим критериям разумности.

Функция scanf считывает данные с помощью формата точно так же, как и функция printf. Как и функция printf, она может быть очень удобной.

void f

{

  int i;

  char c;

  double d;

  char* s = (char*)malloc(100);

  /* считываем данные в переменные, передаваемые как указатели: */

  scanf("%i %c %g %s", &i, &c, &d, s);

  /* спецификатор %s пропускает первый пробел и прекращает

     действие на следующем пробеле */

}

  Как и функция printf, функция scanf не является безопасной с точки зрения типов. Форматные символы и аргументы (все указатели) должны точно соответствовать друг другу, иначе во время выполнения программы будут происходить странные вещи. Обратите также внимание на то, что считывание данных в строку s с помощью спецификатора %s может привести к переполнению. Никогда не используйте вызовы gets или scanf("%s")!

  Итак, как же безопасно ввести символы? Мы можем использовать вид формата %s, устанавливающий предел количества считываемых символов. Рассмотрим пример.

char buf[20];

scanf("%19s",buf);

Нам требуется участок памяти, заканчивающийся нулем (содержание которого вводится функцией scanf), поэтому 19 — это максимальное количество символов, которое можно считать в массив buf. Однако этот способ не отвечает на вопрос, что делать, если некто введет больше 19 символов. Лишние символы останутся в потоке ввода и будут обнаружены при следующей попытке ввода.

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

while((x=getchar)!=EOF) {

  /* ... */

}

Макрос EOF, описанный в библиотеке stdio, означает “конец файла”; см. также раздел 27.4.

Альтернативы функций scanf("%s") и gets в стандартной библиотеке языка C++ от этих проблем не страдают.

string s;

cin >> s; // считываем слово

getline(cin,s); // считываем строку

<p id="AutBody_Root559"><strong>27.6.3. Файлы</strong></p>

В языке C (и C++) файлы можно открыть с помощью функции fopen, а закрыть — с помощью функции fclose. Эти функции, вместе с представлением дескриптора файлов FILE и макросом EOF (конец файла), описаны в заголовочном файле .

FILE *fopen(const char* filename, const char* mode);

int fclose(FILE *stream);

По существу, мы используем файлы примерно так:

void f(const char* fn, const char* fn2)

{

  FILE* fi = fopen(fn, "r");  /* открываем файл fn для чтения */

  FILE* fo = fopen(fn2, "w"); /* открываем файл fn для записи */

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT