/*
	  МГТУ ГА
	  ЭВМ-1-2
      Виталий Новичков

       27 апреля 2011
 (С) 2011 Wohlhabenden.NET

   Лабораторная работа #7

"Обработка бинарных файлов"

	      Цель лабораторной работы:
_____________________________________________________
Целью лабораторной работы является получение навыков
прогарммирования с использованием бинарных файлов,
содержащих структурированные данные, освоение:
   * объявление файлов;
   * функций открытия и закрытия файолов;
   * методов создания, дополнения, чтеня и
     модефикации данных файла;
   * методов поэтапной разработки и отладки програмы.
_____________________________________________________
*/

#include <conio.h>
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iomanip.h>
#include <fstream.h>
#include "..\#6\prnbrdr.c"

struct stud
	{
	char s_name[10];
	char FN_trainer[10];
	float delay_tr;
	float cost_ts;
	int sprtmen_q;
	}
	st;

int z = sizeof(stud);

/*
░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀░
*/

char * header[] =
{
"                        Спортивные секции                            ",
"╔══════════╦══════════╦══════════════╦═══════════════╦═════════════╗",
"║ Название ║   ФИО    ║ Длительность ║    Стоимость  ║ Количество  ║",
"║  секции  ║  Тренера ║  Тренировки  ║ одного занятия║ Спортсменов ║",
"╠══════════╬══════════╬══════════════╬═══════════════╬═════════════╣",
"╚══════════╩══════════╩══════════════╩═══════════════╩═════════════╝"
//├────────┤ ├────────┤ ├────────────┤ ├─────────────┤ ├───────────┤
//     10        10         14                15             13
};

ifstream fin;
ofstream fout;
fstream io;
const char e='\n';


void p(),
     read_fs(),
     crat(int),
     add_(),
     find01(int),
     find02(int),
     editor_(int),
     p_header(),
     wR_f(int),
     filter_(char *, int),
     pri(char *);



void main(int argc, char *params[])
{
clrscr();
fout.open("l7_out.txt");
if (!fout)
	{
	pri("Ошибка при открытии файла результатов");
	getch();
	exit(0);
	}

// Считывание параметра, который определяет вывод на экран
// процесса обработки данных функцией filter() для нахождения ошибок
// заполненя входных файлов
int debug=0;
char *DBG_param=params[1];
if (argc>1)
{
filter_(params[1], 1);
cout << "PARAM = " << params[1]<<"  "<< (int)params[1] <<endl;
   if ((int)params[1]==(int)-10)
   debug=1;
cout << "DEBUG = " << debug << endl;
}


crat(debug);    read_fs();
add_();    read_fs();
find01(debug);
find02(debug);
editor_(debug); read_fs();
fout.close();
textcolor(7);
cprintf("\n");
textcolor(2);
cprintf("\nОбработка данных успешно завершена!");
textcolor(7);
textcolor(7);
cprintf("\n");
//Предложение просмотреть файл результатов после работы прогарммы
char key;
printf("\nОткрыть файл результатов? (Y/N)");
while((key!='y')&&(key!='Y')&&(key!='n')&&(key!='N'))
{
key=getch();
}
if((key=='y')||(key=='Y'))
system("edit L7_OUT.TXT");
}



void pri(char *s)
	{
	prnborder(s,12);
	}


void p_header()
	{
	for(int i=0; i<5; i++)
	fout << header[i] << '\n';
	}


void p()
	{
	fout << '║' << setiosflags(ios::left)<<
	setw(10) << st.s_name << '║' <<
	setw(10) << st.FN_trainer << '║' <<
	setw(14) << st.delay_tr << "║ " <<
	setw(14) << st.cost_ts << "║ " <<
	setw(12) << st.sprtmen_q << "║\n";
	}

void read_fs()
	{
	int n=0;
	float s=0;
	fout << "\n		ЧТЕНИЕ ФАЙЛА\n";
	fin.open("binary.bin", ios::in|ios::binary);
	if (!fin)
		{ pri("Ошибка открытия бинарного файла для чтения"); exit(0); }
	p_header();
	while(fin.peek()!=EOF)
	   {
	     fin.read((char *) &st, z);
	     p();
	     s+=st.sprtmen_q;
	     n++;
	   }
	fout << header[5]<<"\n\nОбщее количество спортсменов: "<<s<<
	"\nКолличество структур в файле: " << n << endl;
	fin.close();
	}

void crat(int dbg=0)
	{
	struct stud;
	fout << "\n		Создание файла\n";
	fin.open("crat.dat");
	if(!fin)
		{pri("Ошибка при открытии файла данных");exit(0);}
	io.open("binary.bin", ios::out|ios::binary);
	if(!io)
		{pri("Ошибка открытия бинарного файла дял его создания");exit(0);}
	p_header();
	wR_f(dbg);
	fin.close();
	io.close();
	}

void wR_f(int dbg=0)
	{
	char T[80];
	while(!fin.eof())
	  {
	  fin.getline(st.s_name, 10); filter_(st.s_name, dbg);
	  fin.getline(st.FN_trainer, 10); filter_(st.FN_trainer, dbg);
	  fin >> st.delay_tr;
	  fin >> st.cost_ts;
	  fin >> st.sprtmen_q;
	  fin.getline(T, 80);
	  io.write((char *) &st, z);
	  p();
	  }
	fout << header[5]<< endl;
	}

// Удаление пробелов вначале и в конце строки - параметра
void filter_(char *a, int debug=0)
	{
	int i, j, l=strlen(a);
	if (debug) cout << "Применение фильтра: \""<<a<< "\"";

	for (i=0; i<l; i++)
		if( (a[i]!=' ') && (a[i]!='\t') )
		for(j=l-1; j>=1; j--)
			if((a[j]!=' ')&&(a[j]!='\t')&&(a[j]!='\n'))
			{
			for(l=i; l<=j; l++)
			    a[l-i]=a[l];
			a[l-i]='\0';
			goto m;
			}
	a[0] = NULL;
	m:
	if (debug) cout <<" => \""<<a<<"\"\n";
	}


void find01(int dbg=0)
	{
	char name[20];
	fin.open("find01.dat");
	if(!fin)
		{
		pri("Ошибка открытия файла данных для поиска 01");
		exit(0);
		}
	fout << "\n           Поиск по ФИО Тренера\n\n";
	//Открытие бинарного файла для чтения
	io.open("binary.bin", ios::in|ios::binary);
	if(!io)
		{
		pri("Ошибка открытия бинарного файла для поиска 01");
		exit(0);
		}
	while(fin.peek()!=EOF)
		{
		fin.getline(name, 10); filter_(name, dbg);
		fout << "\nИщем тренера - \"" << name << "\"\n";
		if(!strcmp(name, ""))
		{
			fout <<"[ НЕТ ДАННЫХ ДЛЯ ПОИСКА ]\n";
			continue;
		}
		io.seekg(0, ios::beg);
		while(io.peek()!=EOF)
			{
			io.read((char*)&st, z);
			if(strcmp(st.FN_trainer, name)==0)
				{
				p(); goto m;
				}
			}
			fout << "[ Запись с тренером "<< name << " не найдена \n";
			m:;
		}
		fin.close(); io.close();
	}

void find02(int dbg=0)
	{
	//Переменные для хранения поисковых признаков
	char Section[10]; float TrCost;
	fin.open("find02.dat", ios::in); //Открытие файла данных для поиска
	if(!fin)
		{
		pri("Ошибка открытия файла данных для поиск 2"); exit(0);
		}
	fout << "\n\nПоиск по названию секции и по стоимости тренировки\n";
	while(fin.peek()!=EOF)
		{
		fin.getline(Section, 10); filter_(Section, dbg);
		fin >> TrCost;
		int k=0;
		fout << "\nИщем в секции - \""<<Section<<"\" тренировки стоимостью >= $"<<TrCost<<e;
		if((!strcmp(Section,""))&&(TrCost==0.0))
			{
			fout << "[Отсутствуют данные для поиска!]\n";
			continue;
			}
		//Открытие бинарного файла для чтения
		io.open("binary.bin", ios::in|ios::binary);
		if(!io) {pri("Ошибка открытия бинарного файла для чтения в поиске 2"); exit(1);}
		while(io.read((char*)&st, z)) /*Пока читаются данные бинарного файла-
					     Цикл поиска*/
		if (((!strcmp(st.s_name, Section))||(!strcmp(Section, "")) )
		&&((TrCost<=st.cost_ts)||(TrCost==0)))
			{
			p();k++;
			}
		if(!k) fout << "[Ничего не найдено!]\n";
		io.close();
		}
		fin.close();
		io.close();

	}

/*
░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀░
*/
void add_()
{
fout << "\n\n		Дополнение файла новыми записями\n";
fin.open("add.dat", ios::in);
if(!fin){pri("Ошибка открытия файла данных для дополнения"); exit(3);}
io.open("binary.bin", ios::app|ios::binary);
if(!io){pri("Ошибка открытия бинарного файла для дополнения"); exit(4);}
for(int i=1; i<5; i++)
fout << header[i]<<endl;
wR_f();
fin.close();
io.close();
}

void editor_(int dbg=0)
	{
	char t[80]; //Массив-буффер
	char name[85];
	float cost_ts; //Переменная для новой стоимости
	fout << "\n\n		Коррекция файла\n\n";
	//Открытие файла с данными для поиска и коррекции структур
	fin.open("doedit.dat", ios::in);
	if(!fin)
		{
		pri("Ошибка открытия файла данных для коррекции");
		exit(5);
		}
	while(fin.peek()!=EOF)
		{
		fin.getline(name, 10); filter_(name, dbg);
		fin >> cost_ts;
		fin.getline(t, 80);
		int k=0;
		if(!strcmp(name, ""))
			{
			fout<<"\nНет данных для поиска корректируемой \
			струкруты\n\n";
			continue;
			}
		//Открытие бинарного файла в режиме чтения/записи
		io.open("binary.bin", ios::in|ios::out|ios::binary);
		if(!io)
			{
			pri("Ошибка открытия файла для его коррекции");
			exit(6);
			}
		//Пока читаются данные - цикл поиска структуры
		while(io.read((char *)&st, z))
			if(!strcmp(st.s_name, name))
				{
				p();
				st.cost_ts=cost_ts;
				p();
				//Указатель записи в файле перемещается на
				//одну структуру назад
				io.seekp(-z, ios::cur);
				//Запись в файл откорректированной структуры
				io.write((char*)&st, z);
				k++;
				break;
				}
		if(!k) fout << "[Секция "<< name <<" не найдена!]"<<endl;
		io.close();
		}
	fin.close(); io.close();
	}
