Краткий конспект семинарских занятий по языку C - Н.Д. Васюкова_ И.В. Машечкин_ В.В.Тюляева_ Е.М.Шляховая (1114683), страница 7
Текст из файла (страница 7)
while(fgets(s,81,f1)!=NULL && i<10) {
i++;
fputs(s,f2);
}
fclose(f1); fclose(f2);
}
Следует помнить, что
char *fgets(char *s,int n,FILE *f);
читает не более n-1 литер в массив s, прекращая чтение, если встретился ‘\n’, который включается в массив. В любом случае массив дополняется нулевым байтом. Если в решении задачи 1 заменить второй параметр при вызове функции fgets на 80, то строки будут переписываться без искажения, но их количество может оказаться меньше десяти, если в исходном файле окажутся строки максимальной длины.
Примечание. Для текстовых файлов использование функции
int feof(FILE *f)
имеет некоторые особенности. Если при чтении из файлового потока f достигнут конец файла, то возвращается ненулевое значение, в противном случае возвращается ноль. При этом, если не предпринималась попытка прочитать информацию за концом файла, то функция feof не будет сигнализировать о том, что достигнут конец файла. Например, чтобы скопировать содержимое одного файла в другой можно было бы произвести следующие действия:
FILE f1,f2;
char str[80];
. . .
while(!feof(f1)) {
fgets(str,80,f1);
fputs(str,f2);
}
Но тогда последняя строка исходного файла будет переписана дважды.
В языке Си предусмотрен также, так называемый прямой ввод-вывод, осуществляемый с помощью функций: fread и fwrite.
Функция
size_t fread(void *p,size_t size,size_t nobj,
FILE *f)
читает из входного потока в массив p nobj объектов размером size безо всякого преобразования. Функция возвращает количество прочитанных объектов и ноль, если исчерпан файл.
Обратная ей функция:
size_t fwrite(void *p,size_t size,size_t nobj,
FILE *f)
пишет в выходной поток из массива p nobj объектов размером size в непреобразованном виде. Возвращает количество записанных объектов, которое в случае ошибки меньше nobj.
Задача 2. В непустом файле с именем “sss” в непреобразованном(бинарном) виде записаны вещественные числа (double). Поменять местами первое максимальное число с последним минимальным.
main()
{ FILE *f;
double max,min,a;
long max_p,min_p;
if((f=fopen(“sss”,”r+”))==NULL) exit(1);
fread(&a,sizeof(double),1,f);
max=min=a;
max_p=min_p=0;
while (fread(&a,sizeof(double),1,f)) {
if(a>max){
max=a;
max_p=ftell(f)-sizeof(double);
}
if(a<=min){
min=a;
min_p= ftell(f)-sizeof(double);
}
}
fseek(f,min_p,SEEK_SET);
fwrite(&max,sizeof(double),1,f);
fseek(f,max_p,SEEK_SET);
fwrite(&min,sizeof(double),1,f);
fclose(f);
}
При работе с однородными бинарными файлами часто возникает задача определения количества объектов, записанных в файл. Например, пусть в бинарном файле записаны числа типа long double.
Для определения количества этих чисел достаточно поставить указатель на конец файла:
FILE *f;
long pos,n;
. . .
fseek(f,0L,SEEK_END);
с помощью функции ftell определить номер текущей позиции (нумерация начинается с нуля):
pos=ftell(f);
и разделить его на размер объекта:
n=pos/sizeof(long double);
Задачи.
-
Написать функцию сортировки файла, содержащего числа типа long, записанные в файл с помощью функции fwrite, не используя дополнительных файлов. Используя эту функцию отсортировать два файла и слить их в один упорядоченный файл. Результат записать в первый файл.
-
Инвертировать файл, содержащий числа типа int, не используя дополнительных файлов.
а) Написать функцию для записи в файл анкет студентов. Каждая анкета есть структура:
struct anketa { char fio[20];
struct { int day, month, year; } data;
short m[3];
};
в которой поле fio – фамилия студента, поле data – дата рождения, а поле m – оценки, полученные студентом в последнюю сессию.
-
Написать функцию, которая из файла анкет студентов удаляет всех “двоичников”.
-
Оставить в файле только строки, содержащие некоторую подстроку. Имя файла и подстроку задавать в виде параметров командной строки.
а)Длина строк не превышает 255 символов.
б) Длина строк не ограничена.
-
Удалить из файла все строки длиной более пятидесяти символов. Длина строк не ограничена. Имя файла задается в командной строке.
-
Преобразовать файл, усекая строки до 50-ти символов.
-
Упорядочить текстовый файл (лексикографически сравнить строки, длина строки не более 80-ти символов), используя один из методов внешней сортировки.
-
Написать функцию-упаковщик файлов. Коды символов лежат в диапазоне от 0 до 127. Последовательность из n одинаковых символов заменяется на байт со значением –n и байт, содержащий код символа. Рассмотреть два варианта: a) n<=127; b) n – любое.
-
Написать функцию-распаковщик файлов, см. задачу 8.
-
Заменить в файле все “begin” на ‘{‘ ,а “end” на ‘}’.
Приложение 1. Приоритеты и порядок вычисления операторов.
Обозначение | Операция | Порядок выполнения |
( ) | вызов функции | Слева направо |
[ ] | индексное выражение | |
-> . | операции доступа к полям записей | |
! | логическое “НЕ” | Справа налево |
~ | поразрядное “НЕ” | |
++ -- | инкрементная и декрементная операции | |
- | унарный минус | |
(тип) | приведение к типу | |
* | косвенная адресация | |
& | взятие адреса | |
sizeof | получение размера объекта | |
* / % | умножение, деление, остаток от деления | Слева направо |
+ - | сложение, вычитание | Слева направо |
<< >> | поразрядные сдвиги | Слева направо |
< <= > >= | операции отношения | Слева направо |
== != | операции отношения | Слева направо |
& | поразрядное “И” | Слева направо |
^ | поразрядное исключающее “ИЛИ” | Слева направо |
| | поразрядное “ИЛИ” | Слева направо |
&& | логическое “И” | Слева направо |
|| | логическое “ИЛИ” | Слева направо |
? : | тернарный оператор | Справа налево |
= += -= *= /= %= <<= >>= &= ^= |= | операции присваивания | Справа налево |
, | операция запятая | Слева направо |
Приоритет операций убывает сверху вниз.
Операции из одной ячейки таблицы имеют одинаковый приоритет.
ЛИТЕРАТУРА.
-
Б.Керниган, Д.Ритчи. Язык программирования Си.
2-ое издание. Москва, Финансы и статистика. 1992г.
-
Б.И.Березин, С.Б.Березин. Начальный курс С и С++.
Москва, Диалог-МИФИ, 1996г.
-
С.О.Бочков, Д.М.Субботин. Язык программирования Си для персонального компьютера. Москва, СП “Диалог”, Радио и связь, 1990г.
-
И.В.Машечкин, М.И.Петровский, П.Д.Скулачев, А.Н.Терехин. Системное Программное Обеспечение: файловые системы ОС Unix и Windows NT. Москва, Диалог-МГУ,1997г.
1 В Си ';' не разделяет операторы, как в других языках программирования, например, в Паскале, а является неотъемлемой частью оператора.
2 Запись if(x==y){…};else{…} приведет к ошибке компиляции (здесь ; рассматривается компилятором как пустой оператор после "сокращенного" условного, а следовательно, для else нет соответствующего if )
3 Речь идет об условной адресации в Си-машине. Эта адресация может не совпадать с реальной адресацией ОЗУ ЭВМ.
4 Следует заметить, что в приведенном ниже примере коллизии имени функции f с именем формального параметра или с переменной f, определенной внутри функции, не будет из-за различия областей видимости.
5 Здесь возникает некая терминологическая путаница, поскольку, как будет рассказано ниже, ключевое слово static используется для определения статических переменных, а в данном контексте с помощью static задаются границы области видимости.
6 Мы не рассматриваем особенности функционирования конкретных трансляторов, а описываем наиболее часто используемые возможности препроцессора.
7 при этом в текст программы вместо DOUBLED_NUMBER подставится 10*2, а не 20
8 В этой теме рассматривается не строгий синтаксис деклараций, а способ разобраться в том, как понимать декларируемое имя.
9 Спецификация языка не очень четко выделяет класс синтаксической конструкции typedef, мы остановимся на термине «оператор»
10 Задачи №4 и №5 взяты из первого издания книги Б.Керниган, Д.Ритчи «Язык программирования Си»
51