No Image

Функции ввода вывода в си

СОДЕРЖАНИЕ
3 просмотров
10 марта 2020

Функциональность ввода-вывода языка Си по текущим стандартам реализуется на низком уровне. Язык Си абстрагирует все файловые операции, превращая их в операции с потоками байтов, которые могут быть как «потоками ввода», так и «потоками вывода». В отличие от некоторых ранних языков программирования, язык Си не имеет прямой поддержки произвольного доступа к файлам данных; чтобы считать записанную информацию в середине файла, программисту приходится создавать поток, ищущий в середине файла, а затем последовательно считывать байты из потока.

Потоковая модель файлового ввода-вывода была популяризирована во многом благодаря операционной системе Unix, написанной на языке Си. Большая функциональность современных операционных систем унаследовала потоки от Unix, а многие языки семейства языков программирования Си унаследовали интерфейс файлового ввода-вывода языка Си с небольшими отличиями (например, PHP). Стандартная библиотека C++ отражает потоковую концепцию в своём синтаксисе (смотрите iostream).

Содержание

Открытие файла при помощи функции fopen [ править | править код ]

Файл открывается при помощи функции fopen , которая возвращает информацию потока ввода-вывода, прикреплённого к указанному файлу или другому устройству, с которого идет чтение (или в который идет запись). В случае неудачи функция возвращает нулевой указатель.

Схожая функция freopen библиотеки Си выполняет аналогичную операцию после первого закрытия любого открытого потока, связанного с её параметрами.

Они объявляются как

Функция fopen по сути представляет собой «обертку» более высокого уровня системного вызова open операционной системы Unix. Аналогично, fclose является оберткой системного вызова Unix close , а сама структура FILE языка Си зачастую обращается к соответствующему файловому дескриптору Unix. В POSIX-окружении функция fdopen может использоваться для инициализации структуры FILE файловым дескриптором. Тем не менее, файловые дескрипторы как исключительно Unix-концепция не представлены в стандарте языка Си.

Параметр mode (режим) для fopen и freopen должен быть строковый и начинаться с одной из следующих последовательностей:

режим описание начинает с..
r rb открывает для чтения начала
w wb открывает для записи (создаёт файл в случае его отсутствия). Удаляет содержимое и перезаписывает файл. начала
a ab открывает для добавления (создаёт файл в случае его отсутствия) конца
r+ rb+ r+b открывает для чтения и записи начала
w+ wb+ w+b открывает для чтения и записи. Удаляет содержимое и перезаписывает файл. начала
a+ ab+ a+b открывает для чтения и записи (создаёт файл в случае его отсутствия) конца

Значение «b» зарезервировано для двоичного режима С. Стандарт языка Си описывает два вида файлов — текстовые и двоичные — хотя операционная система не требует их различать (однако, для некоторых компиляторов, например LCC, указание ‘b’ при работе с бинарным файлом принципиально важно!). Текстовый файл — файл, содержащий текст, разбитый на строки при помощи некоторого разделяющего символа окончания строки или последовательности (в Unix — одиночный символ перевода строки
; в Microsoft Windows за символом перевода строки следует знак возврата каретки)
. При считывании байтов из текстового файла, символы конца строки обычно связываются (заменяются) с переводом строки для упрощения обработки. При записи текстового файла одиночный символ перевода строки перед записью связывается (заменяется) с специфичной для ОС последовательностью символов конца строки. Двоичный файл — файл, из которого байты считываются и выводятся в «сыром» виде без какого-либо связывания (подстановки).

При открытом файле в режиме обновления (‘+‘ в качестве второго или третьего символа аргумента обозначения режима) и ввод и вывод могут выполняться в одном потоке. Тем не менее, запись не может следовать за чтением без промежуточного вызова fflush или функции позиционирования в файле ( fseek , fsetpos или rewind ), а чтение не может следовать за записью без промежуточного вызова функции позиционирования в файле. [1]

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

Закрытие потока при помощи fclose [ править | править код ]

Функция fclose принимает один аргумент: указатель на структуру FILE потока для закрытия.

Функция возвращает нуль в случае успеха и EOF в случае неудачи. При нормальном завершении программы функция вызывается автоматически для каждого открытого файла.

Чтение из потока [ править | править код ]

при помощи fgetc [ править | править код ]

Функция fgetc применяется для чтения символа из потока.

В случае успеха, fgetc возвращает следующий байт или символ из потока (зависит от того, файл «двоичный» или «текстовый», как выше обсуждалось). В противном случае, fgetc возвращает EOF . (Отдельный тип ошибок можно определить вызовом ferror или feof с указателем на файл.)

Читайте также:  Звук когда человек тупит

Стандартный макрос getc также определён в , успешно работая как fgetc , кроме одного: будучи макросом, он может обрабатывать свои аргументы более одного раза.

Стандартная функция getchar также определена в , она не принимает аргументов, и эквивалентна getc(stdin) .

«Ловушка» EOF [ править | править код ]

Распространённой ошибкой является использование fgetc , getc или getchar для присваивания результата переменной типа char перед сравнением его с EOF . Следующий фрагмент кода демонстрирует эту ошибку, а рядом приведён корректный вариант:

Ошибка Правильно

Нужно учитывать систему, в которой тип char , длина которого составляет 8 бит (в частности, архитектура x86), представляет 256 различных значений. getchar может возвращать любой из 256 возможных символов, а также может возвращать EOF для обозначения конца файла, значение которого не может совпадать ни с одним из значений char .

Когда результат getchar присваивается переменной типа char , которая может представить лишь 256 различных значений, происходит вынужденная потеря информации — при сжатии 257 значений в 256 «мест» происходит коллизия. Значение EOF при конвертации в char становится неотличимым от любого из остальных 256 символов. Если этот символ обнаружен в файле, код, приведённый выше, может принять его за признак конца файла, или, что ещё хуже, если тип char — беззнаковый, тогда с учётом того, что EOF — значение отрицательное, оно никогда не сможет стать равным любому беззнаковому char , и таким образом, пример выше не закончится на метке конца файла, а будет выполняться вечно, повторно печатая символ, получающийся при конвертации EOF в char .

В системах, где int и char одинакового размера [ каких? ] [ источник не указан 3263 дня ] , даже «правильный» вариант будет работать некорректно из-за сходства EOF и другого символа. Правильным вариантом обработки подобной ситуации является проверка feof и ferror после того, как getchar вернет EOF . Если feof определит, что конец файла ещё не достигнут, а ferror «сообщит», что ошибок нет, то EOF , возвращённый getchar , может считаться текущим символом. Такие дополнительные проверки делаются редко, так как большинство программистов считает, что их код никогда не будет выполняться на подобных системах с «большим char ». Другой способ состоит в использовании проверки при компиляции, что UINT_MAX > UCHAR_MAX , которая хотя бы предотвратит компиляцию на подобных системах.

при помощи fgets [ править | править код ]

Функция fgets применяется для чтения строки из потока. Считывание происходит до тех пор пока не будет достигнут конец строки (hex:0D0A, эквивалентны в листингах
) или длина строки, в которую происходит считывание. Предположим, у нас есть файл some_file.txt с текстом

в результате выполнения мы получим

Функция strlen определяет длину строки по количеству символов до ‘’ так например

fwrite [ править | править код ]

В языке программирования Си функции fread и fwrite соответственно реализуют файловые операции ввода и вывода. fread и fwrite объявлены в .

Запись в файл при помощи fwrite [ править | править код ]

fwrite определяется как

Функция fwrite записывает блок данных в поток. Таким образом запишется массив элементов array в текущую позицию в потоке. Для каждого элемента запишется size байт. Индикатор позиции в потоке изменится на число байт, записанных успешно. Возвращаемое значение будет равно count в случае успешного завершения записи. В случае ошибки возвращаемое значение будет меньше count .

Следующая программа открывает файл пример.txt, записывает в него строку символов, а затем его закрывает.

Запись в поток при помощи fputс [ править | править код ]

Функция fputc применяется для записи символа в поток.

Параметр c «тихо» конвертируется в unsigned char перед выводом. Если прошло успешно, то fputc возвращает записанный символ. Если ошибка, то fputc возвращает EOF .

Стандартный макрос putc также определён в , работая в общем случае аналогично fputc , за исключением того момента, что будучи макросом, он может обрабатывать свои аргументы более одного раза.

Стандартная функция putchar , также определённая в , принимает только первый аргумент, и является эквивалентной putc(c, stdout) , где c является упомянутым аргументом.

Пример использования [ править | править код ]

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

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

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

  • printf() — для вывода информации
  • scanf() — для ввода информации.
Читайте также:  Лучший телефон для школьника младших классов

Вывод информации

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

Общая форма записи функции printf() :

СтрокаФорматов состоит из следующих элементов:

  • управляющих символов;
  • текста, представленного для непосредственного вывода;
  • форматов, предназначенных для вывода значений переменных различных типов.

Объекты могут отсутствовать.

Управляющие символы не выводятся на экран, а управляют расположением выводимых символов. Отличительной чертой управляющего символа является наличие обратного слэша ‘’ перед ним.

Основные управляющие символы:


  • ’ — перевод строки;
  • ‘ ’ — горизонтальная табуляция;
  • ‘v’ — вертикальная табуляция;
  • ‘’ — возврат на символ;

  • ’ — возврат на начало строки;
  • ‘a’ — звуковой сигнал.

Форматы нужны для того, чтобы указывать вид, в котором информация будет выведена на экран. Отличительной чертой формата является наличие символа процент ‘%’ перед ним:

  • %d — целое число типа int со знаком в десятичной системе счисления;
  • %u — целое число типа unsigned int ;
  • %x — целое число типа int со знаком в шестнадцатеричной системе счисления;
  • %o — целое число типа int со знаком в восьмеричной системе счисления;
  • %hd — целое число типа short со знаком в десятичной системе счисления;
  • %hu — целое число типа unsigned short ;
  • %hx — целое число типа short со знаком в шестнадцатеричной системе счисления;
  • %ld — целое число типа long int со знаком в десятичной системе счисления;
  • %lu — целое число типа unsigned long int ;
  • %lx — целое число типа long int со знаком в шестнадцатеричной системе счисления;
  • %f — вещественный формат (числа с плавающей точкой типа float );
  • %lf — вещественный формат двойной точности (числа с плавающей точкой типа double );
  • %e — вещественный формат в экспоненциальной форме (числа с плавающей точкой типа float в экспоненциальной форме);
  • %c — символьный формат;
  • %s — строковый формат.

Строка форматов содержит форматы для вывода значений. Каждый формат вывода начинается с символа % . После строки форматов через запятую указываются имена переменных, которые необходимо вывести.
Количество символов % в строке формата должно совпадать с количеством переменных для вывода. Тип каждого формата должен совпадать с типом переменной, которая будет выводиться на это место. Замещение форматов вывода значениями переменных происходит в порядке их следования.
Пример на Си

Результат работы программы

Тот же самый код может быть представлен с использованием одного вызова printf :

Табличный вывод

При указании формата можно явным образом указать общее количество знакомест и количество знакомест, занимаемых дробной частью:

В приведенном примере 10 — общее количество знакомест, отводимое под значение переменной; 5 — количество позиций после разделителя целой и дробной части (после десятичной точки). В указанном примере количество знакомест в выводимом числе меньше 10, поэтому свободные знакоместа слева от числа заполняются пробелами. Такой способ форматирования часто используется для построения таблиц.

Ввод информации

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

Строка форматов аналогична функции printf() .
Для формирования адреса переменной используется символ амперсанд ‘&’ :
адрес = &объект

Строка форматов и список аргументов для функции обязательны.

Результат работы программы:

Функция scanf( ) является функцией незащищенного ввода, т.к. появилась она в ранних версиях языка Си. Поэтому чтобы разрешить работу данной функции в современных компиляторах необходимо в начало программы добавить строчку

Другой вариант — воспользоваться функцией защищенного ввода scanf_s( ) , которая появилась несколько позже, но содержит тот же самый список параметров.

Для организации интерфейса с пользователем предусмотрены базовые возможности потокового (консольного) ввода/вывода. Наиболее универсальными функциями ввода/вывода являются функции printf() и scanf(), входящие в библиотеку stdio.h. Формат этих функций во многом схож.

Рассмотрим функцию printf(). Эта функция использует "управляющую строку” и набор "аргументов". Инструкции, передаваемые функции printf() в управляющей строке, зависят от типа данных аргумента. Например, при выводе на экран целого числа применяется формат %d, в то время как для переменных с плавающей точкой используется формат %f. Если же на экран выводится только текст, то кроме строки, заключенной в кавычки других аргументов нет. Результатом выполнения следующей программы:

Читайте также:  Css переход на новую строку

int i; // объявление i, как переменной целого типа

float х; // объявление х, как переменной с плавающей точкой

printf("Пример вывода на экранп");

printf("4e4oro числа i = %d ", i);

printf( M H числа с плавающей точкой х = %f ", х);

будет следующий текст, выведенный на экран дисплея:

Пример вывода на экран

целого числа i = 10

и числа с плавающей точкой х = 3.75

В данной программе сначала объявляются переменные, которые будут использоваться в дальнейшем, имеющие целый тип (int) и десятичный с плавающей точкой (float). Это же отмечено в комментариях, которые идут после двойной косой черты (//). Комментарии используются для записи каких-либо заметок, полезных самому программисту. Здесь можно оставлять любые пояснения, в процессе работы программы они игнорируются.

После того, как переменным присвоены значения, выполняется вывод на экран. При первом вызове функции printf() на экран выводится только текст "Пример вывода на экран”. Также в этой строке программы содержится управляющий символ ”п”, он отвечает за переход на следующую строку и возврат в крайнее левое положение. Без этого символа весь текст выводился бы на экран в одну строку.

Две заключительные строки программы выводят на экран текст и значения переменных. Можно сказать, что при выводе на экран символы формата заменяются значениями переменных. Так, %d заменяется значением переменной i, равным 10, a %f – значением переменной х, т. е. 3.75. В одном вызове функции printf() может быть несколько символов форматирования. Например, последние две строчки можно заменить одной:

printf("neaoro числа i=%d и числа с плавающей точкой x=%f ", i, х);

Результат выполнения программы был бы тем же.

В общем виде формат, указываемый при обращении к функции printf(), выглядит следующим образом:

рпЩДуправляющая строка, аргумент1, аргумент2, . );

Аргумент 1, аргумент2 и т. д. – это печатаемые параметры, которые могут быть переменными (i, х), константами (25, 3.14159) или даже выражениями, которые будут вычислены перед выводом на экран (2*3, i+5).

Управляющая строка – это строка символов, показывающая, как должны быть напечатаны параметры. Таким образом, можно заключить, что управляющая строка содержит информацию двух различных видов:

  • 1. Символы, печатаемые текстуально.
  • 2. Идентификаторы данных, называемые также "спецификациями преобразования".

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

%d – десятичное целое число (int);

%f- число с плавающей точкой (float или double);

%с – отдельный символ (char);

%s – строка символов;

%е – число с плавающей точкой (float или double), экспоненциальная запись;

%g – используется вместо %е или %f, если он короче (float или double);

%о – восьмеричное число без знака (int);

%х – шестнадцатеричное число без знака (int);

%u – десятичное число без знака (int).

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

printf( M TeKCTOBoe сообщениеп");

puts( M TeKCTOBoe сообщение");

Для ввода данных в языке Си используется функция scanf(). Формат этой функции аналогичен формату функции printf(). Здесь также указывается управляющая строка, за которой идет список аргументов. Основное различие двух этих функций заключается в особенностях данного списка. Функция printf() использует имена переменных, константы и выражения, в то время как scanf() – только указатели на переменные. К счастью, для применения этой функции можно ничего не знать об указателях, достаточно перед именем переменной писать символ (означающий адрес переменной). Пример применения функции scanf() для ввода целого числа:

Одна из наиболее распространенных ошибок состоит в написании вместо приведенной выше строки следующей:

scanf("%d", i); //неправильно!

Это приводит к возникновению логической ошибки, которую не сразу заметно. Никогда не забывайте об этом!

Функция scanf() использует практически тот же набор символов спецификации преобразования, что и функция printf(). Отличия в случае scanf() следующие:

  • 1. Отсутствует спецификация %g.
  • 2. Спецификации %f и %е эквивалентны.
  • 3. Для ввода целых чисел типа short применяется спецификация %h.

рпЩД"Квадрат числа %f равен %f ", num, num * num);

Функция scanf() является универсальной функцией ввода. Это значит, что она позволяет читать данные все типов. Однако в Си имеются и другие функции ввода, такие как gets() и getchar(), которые более удобны для выполнения конкретных задач – чтения одиночных символов или строк, содержащих пробелы.

Комментировать
3 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
Adblock detector