
Лаба 8 / Лабораторная_работа_№8_Токарев_0421
.docxМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра Электротехнологической и преобразовательной техники
отчет
по лабораторной работе № 8
по дисциплине «Информационные технологии»
Тема: Форматное преобразование данных
Студент гр. 0421 |
|
Токарев А.А. |
Преподаватель |
|
Чмиленко Ф.В. |
Санкт-Петербург
2021
Цель работы: Освоение техники работы с файлами данных помощью библиотеки языка С.
Задания:
Форматированное сохранение массива сложной структуры в текстовый файл
Чтение массива сложной структуры из текстового файла
Определение размера файла
Запись в файл в двоичном формате
Чтение из файла двоичного формата
Чтение элемента массива из произвольного места файла двоичного формата
Запись элемента массива в произвольное место файла двоичного формата
Дополнительные задания:
Ввод/вывод из фала с помощью потокового вывода языка С++
Ход работы:
Задание 1.
Создадим программу, в которой реализуем открытие текстового файла с помощью open и сохранит в него заранее созданный и инициализированный массив структур:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
A data[] =
{
{20, -2.44, "Язык С++", 13.33, 12},
{-1, 44.21, "Язык FORTRAN", -0.33, 3},
{0, 12.33, "Язык Pascal", 1.23, 14},
{40, -66.12, "Язык Python", 2.11, 11},
{28, 28.28, "Язык С", 11.22, -5},
{44, 55.55, "Язык C#", 25.22, 54},
{-4, 41.44, "Язык Ruby", 243.22, 777},
{2, 2.22, "Язык Java", 77.77, 0},
{55, 51.15, "Язык JavaScript", 15.15, 99},
{99, 54.54, "Язык PHP", 51.55, 28}
};
inp = fopen("C:\\Users\\Admin\\Desktop\\data.txt", "w"); //открываем файл для записи
for (int i = 0; i < 10; i++)
{
fprintf(inp, "%d %f %s %f %d\n", data[i].a, data[i].b, data[i].c, data[i].d, data[i].e); //запись в файл
}
fclose(inp); //закрываем файл
return 0;
}
Рисунок 1 – Содержание файла data.txt
Доработаем программу так, чтобы имя файла можно было задавать с клавиатуры:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
char str[80];
A data[] =
{
{20, -2.44, "Язык С++", 13.33, 12},
{-1, 44.21, "Язык FORTRAN", -0.33, 3},
{0, 12.33, "Язык Pascal", 1.23, 14},
{40, -66.12, "Язык Python", 2.11, 11},
{28, 28.28, "Язык С", 11.22, -5},
{44, 55.55, "Язык C#", 25.22, 54},
{-4, 41.44, "Язык Ruby", 243.22, 777},
{2, 2.22, "Язык Java", 77.77, 0},
{55, 51.15, "Язык JavaScript", 15.15, 99},
{99, 54.54, "Язык PHP", 51.55, 28}
};
cout << "Введите имя файла:" << endl;
gets(str);
inp = fopen(str, "w"); //открываем файл для записи
for (int i = 0; i < 10; i++)
{
fprintf(inp, "%d %f %s %f %d\n", data[i].a, data[i].b, data[i].c, data[i].d, data[i].e); //запись в файл
}
fclose(inp); //закрываем файл
system("pause");
return 0;
}
Рисунок 2 – Результат работы доработанной программы
Рисунок 3 – Содержпние файла file1.txt
Задание 2.
Отредактируем созданный в задании 1 файл data.txt, удалив из него последние две строчки. Разработаем программу для чтения отредактированного файла в массив структур с помощью функции fscanf. Имя файла будем задавать с консоли, предусмотрев ситуацию, когда запрашиваемого файла не окажется на диске. Для вывода на консоль прочитанного из файла, добавим функцию void View(*char, int):
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
void View(struct A data[], int i)
{
for (int j = 0; j < i; j++)
{
printf("%hd %.2lf %s %.2f %hd\n", data[j].a, data[j].b, data[j].c , data[j].d, data[j].e);
}
}
int main()
{
system("chcp 1251");
system("cls");
int i = 0;
FILE* inp; //указатель на файл
char str[80], tmp1[15][15], tmp2[15][15];
A data[15];
M1:cout << "Введите имя файла:" << endl;
gets(str);
inp = fopen(str, "r+"); //открываем файл для записи
if(fopen(str, "r+") == NULL)
{
cout << "Ошибка!Данного файла нет на диске!Введите имя файла:" << endl;
fflush(stdin);
goto M1;
}
while(!feof(inp))
{
fscanf(inp, "%hd %lf %s %s %f %hd\n", &data[i].a, &data[i].b, tmp1[i], tmp2[i], &data[i].d, &data[i].e); //чтение из файла
snprintf(data[i].c, sizeof(data[i].c), "%s %s", tmp1[i], tmp2[i]);
i++;
}
View(data, i);
fclose(inp); //закрываем файл
system("pause");
return 0;
}
Рисунок 4 – Результат работы программы по чтению данных из файла
Задание 3.
Доработаем предыдущее задание. Определим размер выбранного для чтения файла с помощью функций fseek и ftell:
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
void View(struct A data[], int i)
{
for (int j = 0; j < i; j++)
{
printf("%hd %.2lf %s %.2f %hd\n", data[j].a, data[j].b, data[j].c , data[j].d, data[j].e);
}
}
int main()
{
system("chcp 1251");
system("cls");
int i = 0;
int sz;
FILE* inp; //указатель на файл
char str[80], tmp1[15][15], tmp2[15][15];
A data[15];
M1:cout << "Введите имя файла:" << endl;
gets(str);
inp = fopen(str, "r+"); //открываем файл для записи
if(fopen(str, "r+") == NULL)
{
cout << "Ошибка!Данного файла нет на диске!Введите имя файла:" << endl;
fflush(stdin);
goto M1;
}
fseek(inp, 0, SEEK_END);
sz = ftell(inp);
fseek(inp, 0, SEEK_SET);
while(!feof(inp))
{
fscanf(inp, "%hd %lf %s %s %f %hd\n", &data[i].a, &data[i].b, tmp1[i], tmp2[i], &data[i].d, &data[i].e); //чтение из файла
snprintf(data[i].c, sizeof(data[i].c), "%s %s", tmp1[i], tmp2[i]);
i++;
}
View(data, i);
cout << "Размер файла равен " << sz << " байт(ов)" << endl;
fclose(inp); //закрываем файл
system("pause");
return 0;
}
Рисунок 5 – Результат работы программы по определению размера файла
Задание 4.
Разработаем программу, которая сохраняет массив структур в бинарном файле с помощью функции fwrite. Сравним размер полученного файла с размером файла текстового формата:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
char str[80];
int sz;
A data[] =
{
{20, -2.44, "Язык С++", 13.33, 12},
{-1, 44.21, "Язык FORTRAN", -0.33, 3},
{0, 12.33, "Язык Pascal", 1.23, 14},
{40, -66.12, "Язык Python", 2.11, 11},
{28, 28.28, "Язык С", 11.22, -5},
{44, 55.55, "Язык C#", 25.22, 54},
{-4, 41.44, "Язык Ruby", 243.22, 777},
{2, 2.22, "Язык Java", 77.77, 0}
};
cout << "Введите имя файла:" << endl;
gets(str);
inp = fopen(str, "wb+"); //открываем файл для записи
for (int i = 0; i < 8; i++)
{
fwrite(&data[i], sizeof(struct A),1,inp);
}
fseek(inp, 0, SEEK_END);
sz = ftell(inp);
fclose(inp); //закрываем файл
cout << "размер файла равен " << sz << "байт(ов)" << endl;
system("pause");
return 0;
}
Рисунок 6 – Результат работы программы по сохранению структуры в файл в двоичном формате
Задание 5.
Разработаем программу, которая читает данные в массив из файла двоичного формата с помощью функции fread. Так как количество информации, содержащееся в файле, нам неизвестно по условию, будем использовать динамическую память:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
void View(struct A data[], int i)
{
for (int j = 0; j < i; j++)
{
cout << data[j].a << " " << data[j].b << " " << data[j].c << " " << data[j].d << " " << data[j].e << endl;
}
}
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
char str[80];
int sz, sz_mas;
cout << "Введите имя файла:" << endl;
gets(str);
inp = fopen(str, "r+b"); //открываем файл для чтения
fseek(inp, 0, SEEK_END);
sz = ftell(inp);
rewind(inp);
sz_mas = sz/(sizeof(short)+sizeof(double)+sizeof(char [20]) + sizeof(float) + sizeof(short));
A *data = new A [sz_mas];
for (int i = 0; i < sz_mas; i++)
{
fread(&data[i].a, sizeof(data[i].a) ,1,inp);
fread(&data[i].b, sizeof(data[i].b) ,1,inp);
fread(&data[i].c, sizeof(data[i].c) ,1,inp);
fread(&data[i].d, sizeof(data[i].d) ,1,inp);
fread(&data[i].e, sizeof(data[i].e) ,1,inp);
}
fclose(inp); //закрываем файл
View(data, sz_mas);
cout << sizeof (struct A);
system("pause");
return 0;
}
Рисунок 7 – Результат работы программы по чтению из файла двоичного формата
Задание 6.
Разработаем программу, которая читает один заданный элемент массива из файла. Номер элемента зададим с консоли:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
char str[80];
int sz, n;
cout << "Введите имя файла:" << endl;
gets(str);
cout << "Введите номер строки: " << endl;
cin >> n;
inp = fopen(str, "r+b"); //открываем файл для чтения
sz = (sizeof(short)+sizeof(double)+sizeof(char [20]) + sizeof(float) + sizeof(short)) * (n - 1);
fseek(inp, sz, SEEK_SET);
A data;
fread(&data.a, sizeof(data.a) ,1,inp);
fread(&data.b, sizeof(data.b) ,1,inp);
fread(&data.c, sizeof(data.c) ,1,inp);
fread(&data.d, sizeof(data.d) ,1,inp);
fread(&data.e, sizeof(data.e) ,1,inp);
fclose(inp); //закрываем файл
cout << data.a << " " << data.b << " " << data.c << " " << data.d << " " << data.e << endl;
system("pause");
return 0;
}
Рисунок 8 – Результат работы программы по чтению одного заданного элемента массива из двоичного файла
Задание 7.
Разработаем программу, которая записывает одну строку массива в заданное место файла. Элементы структуры и номер строки будем задавать с консоли:
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
struct A {
short a;
double b;
char c[20];
float d;
short e;
};
void View(struct A data[], int i)
{
cout <<"Новый массив данных:" << endl;
for (int j = 0; j < i; j++)
{
cout << data[j].a << " " << data[j].b << " " << data[j].c << " " << data[j].d << " " << data[j].e << endl;
}
}
int main()
{
system("chcp 1251");
system("cls");
FILE* inp; //указатель на файл
char str[80];
int sz1, n, sz_mas, sz;
A temp;
char tmp1[20];
char tmp2[20];
cout << "Введите имя файла:" << endl;
gets(str);
cout << "Введите номер строки: " << endl;
cin >> n;
cout << "Введите новую запись:" << endl;
scanf("%hd %lf %s %s %f %hd", &temp.a, &temp.b, tmp1, tmp2, &temp.d, &temp.e);
snprintf(temp.c, 20, "%s %s", tmp1, tmp2);
inp = fopen(str, "r+b"); //открываем файл для чтения
fseek(inp, 0, SEEK_END);
sz = ftell(inp);
rewind(inp);
sz1 = (sizeof(short)+sizeof(double)+sizeof(char [20]) + sizeof(float) + sizeof(short)) * (n - 1);
fseek(inp, sz1, SEEK_SET);
fwrite(&temp.a, sizeof(temp.a) ,1,inp);
fwrite(&temp.b, sizeof(temp.b) ,1,inp);
fwrite(&temp.c, sizeof(temp.c) ,1,inp);
fwrite(&temp.d, sizeof(temp.d) ,1,inp);
fwrite(&temp.e, sizeof(temp.e) ,1,inp);
rewind(inp);
sz_mas = sz/(sizeof(short)+sizeof(double)+sizeof(char [20]) + sizeof(float) + sizeof(short));
A *data = new A [sz_mas];
for (int i = 0; i < sz_mas; i++)
{
fread(&data[i].a, sizeof(data[i].a) ,1,inp);
fread(&data[i].b, sizeof(data[i].b) ,1,inp);
fread(&data[i].c, sizeof(data[i].c) ,1,inp);
fread(&data[i].d, sizeof(data[i].d) ,1,inp);
fread(&data[i].e, sizeof(data[i].e) ,1,inp);
}
fclose(inp); //закрываем файл
View(data, sz_mas);
system("pause");
return 0;
}
Рисунок 9 – Результат работы программы по записи строки массива в заданное место файла
Дополнительное задание.
Разработаем программу, в которой реализуем задания 1 и 2 с помощью потоковой библиотеки работы с файлами С++:
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct A {
short a;
double b;
string c;
float d;
short e;
};
int main()
{
system("chcp 1251");
system("cls");
char str[80];
int i = 0;
string s;
A data[] =
{
{20, -2.44, "Язык С++", 13.33, 12},
{-1, 44.21, "Язык FORTRAN", -0.33, 3},
{0, 12.33, "Язык Pascal", 1.23, 14},
{40, -66.12, "Язык Python", 2.11, 11},
{28, 28.28, "Язык С", 11.22, -5},
{44, 55.55, "Язык C#", 25.22, 54},
{-4, 41.44, "Язык Ruby", 243.22, 777},
{2, 2.22, "Язык Java", 77.77, 0},
{55, 51.15, "Язык JavaScript", 15.15, 99},
{99, 54.54, "Язык PHP", 51.55, 28}
};
A data1[80];
cout << "Введите имя файла:" << endl;
gets(str);
fstream inp;
inp.open(str);
for(int i = 0; i < 10; i++)
{
inp << data[i].a << " " << data[i].b << " " << data[i].c << " " << data[i].d << " " << data[i].e << endl;
}
inp.close(); //закрываем файл
inp.open(str);
while (!inp.eof())
{
getline(inp, s);
cout << s << "\n";
}
inp.close();
system("pause");
return 0;
}
Рисунок 10 – Результат работы программы по потоковому вводу/выводу из файла
Выводы:
В данной лабораторной работе были изучены основные функции для работы с файлами языка си. Были разработаны программы, выполняющие форматированный ввод массива структур в текстовый файл и форматированный вывод массива структур из текстового файла. Также был определен размер получившегося текстового файла.
Кроме того, были разработаны программы, выполняющие форматированный ввод массива структур в двоичный файл и форматированный вывод массива структур из двоичного файла. Также был определен размер получившегося двоичного файла и проведено сравнение размера двоичного файла и текстового. Двоичный файл занимает меньше места на диске.
С помощью функции fseek были разработаны программы по чтению и записи элемента массива в бинарный файл.
Кроме того, был выполнен форматированный ввод и вывод массива структур в файл был с помощью инструментов потокового ввода/вывода языка С++.