23.67M
Категория: ПрограммированиеПрограммирование

Программирование на языке высокого уровня C++

1.

Богатов Р.Н.
Программирование
на языке высокого уровня
C++ ► Лекция 7 ► Текстовые и двоичные файлы
Кафедра АСОИУ ОмГТУ, 2020

2.

Повтор. Контроль ввода
...
int a, b, n;
do {
printf("\nВведите натуральные A и B: ");
fflush(stdin);
n = scanf("%d%d", &a, &b);
} while (n!=2 || a<=0 || b<=0);
fflush(stdin);
...

3.

Вывод содержимого текстового файла на экран
Мама и папа, я без вас очень скучаю. Особенно по вечерам. Но я вам не скажу, где я живу.
А то вы меня заберете, а Матроскин и Шарик пропадут...
Дорогие папа и мама, вы меня теперь просто не узнаете. Хвост у меня крючком, уши
торчком, нос холодный, и лохматость повысилась...
До свидания. Ваш сын - дядя Фёдор
//
открытие
файла
//
открытие
файла
//
открытие
файла
FILE
*f;
FILE
*f;
*f; "myfile.txt", "r" );
ffFILE
== fopen(
fopen(
f = fopen( "myfile.txt",
"myfile.txt", "r"
"r" );
);
//
работа
сс файлом
//
работа
//
работа
с файлом
файлом
char
s[7000];
char
s[7000];
for(;;)f, "%s", s );
fscanf(
fscanf(
f, "%[^\n]s", s );
{
printf(
"%s",
s );
printf(
"%s",
char
c; s );
int n =файла
fscanf( f, "%c", &c );
//
// закрытие
закрытие
файла
if (n!=1) break;
fclose(f);
fclose(f);
printf( "%c", c );
}
// закрытие файла
fclose(f);
...
// работа с файлом
for(;;)
{
int c = fgetc(f);
if (feof(f)) break;
printf( "%c", c );
}
...

4.

Что делать с депрекацией (deprecation, неодобрением)
использования стандартных функций ввода-вывода?
// либо подавить депрекацию,
// определив сигнальный идентификатор:
// либо использовать безопасные (safe)
// эквиваленты функций ввода-вывода
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
...
#include <stdio.h>
...
int main()
{
// открытие файла
FILE* f;
f = fopen("myfile.txt", "r");
int main()
{
// открытие файла
FILE* f;
fopen_s(&f, "myfile.txt", "r");
...
...
}
}

5.

Посимвольная обработка текстового файла
// заменить
// заготовка:
посимвольное
строк
копирование
набуквы
пробел
файла
строки),
// разрыв
заменить
все ('\n')
русские
на (склеить
подчёркивания
//
этом
заменить
на одинарный (конец абзаца)
// при
доделать:
удалить\n\n
повторы
пробелов
...двойной
char
previous
== '' ';
char#define
previous
';
for_CRT_SECURE_NO_WARNINGS
(;;)
for
#include
for (;;)
(;;) { <stdio.h>
{{ #include <stdlib.h>
int c = fgetc(f1);
int
int cc == fgetc(f1);
fgetc(f1);
if (feof(f1)) break;
int
if
(feof(f1))
main()
if (feof(f1)) break;
break;
{
// верно только для кодировки Windows 1251
if
(c
FILE
==
'\n'
*f1
=&&
fopen("text1.txt",
previous
'\n')
if (c == //
'\n'
&&
previous
'\n')"rt");
(кроме
букв ё !=
и!=Ё)
FILE
fputc('
*f2
',
=',fopen("text2.txt",
f2);
"wt+");
fputc('
f2);
if (c
>=
(unsigned char)'А')
else
else
c = '_';
for
fputc(c,
f2);
if (;;)
(!(c ==
' ' && previous == ' '))
{
fputc(c, f2);
f2);
fputc(c,
previous
int
=
c;
c
=
fgetc(f1);
}
}
break;
previous
= (feof(f1))
c;
... if
fputc(c, f2);
}
}
_fcloseall();
system("start text2.txt");
}

6.

Что делает эта программа?
...
printf("Введите
текст: ");
FILE
*f;
int
count=0;
... s[2000]="";
char
f = fopen(
"myfile.txt", "rt" );
for(int
i=0;;)
for(;!feof(f);)
scanf("%[^\n]s",
s, 2000);
{ {...
for(;!feof(f);)
char
s[100];
for(;
s[i]=='
...
char
c=' '; '; i++);
int
N
=
strlen(s);
{ int
if for(;
(i>=N)
count
= break;
0;
char
s[100];
!feof(f)
&& c==' ';)
strcat(s,
"
");
char
c='
';
for(;
s[i]!='
';count++)
i++);
for
(;
c
= fgetc(f);
for
(; !feof(f);
!feof(f);)
for(;
!feof(f)
&&
c==' ';)
count++;
char s[500] = {c};
int{{count=0;
c = fgetc(f);
}
int
j=1; f,"%s%*[
for(int
i=0;;)
fscanf(f,
fscanf(
"%s%*[\t\n]s",
\t\n]s",s,s,100);
100);
printf("%c",
c);
...
for(;
!feof(f)
&&
c!='
';
j++)
{
strrev(s);
for(;
!feof(f)
c!=' ';)
fprintf(
f2, &&
"%s\n",
strrev(s) );
s[j] = (c
=i++);
fgetc(f));
for(;s[i]=='
';
printf("%c", s);
c = fgetc(f));
printf("%s\n",
} s[j-1]=0;
if
(i>=N)
break;
printf("\n");
}...
printf( "%s\n",
strrev(s) );
for(;s[i]!='
'; i++);
} ...
*
(звёздочка)
означает, что нужно считать
} count++;
данные по всем указанным правилам, но
...
}fclose(f);
никуда не сохранять (проигнорировать их).
Точно%d
такслов.",
же можноcount);
считать и пропустить
printf("В тексте
Мама и папа, я без вас очень
вечерам.(%*c).
Но я вам не скажу, где я живу. А то вы меня
числоскучаю.
(%*d,Особенно
%*f) илипосимвол
заберете, а Матроскин и Шарик пропадут...
Дорогие папа и мама, вы меня теперь просто не узнаете. Хвост у меня крючком, уши торчком, нос
холодный, и лохматость повысилась...
До свидания. Ваш сын - дядя Фёдор

7.

int main()
{
FILE *f = fopen("sine.off", "wt+");
fprintf(f, "OFF\n");
Файлы
формата
OFF
const int N = 20; // количество точек функции
const double z = 1; // ширина ленты
OFF double A = 1.8; // высота (амплитуда)
const
8 6 12
const
int V = 2*N; // количество вершин
const
F =1.4142
N-1; // количество граней
1.0 int
0.0
const int E = 4*F; // количество рёбер
0.0 1.0 1.4142
fprintf(f, "%d %d %d\n", V, F, E);
-1.0 0.0 1.4142
for(int
i = 0;
i < N; i++)
0.0 -1.0
1.4142
{
1.0 0.0 0.0
double x = i*2*3.1415/(N-1);
0.0double
1.0 y0.0
= A*sin(x);
-1.0// записываем
0.0 0.0 по две вершины
0.0fprintf(f,
-1.0 0.0"%lf %lf %lf\n", x, y, 0);
fprintf(f, "%lf %lf %lf\n", x, y, z);
}4 0 1 2 3
4 7 4 0 3
//
4 записываем
4 5 1 0 грани
for(int i = 0; i < N-1; i++)
4 5fprintf(f,
6 2 1
"4 %d %d %d %d\n", 2*i, 2*i+1, 2*i+3, 2*i+2);
См. en.wikipedia.org/wiki/OFF_(file_format)
4 3 2 6 7
fclose(f);
4 6 5 4 7
printf("File 'sine.off' has been created!");
system("start https://3dviewer.net/");
}

8.

int main()
void cylider(double x1, double y1, double z1, double x2, double y2, double z2, double heigt)
{
{
srand((unsigned)time(0));
void
cucumber(double
x1, double y1, double z1, double x2, double y2, double z2,
int
V = Vc;
cucumber(0, 0, 0, 0, 0, 1, 1.0); // огурчик от (0,0,0) до (0,0,1)
длиной
1.0
double
length,
int level = 0)
double R = 0.2 * heigt;
{ // расчёт вершин гранёного цилиндра, ортогонального осям
FILE *f = fopen("fractal cucumber.off", "wt+");
for(int
i = 0; i < N; i++)
// огурец-родитель
fprintf(f, "OFF\n");
{ cylider(x1, y1, z1, x2, y2, z2, length);
fprintf(f,
"%d %d 0\n", Vc, Rc+Pc );
double alpha = i*2*3.1415/N;
if (level == fractal_depth) return;
double dx = R*cos(alpha);
// записываем вершины
double dy = R*sin(alpha);
for(int
i = 0; i0.25;
< Vc; //
i++)сдвиг центра фрактолизации
double
X[Vc]w == x1+dx*(x1==x2);
fprintf(f, "%.6lg %.6lg %.6lg\n", X[i], Y[i], Z[i] );
Y[Vc] = координат
y1+dy*(y1==y2);
// расчёт
центра фрактолизации (откуда будут расти отпрыски)
Z[Vc++]
z1+(dx*(y1==y2)+dy*(x1==x2))*(z1==z2);
double
x = =w*x1+(1-w)*x2,
y = w*y1+(1-w)*y2, z = w*z1+(1-w)*z2;
// записываем грани
X[Vc] = x2+dx*(x1==x2);
for(int i = 0; i < Rc; i++)
Y[Vc] = y2+dy*(y1==y2);
double
L = length
k;%d\n",rectangles[i][0],
// длина отпрыска уменьшается на каждом уровне
fprintf(f,
"4 %d %d* %d
Z[Vc++] = z2+(dx*(y1==y2)+dy*(x1==x2))*(z1==z2);
rectangles[i][1],
rectangles[i][2],
rectangles[i][3]);
cucumber(x,
y, z, x-L, y,
z, L, level + 1),
} if (x1==x2)
Фрэктэл кукумбер???
cucumber(x, y, z, x+L, y, z, L, level + 1);
for(int j = 0; j < Pc; j++)
//ifзаписываем
грани
(y1==y2)const
cucumber(x,
y, z, =x,5; y-L,
z, L, level
+ 1),рекурсии
int fractal_depth
// максимальная
глубина
{
for(int i = 0;const
i <cucumber(x,
N; i++) k = 0.5;
y, z,
y+L, z, масштабирования
L, level + 1);
// x,
коэффициент
fprintf(f, "%d",double
N);
rectangles[Rc][0]
= V+2*i,
if for(int
(z1==z2)
i = 0;cucumber(x,
i < N; i++) y, z, x, y, z-L, L, level + 1),
rectangles[Rc][1]
=N V+2*i+1,
const
int
= polygons[j][i]);
11; y,
// количество
гранейL,цилиндра
cucumber(x,
z, x, y, z+L,
level + 1);
fprintf(f,
" %d",
rectangles[Rc][2]
=
V+(2*i+3)%(2*N),
const
int
M
=
400000;
//
максимальное
количество
точек
fprintf(f, "\n");
}
rectangles[Rc][3]
=
V+(2*i+2)%(2*N),
double X[M], Y[M], Z[M];
}
Rc++;
int rectangles[M/2][4];
fclose(f);
int polygons[M/N][N];
// пол и потолок
int Vc cucumber.off'
= 0;
// количество
вершин
printf("File 'fractal
has been created.
You can view it on
for(int i = 0;int
i <RcN;= i++)
polygons[Pc][i]
=
V+2*i; Pc++; граней цилиндров
0;
//
количество
прямоугольных
https://3dviewer.net/ (let it open up!)...");
for(int i = 0;int
i <PcN;= i++)
V+2*i+1; Pc++;
0; polygons[Pc][i]
// количество =N-угольников
(пол и потолок цилиндра)
system("start https://3dviewer.net/");
}
}

9.

Текстовый и двоичный режимы работы с файлами
// открытие файла в текстовом режиме
FILE *f;
f = fopen( "myfile.txt", "rt" );
// открытие файла в двоичном режиме
FILE *f;
f = fopen( "myfile.txt", "rb" );
// работа с файлом
...
// работа с файлом
...
• LF (line feed), ASCII=10, '\n' – управляющий код подачи строки
• CR (carriage return), ASCII=13, '\r' – управляющий код возврата каретки
// эксперимент!
printf( "Привет\nПока" );
printf( "Привет\rПока" );
printf( "Привет\n\rПока" );
printf( "Привет\r\nПока" );

10.

Хранение данных в текстовом файле
// открытие файла на запись
FILE *f;
f = fopen( "myfile.txt", "wt+" );
0,000000
0,000000
0,400000
0,194709
0,800000
0,358678
1,200000
0,466020
// запись в текстовый файл подобно выводу на экран 1,600000 0,499787
2,000000
0,454649
for( double x=0; x<2*3.1416; x+=0.4 )
2,400000
0,337732
fprintf( f, "%f\t%f\n", x, 0.5*sin(x) );
2,800000
0,167494
3,200000
-0,029187
// закрытие файла
3,600000 x,-0,221260
printf( "%f\t%f\n", x, 0.5*sin(x) );
fprintf( stdout, "%f\t%f\n",
0.5*sin(x) );
fclose(f);
4,000000
-0,378401
-0,475801
scanf( "%f%f", &a, &b );
fscanf( stdin, "%f%f",4,400000
&a, &b );
4,800000
-0,498082
// открытие файла на чтение
5,200000
-0,441727
f = fopen( "myfile.txt", "rt" );
5,600000
-0,315633
6,000000
-0,139708
do {
float a, b;
fscanf( f, "%f%f", &a, &b );
// использование данных
...
} while( !feof(f) );
// закрытие файла
fclose(f);

11.

Хранение тех же данных в двоичном файле
// открытие файла на запись
FILE *f;
f = fopen( "myfile.dat", "wb+" );
// запись в файл в двоичном режиме
for( double x=0; x<2*3.1416; x+=0.4 )
{
fwrite( &x, sizeof(x), 1, f );
double y = 0.5*sin(x);
fwrite( &y, sizeof(y), 1, f );
}
// открытие файла на чтение
f = fopen( "myfile.dat", "rb" );
// закрытие файла
fclose(f);
do {
double a, b;
fread( &a, sizeof(a), 1, f );
fread( &b, sizeof(b), 1, f );
// использование данных
...
} while( !feof(f) );
// закрытие файла
fclose(f);

12.

Инкапсуляция данных в структуры
struct ab
{
double a, b;
};
...
for( double x=0; x<2*3.1416; x+=0.4 )
{
ab t;
ab t = { x, 0.5*sin(x) };
t.a = x;
t.b = 0.5*sin(x);
fwrite( &t, sizeof(t), 1, f );
}
...
...
do {
ab t;
fread( &t, sizeof(t), 1, f );
// использование данных в t.a и t.b
...
} while( !feof(f) );
...

13.

Файлы формата BMP (24-битные, без сжатия)
//
заголовка
...копирование
FILE*
f1 = fopen("kitten.bmp", "rb");
fseek(f1,
0, SEEK_SET);
// копирование
пикселей
FILE*
f2 = fopen("lion.bmp",
"rb");
char
*buffer
=
new
char[offset];
for (int
0; y < Y1; y++)
FILE*
fres y= =fopen("result.bmp",
"wb+");
fread(buffer,
for (int offset,
x = 0; x1,< f1);
X1; x++)
//
запомнить
размер
заголовка
и начало массива пикселей
fwrite(buffer,
offset,
1, fres);
{
fseek(f1, 0x0A,
SEEK_SET);
unsigned
char r1, g1, b1;
int
offset;
// подготовка
к копированию
пикселей
fread(&r1,
1, 1, f1);
fread(&offset, 4, 1, f1);
fseek(f1, offset,
SEEK_SET);
fread(&g1,
1, второго
1, f1); файла
... // точно
так же для
fseek(f2, offset,
SEEK_SET);
fread(&b1,
1, 1, f1);
// размеры unsigned
рисунка char r2, g2, b2;
// копирование
пикселей
fseek(f1,
0x12,
SEEK_SET);
fread(&r2,
1, 1, f2);
int
for X1,
(intY1;
yfread(&g2,
= 0; y < Y1;
y++)
1, 1,
f2);
fread(&X1,
4,
1,
f1);
for (int
x = 0; x1,< 1,
X1;f2);
x++)
fread(&b2,
fread(&Y1,
4, 1, f1);
{
... // точно так же для второго файла
unsigned
r1,//g1,
b1;яркости первого изображения
double k char
= 0.5;
доля
1, 1,
unsigned
char
r =f1);
(unsigned char)(r1*k + r2*(1-k));
if (X1!=X2fread(&r1,
|| Y1!=Y2)
fread(&g1,
1,
1,
printf("FAILURE:
Your
must have
the same+ resolution!"),
exit(-1);
unsigned char
g files
=f1);
(unsigned
char)(g1*k
g2*(1-k));
fread(&b1,
1, 1,
unsigned char
b =f1);
(unsigned char)(b1*k + b2*(1-k));
if (X1 % 4...
!= 0)
fwrite(&r,
1, 1, fres);
printf("FAILURE:
The
width of the image must be a multiply of 4!"), exit(-1);
}
fwrite(&g, 1, 1, fres);
fwrite(&b,
1, 1,
fres);
printf("Processing
%dx%d
pixels...\n\n",
X1, Y1);
_fcloseall();
}
...
printf("Done.
See RESULT.BMP..."); system("start RESULT.BMP");
...

14.

15.

Домашнее задание
Построить гистограмму длин слов из заданного текстового файла.
Словом считать последовательность символов, не содержащую пробелов.
• Для начала задачу можно решить для текстовой строки, которую пользователь
вводит с клавиатуры, а потом уже, когда всё будет работать, доделать считывание
данных из файла.
• Все сложные задачи нужно разбивать на подзадачи. Сначала можно просто
научиться выделять слова и подсчитывать их количество.
• Затем добавить код для сбора статистики. Гистограмма – это счётчики
встречаемости слов каждой возможной длины (например, от 1 до 100 символов).
Если длина слова получена в переменной j и есть массив счётчиков counts, то
нужно выполнить простое действие: counts[j]++.
English     Русский Правила