Файл: Лабораторная работа 1 Изучение среды разработки программ 3 Лабораторная работа 2 Исследование базовых типов данных языка Си 18.doc
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 271
Скачиваний: 3
СОДЕРЖАНИЕ
Лабораторная работа № 1Изучение среды разработки программ
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Лабораторная работа № 2Исследование базовых типов данных языка Си
Лабораторная работа № 4Применение управляющих инструкций языка для организации ветвлений в программе
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
ЗАДАНИЕ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
Лабораторная работа № 5Исследование циклов
Лабораторная работа № 6Применение массивов и указателей для решения прикладных задач
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Лабораторная работа № 7Исследование массивов и указателей
Лабораторная работа № 8Применение функций работы со строками для решения прикладных задач
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Практическое занятие № 6Использование функций для работы с массивами
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Практическое занятие № 7Программирование рекурсивных алгоритмов
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Практическое занятие № 8Применение производных типов данных для решения прикладных задач
ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Лабораторная работа № 5Исследование методов доступа к файлам данных
Лабораторная работа № 6Исследование связанных списков данных
В Си существует два типа потоков: текстовые (text) и двоичные (binary).
Текстовый поток - это последовательность символов. При передаче символов из потока на экран, часть из них не выводится (например, символ возврата каретки, перевода строки).
Двоичный поток - это последовательность байтов, которые однозначно соответствуют тому, что находится на внешнем устройстве.
Прежде чем читать или записывать информацию в файл, он должен быть открыт и тем самым связан с потоком. Это можно сделать с помощью библиотечной функции fopen(). Она берет внешнее представление файла (например, c:\my_prog.txt) и связывает его с внутренним логические именем, которое используется далее в программе. Логическое имя - это указатель на требуемый файл. Его необходимо определить; делается это, например, так:
FILE *fp;
Здесь FILE - имя типа, описанное в стандартном заголовочном файле stdio.h, fp - указатель на файл. Обращение к функции fopen() в программе осуществляется выражением:
fp = fopen("спецификация_файла",
"способ_использования_файла");
Спецификация файла (т.е. имя файла и путь к нему) может, например, иметь вид: "c:\\my_prog.txt" - для файла my_prog.txt на диске с:.
Способ использования файла задается следующими символами:
-
r – (от read) открыть существующий файл для чтения; -
w – (от write) создать новый файл для записи (если файл с указанным именем существует, то он будет переписан); -
а – (от add) дополнить файл (открыть существующий файл для записи информации, начиная с конца файла, или создать файл, если он не существует);
Тип файлового потока задается ключом t (текстовый) или b (бинарный). Если режим t или b не задан (например, r, w или а), то он определяется значением глобальной переменной _fmode. Если fmode=0_BINARY, то файлы открываются в двоичном режиме, а если _fmode=0_TEXT - в текстовом режиме. Константы 0_BINARY и 0_ТЕXТ определены в файле fcntl.h.
Если в результате обращения к функции fopen( ) возникает ошибка, то она возвращает указатель на константу NULL.
Рекомендуется использовать следующий способ открытия файла:
if ((fp = fopen("c:\\my_prog.txt", "rt")) == NULL)
{
puts("Открыть файл не удалось\n")
return 0;
}
После окончания работы с файлом он должен быть закрыт. Это делается с помощью библиотечной функции
fclose(). Она имеет следующий прототип:
int fclose(FILE *fp);
При успешном завершении операции функция fclose() возвращает значение нуль. Любое другое значение говорит об ошибке.
Рассмотрим стандартные функции для работы с файлами последовательного доступа:
1. Функция putc() записывает символ в файл и имеет следующий прототип:
int putc(int с, FILE *fp);
Здесь fp - указатель на файл, возвращенный функцией fopen(), с - символ для записи (переменная с имеет тип int, но используется только младший байт). При успешном завершении putc() возвращает записанный символ, в противном случае возвращается константа EOF. Она определена в файле stdio.h и имеет значение (-1).
2. Функция getc() читает символ из файла и имеет следующий прототип:
int getc(FILE *fp);
Здесь fp - указатель на файл, возвращенный функцией fopen(). Эта функция возвращает прочитанный символ. Соответствующее значение имеет int, но старший байт равен нулю. Если достигнут конец файла, то getc возвращает значение ЕОF.
3. Функция feof() определяет конец файла при чтении двоичных данных и имеет следующий прототип:
int feof(FILE *fp);
Здесь fp - указатель на файл, возвращенный функцией fopen(). При достижении конца файла возвращается ненулевое значение, в противном случае возвращается 0.
4. Функция fputs() записывает строку символов в файл. Она отличается от функции puts() только тем, что в качестве второго параметра должен быть записан указатель на переменную файлового типа.
Например:
fputs("Ехаmple", fp);
При возникновении ошибки возвращается значение EOF.
5. Функция fgets() читает строку символов из файла. Она отличается от функции gets( ) тем, что в качестве второго параметра должно быть записано максимальное число вводимых символов плюс единица, а в качестве третьего - указатель на переменную файлового типа. Строка считывается целиком, если ее длина не превышает указанного числа символов, в противном случае функция возвращает только заданное число символов. Рассмотрим пример:
fgets(string, n, fp);
Функция возвращает указатель на строку string при успешном завершении и константу NULL в случае ошибки либо достижения конца файла.
Рассмотрим другие библиотечные функции, используемые для работы с файлами прямого доступа (все они описаны в файле stdio.h):
1. Функция fseek()
позволяет выполнять чтение и запись с произвольным доступом и имеет следующий прототип:
int fseek(FILE *fp, long count, int access);
Здесь fp - указатель на файл, возвращенный функцией fopen(), count - номер байта относительно заданной начальной позиции, начиная с которого будет выполняться операция, access - способ задания начальной позиции.
Переменная access может принимать следующие значения:
0 - начальная позиция задана в начале файла;
1 - начальная позиция считается текущей;
2 - начальная позиция задана в конце файла.
При успешном завершении возвращается нуль, при ошибке - ненулевое значение.
2. Функция ferror() позволяет проверить правильность выполнения последней операции при работе с файлами. Имеет следующий прототип:
int ferror(FILE *fp);
В случае ошибки возвращается ненулевое значение, в противном случае возвращается нуль.
3. Функция remove( ) удаляет файл и имеет следующий прототип:
int remove(char *file_name);
Здесь file_name - указатель на строку со спецификацией файла. При успешном завершении возвращается нуль, в противном случае возвращается ненулевое значение.
4. Функция rewind() устанавливает указатель текущей позиции в начало файла и имеет следующий прототип:
void rewind(FILE *fp);
5. Функция fread() предназначена для чтения блоков данных из потока. Имеет прототип:
unsigned fread(void *ptr, unsigned size,
unsigned n, FILE *fp);
Она читает n элементов данных, длиной size байт каждый, из заданного входного потока fp в блок, на который указывает указатель ptr. Общее число прочитанных байтов равно произведению n*size. При успешном завершении функция fread() возвращает число прочитанных элементов данных, при ошибке - 0.
6. Функция fwrite() предназначена для записи в файл блоков данных. Имеет прототип:
unsigned fwrite(void *ptr, unsigned size,
unsigned n, FILE *fp);
Она добавляет n элементов данных, длиной size байт каждый, в заданный выходной файл fp. Данные записываются с позиции, на которую указывает указатель ptr. При успешном завершении операции функция fwrite() возвращает число записанных элементов данных, при ошибке - неверное число элементов данных.
2. Подход с использованием возможностей языка С++
Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику. Потоки С++ в отличие от функций ввода/вывода в стиле Си основаны на понятии класса, которые мы пока не изучаем. Поэтому рассмотрим только порядок использования файловых потоков С++ без объяснения теории.
Файловый поток для чтения открывается следующим образом:
ifstream идентификатор_потока(имя_файла,ключи_потока);
Например:
ifstream input("input.txt",ios::in);
- открывается файловый поток с идентификатором input для чтения из файла. Такой файловый поток должен быть по аналогии с Си и обязательно закрыт: input.close();
Файловый поток для записи открывается так:
ofstream идентификатор_потока(имя_файла,ключи_потока);
Например:
ofstream output("output.txt",ios::out);
Этот поток также должен быть закрыт:
output.close();
Как же работать с такими потоками? Очень просто:
int main()
{
int n,k;
float f;
char str[100];
ifstream input("input.txt",ios::in);
ofstream output("output.txt",ios::out);
input>>n;
input>>k;
n=n+k;
output<
input>>f;
f=f+2;
output<
input>>str; output<
input>>str; output<
input.close();
output.close();
return 0;
}
Если исходным содержимым файла input.txt было следующее:
5
10
-5.56783345
Hello world!
то в файл output.txt запишется следующее:
15
-3.56783
Hello, world!!!
ЗАДАНИЕ НА ИССЛЕДОВАНИЕ
1. Работа с неструктурированными данными
Для исследования различных методов доступа к файлам данных необходимо выполнить следующие подготовительные действия:
-
Создать в Блокноте следующий текстовый файл:
У меня спросили: сколько будет x Опер y ?
А я не знаю! А n Опер k ? Тоже!
Помогите!
Например:
У меня спросили: сколько будет 7 * 2 ?
А я не знаю! А 9 / 4 ? Тоже!
Помогите!
-
Вам известна структура файла. Вывести содержимое файла на экран, а в выходной файл записать результаты:
x Опер y = Рез1
n Опер k = Рез2
Например:
7 * 2 = 14
9 / 4 = 2.25
-
Исходные данные берутся из таблицы согласно варианта:
Вар. | x | Опер | y | n | Опер | k | Вар. | x | Опер | y | n | Опер | k |
1 | 15 | + | 4 | 7 | * | 8 | 9 | 23 | + | 37 | 13 | * | 5 |
2 | 18 | - | 19 | 18 | / | 4 | 10 | 7 | - | 42 | 37 | / | 6 |
3 | 9 | * | 6 | 56 | - | 37 | 11 | 34 | * | 3 | 14 | - | 53 |
4 | 23 | / | 5 | 31 | + | 29 | 12 | 21 | / | 5 | 11 | + | 77 |
5 | 7 | + | 23 | 14 | / | 4 | 13 | 12 | + | 25 | 20 | / | 6 |
6 | 34 | - | 67 | 11 | * | 3 | 14 | 15 | - | 72 | 54 | * | 2 |
7 | 21 | * | 2 | 20 | + | 11 | 15 | 18 | * | 4 | 7 | + | 55 |
8 | 12 | / | 5 | 54 | - | 32 | 16 | 9 | / | 18 | 18 | - | 81 |