Вы находитесь на странице: 1из 10

Лабораторная работа N 5

Ввод-вывод в языке программирования C

Цель и задача работы: ознакомление с функциями ввода-вывода, изучение


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

Теоретические положения

Функция ввода отвечает за ввод с указанного устройства и перевод данных,


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

Простой ввод-вывод

В любых программах функции ввода/вывода играют важную роль. Рассмотрим


функции, которые встречаются в большинстве программ.
Самый простой механизм ввода – чтение по одному символу из стандартного
входного потока (с клавиатуры) с помощью функции getchar().
Формат процедуры:
int getchar (void);
Здесь определен тип единственного аргумента (void) и тип возвращаемого
функцией значения (int).
Инструкция вида:
x=getchar();
присваивает переменной x очередной вводимый символ. Переменная x должна иметь
символьный или целый тип. Другая функция putchar(х) выдает значение переменной
х в стандартный выходной поток (на экран дисплея).
Формат процедуры:
int putchar (int);
Функции getchar() и putchar() объявлены в стандартном подлючаемом файле
stdio.h.
1
Ввод и вывод данных

Две функции printf() для вывода и scanf() для ввода позволяют преобразовать
численные величины в символьное представление и обратно. Они также позволяют
выполнить форматированный ввод-вывод.
Функция:
printf(format, arg1, arg2, ...)
печатает свои аргументы в соответствии с форматом. Строка format содержит
обычные символы, которые просто копируются в выходной поток, и спецификации
преобразований, каждая из которых вызывает преобразование и печать очередного
аргумента.
Каждая спецификация преобразования начинается с символа % и заканчивается
символом преобразования. Между % и символом преобразования могут находиться:
– знак минус, который говорит о выравнивании преобразованного аргумента по
левому краю его поля;
– строка цифр, задающая минимальную ширину поля. Преобразованное число
будет напечатано в поле по крайней мере этой ширины, а если необходимо, то и в
более широком. Если преобразованный аргумент имеет меньше символов, чем
указанная ширина поля, то он будет дополнен слева (или справа, если было указано
выравнивание по левому краю) заполняющими символами до этой ширины.
Заполняющим символом обычно является пробел, а если ширина поля указывается с
лидирующим нулем, то этим символом будет нуль (лидирующий нуль в данном
случае не означает восьмеричной ширины поля);
– точка, которая отделяет ширину поля от следующей строки цифр;
– строка цифр (точность), которая указывает максимальное число символов
строки, которые должны быть напечатаны, или число печатаемых справа от
десятичной точки цифр для переменных типа float или double;
– модификатор длины L, который указывает, что соответствующий элемент
данных имеет тип long, а не int.
Ниже приводятся символы преобразования и их смысл:
d или i – аргумент преобразуется к десятичному виду;
c – аргумент преобразуется в беззнаковую восьмеричную форму (без
лидирующего нуля);
X или x – аргумент преобразуется в беззнаковую шестнадцатеричную форму
(без лидирующих 0X);
u – аргумент преобразуется в беззнаковую десятичную форму;
c – аргумент рассматривается как отдельный символ;
2
s – аргумент является строкой: символы строки печатаются до тех пор, пока не
будет достигнут нулевой символ или не будет напечатано количество символов,
указанное в спецификации точности;
E или e – аргумент, рассматриваемый как переменная типа float или double,
преобразуется в десятичную форму в виде [-]M.NNNNNNE[+-]XX, где длина строки
из N определяется указанной точностью. Точность по умолчанию равна 6;
f – аргумент, рассматриваемый как переменная типа float или double,
преобразуется в десятичную форму в виде [-]MMM.NNNNNN, где длина строки из N
определяется указанной точностью. Точность по умолчанию равна 6;
G или g- используется или формат %E (e) или %f, какой короче. Незначащие
нули не печатаются.
Если идущий за % символ не является символом преобразования, то печатается
сам этот символ. Следовательно, символ % можно напечатать, указав %%.
Функция printf() использует строку формата для определения числа аргументов
и их типов. Если количество аргументов окажется недостаточным или они будут
иметь типы, не соответствующие формату, то могут быть получены бессмысленные
результаты.
Функция scanf() является аналогом printf() и выполняет при вводе форматные
преобразования в обратном направлении.
Функция
scanf(format, arg1, arg2, ...)
читает символы из стандартного ввода, интерпретирует их в соответствии с
форматом, указанном в format, и помещает результаты в аргументы. Каждый из
аргументов должен быть указателем.
Форматная строка может содержать:
– пробелы, табуляции или символы новой строки ("символы пустых
промежутков"), которые игнорируются;
– все символы таблицы ASCII, кроме %;
– спецификации преобразования, состоящие из символа %, необязательного
символа подавления присваивания *, необязательного числа, задающего
максимальную ширину поля и символа преобразования.
Спецификация преобразования управляет преобразованием следующего поля
ввода. Результат помещается в переменную, которая указывается соответствующим
аргументом.
Если с помощью символа * указано подавление присваивания, то это поле
ввода просто пропускается и никакого присваивания не производится. Поле ввода
определяется как строка символов, которые отличны от символов промежутков. Оно
3
продолжается до следующего символа промежутка, или пока не будет исчерпана
ширина поля, если она указана. Отсюда следует, что при поиске нужного поля,
функция scanf() будет пересекать границы строк, т.к. символ новой строки входит в
число промежутков.
Символ преобразования определяет интерпретацию поля ввода. Допускаются
следующие символы преобразования:
d или i – ожидается десятичное целое, соответствующий аргумент должен быть
указателем на целое;
o – ожидается восьмеричное целое (с лидирующим нулем или без него),
соответствующий аргумент должен быть указателем на целое;
x – ожидается шестнадцатеричное целое (с лидирующими 0X или без них),
соответствующий аргумент должен быть указателем на целое;
c – ожидается отдельный символ, соответствующий аргумент должен быть
указателем на символы. Обеспечивается чтение каждого следующего символа, даже
если это символ промежутка.
s – ожидается символьная строка, соответствующий аргумент должен быть
указателем на массив символов, который достаточно велик для принятия строки и
добавляемого в конце символа \0;
f – ожидается число с плавающей точкой, соответствующий аргумент должен
быть указателем на переменную типа float;
Е или e – ожидается число с плавающей точкой. Формат ввода переменной
типа float включает необязательный знак, строку цифр, возможно содержащую
десятичную точку, и необязательное поле экспоненты, состоящее из буквы E (e), за
которой следует целое, возможно имеющее знак.
Перед символами преобразования d (i), о и x может стоять модификатор длины
L, который означает, что в списке аргументов должен находиться указатель на
переменную типа long, а не типа int. Модификатор длины L также может стоять перед
символами преобразования E (e) или f, говоря о том, что в списке аргументов должен
находиться указатель на переменную типа double, а не типа float.
Выполнение функции scanf() заканчивается когда она исчерпает свою
форматную строку, или когда некоторый элемент ввода не совпадет со
спецификацией преобразования. В качестве своего значения scanf() возвращает число
правильно введенных элементов. Это число может быть использовано для
определения числа элементов ввода. При выходе на конец файла возвращается EOF.
Пример:
printf(\n %5.3f, 3.14159);
/* Вывод происходит с новой строки. Выводится число с плавающей точкой,
для которого отводится поле шириной 5, в котором 3 позиции отводится

4
под дробную часть. Результат округляется до третьего знака после
запятой.
*/

Результат на экране дисплея выглядит следующим образом:


3.142

scanf(%d %c, &a, &b);


/* Вводятся значения переменных целого и символьного типа. */

Строка ввода может иметь следующий вид:


12 w

Стандартные типы данных в С

int (Числа с фиксированной точкой)


Диапазон представления чисел: от -32768 до +32767.
В памяти занимает 2 байта.
char (Символьный тип)
Все символы таблицы ASCII.
В памяти занимает 1 байт.
float (Числа с плавающей точкой)
Диапазон представления чисел: от -3.4*10-38 до 3.4*1038.
В памяти занимает 4 байта.
double (Числа с плавающей точкой двойной точности)
Диапазон представления чисел: от -1.7*10-308 до 1.7*10308.
В памяти занимает 8 байт.

Файловый ввод-вывод

Под файлом будет подразумеваться порция информации на диске со своим


именем. Часто бывает необходимо ввести некоторые данные из файла или вывести
результаты в файл. Например, бывает необходимо обрабатывать массивы, которые
слишком велики, чтобы полностью разместится в памяти.
Для работы с файлом в языке C необходима ссылка на файл. Для определения
такой ссылки существует структура FILE, описанная в файле stdio.h. Данная
структура содержит все необходимые поля для управления файлами, например:
текущий указатель буфера, текущий счетчик байтов, базовый адрес буфера ввода-
вывода, номер файла.
5
Открытие файла

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


существует функция fopen().
Пример использования функции:
FILE *new;
new=fopen(“text.txt”,”r”);

Данная функция имеет два аргумента:


1) имя файла (если файл находится не в текущей директории, то имя файла
может включать в себя путь);
2) аргумент, определяющий способ открытия файла. Приведем основные
значения данного аргумента:
“r” : считывание из файла;
“w”: запись в файл;
“a” : дополнение файла;
“r+”: открытие существующего файла для корректировки (чтение и запись);
“w+”: создание нового файла для корректировки (чтение и запись). Если
файл с этим именем уже существует, он будет переписан;
“a+”: открытие для добавления. Открывает (или создает если файл не
существует) файл, для записи в конец файла.
При открытии файла в режиме “r” открывается существующий файл. Если же
использованы режимы “w” и “a”, и файл с указанным именем не найден, то создается
новый файл.
Если использовать режим “w” для существующего файла, то его содержимое
стирается, и только затем происходит запись.
Если добавить “t” (например “rt”, ”w+t”), то файл отрывается в текстовом
режиме, а при добавлении “b” (“ab”, “r+b”) – в двоичном режиме.
По умолчанию файл открывается в текстовом режиме.
Функция при успешном открытии возвращает указатель на файл, а при
неудачном – значение ‘NULL’, определенное в stdio.h как 0.

Закрытие файла

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


fclose().
Пример использования функции:
int close_result;
close_result=fclose(new);
6
Аргументом функции является указатель на файл, который необходимо
закрыть. Функция возвращает значение 0, если файл был закрыт успешно, и –1 в
противном случае.

Ввод-вывод одиночного символа в файл

Выполняется при помощи функций getc() и putc().


Данные функции выполняют считывание и, соответственно, запись одиночного
символа в файл. Рассмотрим пример их использования в программе:
FILE *in, *out;
char ch;
ch=getc(in); /* считывание символа из файла, на который указывает in*/
putc(ch, out); /* запись считанного символа в файл,
на который указывает out */

Функция getc() использует в качестве параметра указатель на файл, а


возвращает считанный символ. Напротив, функция putc() использует два аргумента:
символ, который выводится в файл и указатель на этот файл. При успешном
выполнении функция возвращает выведенный символ, а при ошибке – EOF.

Ввод-вывод в файл по формату

Выполняется функциями fprintf() и fscanf(). Они работают аналогично


функциям printf() и scanf(), но им нужен дополнительный параметр для ссылки на
файл, который является первым в списке аргументов.
Пример, иллюстрирующий работу этих функций:
#include<stdio.h>
void main()
{
FILE *fi;
int age;

fi=fopen(“sam”,”r”);
fscanf(fi,”%d”,&age);
fclose(fi);
fi=fopen(“data”,”a”);
fprintf(fi,”Sam is %d.\n”,age);
fclose(fi);
}

Ввод-вывод символьных массивов в файл

Выполняется функциями fgets() и fputs().


Рассмотрим использование функций на примере:
7
#include<stdio.h>
#define MAX 80
void main()
{
FILE *f;
char string[MAX];

f=fopen(“story”,”r”);
while(fgets(string,MAX,f)!=NULL)
fputs(string, stdout);
}

Данная программа выводит содержимое файла “story” в стандартный файл


вывода (на экран) строка за строкой.
Функция fgets() имеет три аргумента: символьный массив, предельную длину
считываемой строки и указатель на файл. Функция прекращает работу при
считывании символа новой строки или после считывания символов общим числом
меньше на единицу, чем указывает второй аргумент (в данном примере 79). В любом
случае символ ‘\0’ добавляется в конец строки.
Функция возвращает NULL, если встречает символ EOF (символ конца файла),
определенный в файле stdio.h как -1.
Функция fputs() записывает строку (свой первый аргумент) в файл, указатель на
который является вторым аргументом. Возвращает EOF, если встречается символ
EOF, или возникает ошибка.
Мы рассмотрели восемь функций, предназначенных для ввода-вывода при
работе с файлами. Существует еще одна функция, которая служит для изменения
текущей позиции в файле.

Изменение текущей позиции в файле

Функция fseek() позволяет установить текущую позицию в файле в любое


положение. Она имеет три аргумента: указатель на файл, аргумент типа long,
указывающий, на сколько символов необходимо сместиться от начального положения
(положительный, если смещение происходит вперед, и отрицательный, если назад), и
,наконец, третий аргумент, определяющий начальное положение. Начальное
положение определяется символическими константами, определенными в файле
stdio.h:
Константа Значение Положение
SEEK_SET 0 Начало файла
SEEK_CUR 1 Текущая позиция
SEEK_END 2 Конец файла

8
Например, оператор
fseek(f,-10,SEEK_END)
делает текущей позицию, находящуюся за десять символов до конца, в файле, на
который указывает первый аргумент.
Функция возвращает 0 при успешном выполнении и –1 при возникновении
ошибки (например, при попытке передвинуться за границы файла).

Задание

Написать программу, реализующую обработку данных и файловый ввод-вывод


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

Варианты заданий

1) Убрать из текста лишние пробелы, т.е. там, где они встречаются больше
одного раза, оставить один пробел.
2) Подсчитать количество символов в заданном тексте.
3) Подсчитать количество слов и число предложений (предложения
оканчиваются точкой, слова разделяются запятыми).
4) Определить, какая буква чаще всего встречается в заданном тексте.
5) Если строка начинается с цифры, то перед ней поставить левую круглую
скобку, а в конец строки - правую круглую скобку.
6) Подсчитать число цифр в данном тексте и их сумму.
7) Перед каждым символом поставить порядковый номер в тексте.
8) Определить переменную "студент", содержащую следующие поля: имя,
фамилия, отчество студента, название института, номер группы. Данные считать из
текстового файла. Вывести данные о студентах, которые учатся в одном и том же
институте, и в одной группе.
9) Определить, входит ли заданное слово в текст. Если да, то сколько раз.
10) Удвоить в тексте каждую литеру.
11) Напечатать в алфавитном порядке все буквы, входящие в текст.
12) Подсчитать сумму чисел, записанных в тексте.
13) В тексте записаны слова через пробел. Вывести их в алфавитном порядке.
14) Напечатать самое длинное слово, найденное в тексте.
9
15) Во всех словах заменить первую букву на последнюю, а последнюю на
первую.
16) Удалить из текста все последующие вхождения первой буквы.
17) Оставить в слове только первые вхождения каждой буквы.
18) Заданное число, от 1 до 1999, напечатать римскими цифрами XLVI и т.д.
19) Определить, является ли текст правильной записью римскими цифрами
целого числа от 1 до 1999. Если да, то напечатать это число арабскими цифрами.
20) Удалить из текста каждое N-е вхождение в него заданного символа.
21) Удалить из текста каждое N-е вхождение в него заданного слова.
22) Задан текст. Вывести этот текст, подчеркивая (ставя в следующей строке
под этим символом минус) все входящие в него цифры.
23) Определить, равны ли два заданных файла.
24) Заменить заданное слово в тексте на другое слово.
25) Определить строку максимальной длины и вывести ее.
26) Подсчитать, сколько раз в тексте встречается заданное слово.
27) Выбросить из текста заданный знак, где бы он не встречался.
28) Удалить из текста каждое четное предложение.
29) Отформатировать текст следующим образом: каждое предложение должно
иметь свой порядковый номер; начинаться с красной строки.
30) Подсчитать, сколько раз в тексте встречается заданный знак.
31) Удалить из текста все предложения, в которых запятые встречаются более
2-х раз.
32) В тексте перед каждым предложением, в котором встречается заданное
слово, поставить восклицательный знак "!".

10