C не усложняет обработку текста. Он убирает слои абстракции и оставляет вам «голую» механику. Если вы изучали документацию по C, то, вероятно, заметили, что все функции ввода/вывода текста находятся в библиотеке stdio. Это аббревиатура от Standard Input/Output (стандартный ввод/вывод). Именно она является фундаментом взаимодействия программ на C с внешним миром.

Большинство начинающих начинают работу с stdin и stdout. Это стандартные потоки. Они обозначают, откуда программа получает данные и куда отправляет результаты. Если вашему приложению нужен только один источник ввода и один приемник вывода, вам не нужна сложная работа с файлами. Вы просто передаете данные через командную строку.

Шесть базовых потоков

Заголовок stdio предоставляет шесть конкретных команд для взаимодействия с этими потоками. Они просты. Прямые.

  • printf : Записывает отформатированный текст в stdout.
  • scanf : Читает отформатированные данные из stdin.
  • puts : Выводит строку на экран.
  • gets : Читает строку текста с клавиатуры.
  • putc : Записывает один символ в stdout.
  • getc или getchar : Читает один символ из stdin.

Зачем их использовать? Потому что их можно перенаправлять. Здесь проявляется сила C. Вам не нужно менять код, чтобы читать данные из файла вместо клавиатуры. Вы просто меняете команду, которую вводите в терминале.

Простой подсчет символов

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

Этот код ожидает ввода. Вы вводите строки. Когда закончите, нажмите CTRL-D. Это сигнализирует о конце файла (eof ). Функция gets возвращает ноль при достижении конца файла, что прерывает цикл. Итоговый подсчет выводится на экран.

Но вот в чем хитрость. Вам не пришлось редактировать код, чтобы подсчитать символы в файле. Вы просто добавили небольшую инструкцию в оболочку (shell).

Перенаправление ввода и вывода

Если вы скомпилировали эту программу в исполняемый файл с именем xxx, вы можете передать ей файл.

Уголковая скобка перенаправляет содержимое filename в stdin. Программа думает, что читает с клавиатуры. На самом деле она читает с диска.

Вы также можете использовать конвейеры (pipes). Это передает вывод одной команды напрямую в другую.

Результат тот же. Команда cat выводит содержимое файла в стандартный вывод. Конвейер передает его вашей программе.

Вы также можете перенаправить вывод. Вместо того чтобы видеть подсчет на экране, вы можете сохранить его.

Теперь xxx читает из filename и записывает результат в новый текстовый файл с именем out. Это мощная возможность. Она позволяет связывать инструменты вместе без написания дополнительного кода для обработки файловых указателей.

Когда потоков недостаточно

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

В таких случаях вам нужны функции прямой работы с файлами. Они также находятся в stdio, но работают с файловыми указателями, а не со стандартными потоками.

  • fopen : Открывает файл для чтения или записи.
  • fclose : Закрывает файл, когда работа с ним завершена.
  • feof : Проверяет, достигнут ли конец файла.
  • fprintf : Записывает отформатированные данные в конкретный файл.
  • fscanf : Читает отформатированные данные из конкретного файла.
  • fputs : Записывает строку в файл.
  • fgets : Читает строку из файла.
  • fputc : Записывает символ в файл.
  • fgetc : Читает символ из файла.

Эти функции дают вам больше контроля. Вы можете управлять несколькими потоками одновременно. Вы можете точно решить, какие данные в какой файл записываются.

Какой путь вы выберете? Простоту перенаправления stdin или контроль прямых файловых указателей? Это зависит от того, что вы создаете. Для быстрых скриптов перенаправление — король. Для сложных приложений вам понадобятся функции работы с файлами.

Идеального ответа нет. Есть только компромиссы.