Include stdio h что это

БлогNot. Лекции по C/C++: работа с файлами (stdio.h)

Лекции по C/C++: работа с файлами (stdio.h)

В лекции рассмотрен классический способ работы с файлами в C/C++, основанный на библиотеке stdio.h и доступе к данным через структуру FILE . Альтернативный современный механизм работы с файлами в языке C++ на основе потоков и библиотек , , будет изучен в следующей лекции.

Базовые функции для работы с файлами описаны в библиотеке stdio.h . Вся работа с файлом выполняется через файловую переменную — указатель на структуру типа FILE , определённую в стандартной библиотеке:

Открыть файл можно функцией fopen , имеющей 2 параметра:

Параметр имя_файла может содержать относительный или абсолютный путь к открываемому файлу:

1) "data.txt" — открывается файл data.txt из текущей папки

Важно: при запуске exe-файла "текущая папка" – та, где он находится; при отладке в IDE папка может быть иной, например, в Visual Studio при открытом консольном решении с именем Console файл следует разместить в папке Console/Console , а при запуске исполняемого файла не из IDE – в папке Console/Debug .

2) "f:\my.dat" — открывается файл my.dat из головной папки диска f:

3) имя файла запрашивается у пользователя:

Параметр режим_доступа определяет, какие действия будут разрешены с открываемым файлом, примеры его возможных значений:

1) "rt" — открываем для чтения текстовый файл;

2) "r+b" — открываем для произвольного доступа (чтение и запись) бинарный файл;

3) "at" – открываем текстовый файл для добавления данных в конец файла;

4) "w" — открываем файл для записи без указания того, текстовый он или бинарный.

Фактически, указание "r" или "t" не накладывает каких-либо ограничений на методы, которые мы будем применять для чтения или записи данных.

После открытия файла следует обязательно проверить, удалась ли эта операция. Для этого есть 2 основных подхода:

1) стандартный обработчик ferror (см. пособиe, п.8.7);

2) сравнить указатель, который вернула fopen , с константой NULL ( nullptr ) из стандартной библиотеки:

Пример. Приложение проверяет, удалось ли открыть файл из текущей папки, имя файла запрашивается у пользователя (Visual Studio)

Важно! Функции, возвращающие указатель, в том числе, fopen , считаются небезопасными в ряде новых компиляторов, например, Visual Studio 2015. Если их использование приводит не просто к предупреждению, а к генерации ошибок, есть 2 основных способа решения проблемы:

1) в соответствии с рекомендациями компилятора, заменить старые названия функций на их безопасные версии, например, strcpy на strcpy_s и fopen на fopen_s . При этом может измениться и способ вызова функций, например,

2) в начало файла (до всех #include ) включить директиву

Если используется предкомпиляция, то можно определить этот макрос в заголовочном файле stdafx.h .

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

Если файл форматированный, то есть, является текстовым и состоит из лексем, разделённых стандартными разделителями (пробел, табуляция, перевод строки), обмен данными с ним можно выполнять методами:

  • fscanf — для чтения
  • fprintf — для записи

Первым параметром этих функций указывается файловая переменная, в остальном работа совпадает со стандартными scanf и printf .

Пример. Файл text.txt в текущей папке приложения имеет следующий вид:

Прочитаем его как последовательность вещественных чисел.

1. Функции семейства scanf возвращают целое число — количество значений, которые успешно прочитаны в соответствии с указанным форматом. В реальных приложениях эту величину следует проверять в коде:

2. На "восприятие" программой данных может влиять установленная в приложении локаль. Например, если до показанного кода выполнен оператор результат работы кода может измениться (для русской локали разделителем целой и дробной части числа является запятая, а не точка).

3. Очередное чтение данных изменяет внутренний файловый указатель. Этот указатель в любой момент времени, пока файл открыт, показывает на следующее значение, которое будет прочитано. Благодаря этому наш код с "бесконечным" while не зациклился.

4. Код показывает, как читать из файла заранее неизвестное количество значений – это позволяет сделать стандартная функция feof (проверка, достигнут ли конец файла; вернёт не 0, если прочитано всё).

5. Распространённый в примерах из Сети код вида

в ряде компиляторов может породить неточности при интерпретации данных. Например, этот код может прочитать как последнее значение завершающий перевод строки в файле, благодаря чему последнее прочитанное значение "удвоится".

В качестве примера форматной записи в файл сохраним массив a из 10 целочисленных значений в файле с именем result.txt по 5 элементов в строке:

Важно! Ввод/вывод функциями библиотеки stdio.h буферизован, то есть, данные "пропускаются" через область памяти заданного размера, обмен данными происходит не отдельными байтами, а "порциями". Поэтому перед чтением данных желательно очищать буфер от возможных "остатков" предыдущего чтения методом fflush , а после записи данных следует обязательно закрывать файл методом fclose , иначе данные могут быть потеряны. Заметим, что консольный ввод/вывод "обычными" методами scanf и printf также буферизован.

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

  • fgetc и fputc — для посимвольного чтения и посимвольной записи данных;
  • fgets и fputs — для чтения и записи строк с указанным максимальным размером.

Как и в случае с функциями для чтения форматированных данных, у всех этих методов имеются аналоги для работы со стандартным вводом/выводом.

Пример. Читая файл, определить длину каждой строки в символах. Для решения задачи воспользуемся тем фактом, что строки завершаются символом "перевод строки" ( ‘
‘ ). Предполагается, что файл уже открыт для чтения.

Важно! Из-за особенностей реализации fgetc , без последней проверки за телом цикла код мог "не обратить внимания", например, на последнюю строку файла, состоящую только из пробелов и не завершающуюся переводом строки.

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

Важно! Без дополнительной обработки прочитанные из файла строки при выводе будут содержать лишние пустые строки между строками данных. Это происходит потому, что функция fgets читает строку файла вместе с символом перевода строки (точней, под Windows — с парой символов
, интерпретируемых как один), а puts добавляет к выводимой строке ещё один перевод строки.

Если максимальная длина строки принципиально не ограничена, помочь может либо предварительное посимвольное чтение файла для её определения, либо работа с файлом как с бинарными данными. Бинарный файл отличается от текстового тем, что необязательно состоит из печатаемых символов со стандартными разделителями между ними. Соответственно, для него не имеет смысла понятие "строки данных", а основной способ работы с ним – чтение и запись наборов байт указанного размера. Основные функции для чтения и записи бинарных данных – fread и fwrite соответственно. В базовой реализации они имеют по 4 параметра:

  • void *buffer — нетипизированный указатель на место хранения данных;
  • size_t (unsigned) size — размер элемента данных в байтах.
  • size_t count — максимальное количество элементов, которые требуется прочитать (записать);
  • FILE *stream — указатель на структуру FILE

Пример. Целочисленный массив a запишем в двоичный файл.

Учитывая, что данные массива хранятся в последовательно идущих адресах памяти, цикл for для записи мы могли заменить одним оператором:

Подход к чтению данных с помощью fread аналогичен. Например, если файл уже открыт для чтения в режиме "rb":

Для файлов, открытых в режиме "r+b", разрешены и чтение, и запись (произвольный доступ). Поэтому при работе с такими файлами нужны функции позиционирования файлового указателя:

  • функции fgetpos и ftell позволяют выполнить чтение текущей позиции указателя в файле;
  • функции fseek и fsetpos позволяют осуществить переход к нужной позиции в файле.

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

Материал для чтения из пособия: пп. 8.6-8.11. Обратите внимание на таблицы с описанными прототипами функций ввода/вывода.

Рекомендуемые задачи: базовое задание включает две задачи, первая из которых предполагает обработку файла как текстовых данных, вторая – как бинарных. В качестве дополнительной третьей задачи может быть предложена реализация одной из задач 1, 2, содержащая консольный интерфейс и меню.

Про conio.h и почему его не надо использовать:

Для ввода/вывода через цветную консоль во многих источниках используются методы библиотеки conio.h . Следует учитывать, что её реализации в компиляторах от Borland и Microsoft значительно отличаются, а в компиляторах под Unix/Linux реализации conio.h могут отсутствовать.

Как вариант, в компиляторах Visual Studio можно использовать аналоги conio.h от сторонних разработчиков, например, открытый проект coniow.h. Законченный пример кода, реализующего несложное консольное меню для Visual Studio, есть вот здесь. Предполагается, что к проекту подключены заголовочный файл coniow.h и файл исходного кода coniow.c .

Оглавление серии

05.11.2015, 09:20; рейтинг: 29715

Я бы хотел поделиться тем, как «научить» стандартные функции, такие как printf, работать в вашем C++ проекте, на примере проекта в Atmel Studio. Так как JTAG отладчика у меня нет, а отлаживать ПО как-то нужно, решил выводить информацию по UART. Сам по себе передатчик может вывести лишь байт, дебажная инфомация же представлена в виде строк. Существует несколько библиотек для буферизированной работы с UART, но я хочу воcпользоваться именно printf из stdio.h.

Создадим пустой С++ executable проект в Atmel Studio. Пропишем:

Перейдём к implementation и обратим внимание на пример:

Попробуем вставить этот код в наш проект:

Жмем build solution и видим следующие ошибки:

Ссылаются они на строку:

Google приводит нас сюда. Designated Initializers описаны тут.

Макрос FDEV_SETUP_STREAM не компилируется в С++, так как он использует Designated Initializers. Для решения проблемы предлагается использовать полную инициализацию. Вернемся к файлу stdio.h. Чуть ниже обьявления FDEV_SETUP_STREAM находится прототип:

И комментарий к нему:

Попробуем воспользоваться им вместо макроса FDEV_SETUP_STREAM. Код проекта примет следующий вид:

Попробуем собрать проект… Build succeeded. Подключаем микроконтроллер к COM порту. Открываем терминал, смотрим.

Надеюсь, данная статья поможет начинающим в отладке.

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.

Теперь приступаем к разбору первой программы.

находится директива препроцессора #include (директивы препроцессора начинаются с символа "#" — "решётка", или "номер" )

"include" означает "включить", то есть — "включить в состав программы заголовочный файл "stdio.h"(h — header, заголовок)

В свою очередь, в файле stdio.h определены стандартные функции ввода-вывода: STanDard Input/Output Header.

Напоминаю, что язык Си создавался для Unix, а в юниксе стандартными средствами ввода-вывода являются соответственно клавиатура и дисплей. Именно эти функции и включает заголовочный файл stdio.h

Следующая строка объявляет функцию main:

Означает она вот что.
Функция main в нашем случае не имеет аргументов ("void" — "ничто") и возвращает целое число(Integer number).

Дальше, в фигурных скобках, содержится тело функции.
Фигурные скобки — это своего рода замена командам begin и end. Коротко и ясно, и не нужно тратить время на массу букв )))

— это, так сказать, Сишный аналог команды "begin"

Далее следует тело функции (в него входит всё, что находится внутри фигурных скобок):

printf — это означает "форматированный вывод на печать(в данном случае "печать" происходит на дисплее).
Распространённая ошибка — набор вместо "printf" просто "print", без буквы "f".
Буква "f" — это важно, это сокращение от слова "formatted", то есть "форматированный".

Вызывается эта функция из библиотеки stdio, объявленной в инструкции препроцессора #include
В кавычках находится выражение, которое требуется вывести на дисплей, а символы "
" означают, что после вывода выражения следует перейти на следующую строку.
Точка с запятой должна быть в конце каждого оператора — таковы правила языка Си.
И пропуск этого символа — также одна из наиболее частых ошибок.

Следующий оператор у нас

Он возвращает нулевое значение(ноль — целое число) функции main в случае успешного её выполнения, что требуется по правилам языка Си.

— а это, соответственно, Сишный "end", конец функции.

UPD: специально по предложению тов. Шимановского pan_szymanowski видоизменил программу, назвав её "slavakpss.c", а исполняемый файл — "slava".

#include
int main (void)
<
printf("Слава КПСС!
");
return 0;
>


[an error occurred while processing the directive]
Карта сайта