Проблема в считывании структуры из типизированного файла
Снизу реализация очереди на основе типизированного файла - с коррекцией неверного времени и поиском определенных заказов (в промежутке времени от и до). Проблема появляется в функции Pop, которая забирает элемент из файла и сдвигает указатель начала - вместо названий и времени заказов считываются пустота и 0 соответственно, КРОМЕ последнего, сколько бы я не вводил. Почему так происходит, понять не могу, уже всю программу перекроил, поэтому где-то код может быть странным или неуместным.
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <windows.h>
#include <string.h>
#include <conio.h>
#include <cctype>
struct TZak { //Создаём структуру, в которой находится информация
char name[31]; //Название заказа
int h; //Часы
int m; //Минуты
int s; //Секунды
};
struct TQ {
FILE* Q; //Файл для очереди
int Q_begin = NULL, Q_end = NULL; //Начало первого и последнего элемента в битах
};
bool Empty(TQ Q) { //Проверка на пустоту
return (Q.Q_begin == Q.Q_end); // Если ссылки на начало и конец пустые значит очередь пустая.
}
void Create(TQ& Q, TZak Zakaz) {//Создание очереди из одного элемента
Q.Q = fopen("tip.bin", "wb");
fwrite(&Zakaz, sizeof(TZak), 1, Q.Q); //Помещаем элемент в очередь
Q.Q_begin = 0;
Q.Q_end = sizeof(TZak); //Cмещаем указатель конца
fclose(Q.Q);
return;
}
void Push(TQ& Q, TZak Zakaz) { //Добавление элемента в конец очереди
Q.Q = fopen("tip.bin", "w+b");
fseek(Q.Q, Q.Q_end, SEEK_SET);
fwrite(&Zakaz, sizeof(TZak), 1, Q.Q); // Мы получаем элемент и помещаем его в конец очереди
Q.Q_end += sizeof(TZak); //Cмещаем указатель конца
fclose(Q.Q);
return;
}
TZak Pop(TQ& Q) { //Взятие элемента из очереди
Q.Q = fopen("tip.bin", "rb");
TZak Elem;
fseek(Q.Q, Q.Q_begin, SEEK_SET);
fread(&Elem, sizeof(TZak), 1, Q.Q); // Мы получаем элемент
Q.Q_begin += sizeof(TZak);
fclose(Q.Q);
return Elem;
}
void outLOG(TQ Q, FILE* log) { //Вывод очереди в лог
Q.Q = fopen("tip.bin", "rb");
fseek(Q.Q, 0, SEEK_SET);
for (int i = 0; i < (Q.Q_end/ sizeof(TZak)); i++) { //поочерёдно читаем элементы из очереди
TZak* Zakaz = new TZak;
fread(Zakaz, sizeof(TZak), 1, Q.Q);
fprintf(log, "\nНазвание: %s Время: %d:%d:%d\n------------------------\n",
Zakaz->name, Zakaz->h, Zakaz->m,
Zakaz->s);
}
fprintf(log, "\n");
fclose(Q.Q);
return;
}
void AddTxt(TQ& Q) { //добавить элементы из текстового файла
FILE* f;
TZak Zakaz;
char s[3];
int kol = 0;
if ((f = fopen("vvod.txt", "rt")) == NULL) { //проверка открытия
printf("Не удалось открыть файл для считывания\nPress any key");
_getch();
return;
}
while (1) { //циклически считываем элементы
fscanf(f, "%30s", Zakaz.name);
if (strcmp(Zakaz.name, "**") == 0 || feof(f)) break;
fscanf(f, "\n");
fscanf(f, "%s", s); Zakaz.h = atoi(s);
if (Zakaz.h < 0) { Zakaz.h = 0; } //коррекция
if (Zakaz.h > 23) { Zakaz.h = 23; }
fscanf(f, "%s", s); Zakaz.m = atoi(s);
if (Zakaz.m < 0) { Zakaz.m = 0; }
if (Zakaz.m > 59) { Zakaz.m = 59; }
fscanf(f, "%s", s); Zakaz.s = atoi(s);
if (Zakaz.s < 0) { Zakaz.s = 0; }
if (Zakaz.s > 59) { Zakaz.s = 59; }
if (Empty(Q)) //проверка на пустоту очереди, если ее нет - создаем, если есть - переносим туда элементы
Create(Q, Zakaz);
else
Push(Q, Zakaz);
kol++;
}
fclose(f);
printf("Введено %d элементов\nPress any key", kol);
_getch();
return;
}
void AddElem(TQ& Q) { //добавление элемента вручную
TZak Zakaz;
printf("Название:"); scanf("%30s", Zakaz.name);
printf("Часы:"); scanf("%d", &Zakaz.h);
printf("Минуты:"); scanf("%d", &Zakaz.m);
printf("Секунды:"); scanf("%d", &Zakaz.s);
if (Zakaz.h < 0) { Zakaz.h = 0; } //коррекция
if (Zakaz.h > 23) { Zakaz.h = 23; }
if (Zakaz.m < 0) { Zakaz.m = 0; }
if (Zakaz.m > 59) { Zakaz.m = 59; }
if (Zakaz.s < 0) { Zakaz.s = 0; }
if (Zakaz.s > 59) { Zakaz.s = 59; }
if (Empty(Q)) //проверка на пустоту очереди, если ее нет - создаем, если есть - переносим туда элементы
Create(Q, Zakaz);
else
Push(Q, Zakaz);
printf("Запись введена\nPress any key");
_getch();
return;
}
void PopN(TQ& Q, int N) { //удаляет N элементов очереди
int i = 0;
TZak Zakaz;
while ((!Empty(Q)) && (i < N)) { //цикилчески удаляем N элементов
Zakaz = Pop(Q);
i++;
}
return;
}
char* ANSIUpperCase(char* s, char* S) { //функция, необходимая для поиска нужных
S = strcpy(S, s);
char* ch = S;
while (*ch) {
if (*ch >= 'a' && *ch <= 'z' || *ch >= 'а' && *ch <= 'я') *ch = *ch - 32;
if (*ch == 'ё') *ch = 'Ё';
ch++;
}
return S;
}
void Filter(TQ Q_main, TQ& Q_correct) { //Функция фильтра
TZak Zakaz;
char SUp[31];
while (!Empty(Q_main)) { //все элементы очереди извлекаем
Zakaz = Pop(Q_main);
if ((Zakaz.h == 15 && Zakaz.m == 20 && Zakaz.s >= 35) || (Zakaz.h == 15 && Zakaz.m > 20) ||
(Zakaz.h > 15 && Zakaz.h < 18) || (Zakaz.h == 18 && Zakaz.m < 50) || (Zakaz.h == 18 && Zakaz.m == 50 && Zakaz.s <= 10)) //оставляем только те, которые удовлетворяют условию
{
if (Empty(Q_correct))
Create(Q_correct, Zakaz);
else
Push(Q_correct, Zakaz);
}
}
return;
}
int main()
{
char ch;
FILE* log;
TQ Q_1, Q_2;
int n;
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
do {
log = fopen("log.txt", "a"); //Открытие лог файла
printf("\nN - Добавить элемент в очередь c клавиатуры;\nT - Добавить элемент в очередь из текстового файла;\nD - Удалить N элементов очереди;\nR - Удалить неудовлетворяющие элементы;\nF - Освободить очередь;\nE - Выход;\nВаш выбор?");
scanf("\n");
ch = getchar(); fflush(stdin);
ch = toupper(ch);
switch (ch) { //Интерактивный выбор в меню
case 'N': AddElem(Q_1); outLOG(Q_1, log); //добавляем элемент вручную, выводим в лог
break;
case 'T': AddTxt(Q_1); outLOG(Q_1, log); //добавляем элемент из текстового, выводим в лог
break;
case 'D': //удаляем N элементов
printf("Введите N:"); scanf("%d", &n);
PopN(Q_1, n); outLOG(Q_1, log);
break;
case 'R': //фильтр
Filter(Q_1, Q_2);
fprintf(log, "Искомая очередь:\n");
Q_1 = Q_2;
if (!Empty(Q_2))
outLOG(Q_2, log);
else
fprintf(log, "Пусто\n");
break;
case 'E': return 0; //выход
default:
printf("Нет такой команды\nPress any key");
_getch();
}
fclose(log);
} while (ch != 'E');
return 0;
}