Есть задание по С++: https://drive.google.com/file/d/0B7zD9kDjFhBzSzJWd1kzcHNWWXNzWkpaaHNQWGtxUXFvQ3Fz/view?usp=sharing
Сам бинарный файл который надо прочитать: https://drive.google.com/file/d/0B7zD9kDjFhBzd1VUVG8tbzdMb1lEWXBoWnlWTUhpbVFmZ18w/view?usp=sharing
Снизу приведена моя реализация решения.
Насколько я понял в файле только 2 человека, после того как я вывожу информацию о 2, программа перестает адекватно работать, то есть при вводе команд информация больше не выводится. Как я заметил при отладке переменная idSize, которая отвечает за размер выводимого блока информации, при последующих вызовах всегда равно 0, соответственно ничего и не выводится - логично, но тем не менее я не могу понять почему ей перестают присваиваться значения из бинарного файла.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int select(char var, ifstream &fin, string path, int numPers) {
cout << "numPers = " << numPers << endl;
if (var == 'e') { // закрытие программы командой "e"
fin.close();
}
else {
int intVar = var - '0'; // приведение команды типа char к int
cout << "intVar = " << intVar << endl;
int bytePos = 1; // Положение указателя чтения из файла
fin.seekg(bytePos);
int currentPos = 1; // Идентификатор текущего пользователя
if (intVar > numPers) { // Если ведено число больше кол-ва людей в файле , вывод сообщения что информации нет.
cout << "There are no information under this ID." << endl;
return 0;
}
else {
while (currentPos != intVar) { // Пока текущее id не равно запрашиваемому выполняется алгоритм
bytePos++; //который исчет 1 байт информации соответсвующего ID и сохраняет его в bytePos
fin.seekg(bytePos);
int lastSize = 0; // Размер последнего выведенного блока
fin.read((char*)&lastSize, 1);
cout << "lastSize =" << lastSize << " "; // эти выводы необязательны, использовал для себя , для вывода промежуточной информации при отладке
bytePos = bytePos + lastSize + 1;
cout << "bytePos =" << bytePos << " ";
fin.seekg(bytePos);
currentPos++;
cout << "currentPos =" << currentPos << endl;
}
}
bytePos += 3; // перемещаем еще на 3 байта чтобы перейти к самой информации
for (int k = 0; k < 6; k++) { // Алгоритм вывода соответвующей информации в зависимости от типа данных
fin.seekg(bytePos); //состоит из 6 иттераций так как 6 блоков информации
cout << "bytePos =" << bytePos << endl;// определяет размер каждого блока
int idSize = 0;
fin.read((char*)&idSize, 1);
cout << "idSize =" << idSize << endl;
if (idSize == 0) { // Если блок пропущен , переходит к следующему
bytePos += 2;
continue;
}
char* name = new char[idSize]; // Использую динамический массив char, длина которого равно значению байта, который отвечает за длину блока информации
int nameInt =0;
if (k == 3 || k==5) { // для блоков 3 и 5 которые численного типа использую другой обработчик информации
bytePos++;
fin.seekg(bytePos);
fin.read((char*)&nameInt, idSize);
cout << " " << nameInt << " ";
}
else { // для блоков типа char
bytePos++;
fin.seekg(bytePos);
fin.read((char*)name, idSize);
for (int j = 0; j < idSize; j++) {
cout << name[j];
}
}
bytePos += idSize + 1;
}
}
cout << "Works";
}
int main()
{
string path = "UserData.bin";
ifstream fin;
fin.open(path);
if (fin.is_open())
{
cout << "All is good!" << endl;
cout << "Enter comand:" << endl;
char var; // id запрашиваемого человек
bool checkComand; // проверка на допустимую команду
char arrayComand[11] = {'0','1','2','3','4','5','6','7','8','9','e'};
int numPers = 0; // Кол-во человек в списке
fin.seekg(0);
fin.read((char*)&numPers, 1);
while (fin.is_open()) { // пока открыт файл, читаю команды с клавиатуры
cin >> var;
if (var == 'E') var = 'e';
for (int i = 0; i < 11; i++) {
if (var == arrayComand[i]) {
select(var, fin, path , numPers); // функция выводы информации запрашиваемому человеку
checkComand = true;
break;
}
}
if (!checkComand) continue;
}
}
else
{
cout << "Error: it's not working :(";
}
fin.close();
}
Вам стоит определиться, что именно вы должны получить после разбора файла (какая получится структура данных), разбить процесс разбора на части и сформировать эту структуру. Использование полученной структуры - это уже другая задача. Если разделить задачу на части, найти ошибку будет куда проще.
Ну и использование стандартной библиотеки сильно облегчает жизнь.
Я бы сделал примерно так (концептуально, тут могут быть ошибки):
using namespace std;
using byte = char; // В C++17 есть нормальный std::byte
struct User{
byte id;
map<byte, vector<byte>> dataSet; // Предполагаю, что идентификатор не повторяются
};
User parseUser(std::iostream& in){
User user;
in.read(&user.id, 1);
if(!in){
// error
}
byte blockSize;
in.read(&blockSize, 1);
int signedBlockSize = blockSize;
while(signedBlockSize > 0){
// читаем id, читаем размер данных, читаем данные. Не забываем уменьшать signedBlockSize
}
}
vector<User> parseFile(std::iostream& in){
vector<User> ret;
byte usersCount;
in.read(&usersCount, 1);
if(!in){
// error
}
for(int i = 0; i < usersCount; ++i){
ret.push_back(parseUser(in));
}
return ret;
}
Как минимум, тут еще нужно обрабатывать ошибки чтения файла и ошибки формата пакета, но для вашей задачи это может быть не важно.
Дальше с этой структурой уже можно делать что угодно, например, искать пользователей по id (но тогда лучше положить их в map
, а не в vector
) - но если вы при этом допустите ошибку, в отладчике вы скорее всего увидите, что ошибка не в парсинге файла, а в интерпретации структуры. Ну или наоборот.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть multiset<multiset<int>> cnt; Хочу отсортировать cnt по последнему элементу multiset-овКак это сделать?
В Visual C++ рекомендуется использовать функцию strcat_s, и другие функции с _s на концеОна принимает размер буфера, по этому при ее использовании...
Нашел задачу на двумерный массив и не понятно как код писать, сам недавно начал учит с++
Найти сумму положительных элементов массива A = {a [i]}, что удовлетворяют условию: b <= a [i] <= dНаписал код но не могу понять почему оно не работает...