Если бы еще бинарник заработал
С текстовым вроде разобрался. Сам себя запутал просто
try
{
fs.open("Phone_book.txt", ios::out);
if (!fs.is_open())
throw logic_error("Phone_book.txt can not be opened");
for (int i = 0; i < contacts.size(); i++)
{
fs << contacts[i] << endl;
}
fs.close();
}
catch (logic_error & ex)
{
cerr << "Error: " << ex.what() << endl;
}
Осталось понять, что не так с бинарным. Он вроде записывается, но в одно строчку, а при считывании вылетает
Потому что надо смотреть не текстовым редактором, а
https://www.google.com/search?q=hex+editor
#35 исправлено?
вроде исправил
static void load(string& str, fstream& fs)
{
size_t len;
fs.read((char*)&len, sizeof(size_t));
char* buf = new char[len + 1];
fs.read(buf, len);
buf[len] = 0;
str = buf;
delete[] buf;
}
но оно все равно не работает
Так а с какой ошибкой и где вылетает?
Не понимаю, что не так
len некорректный по каким-то причинам.
Я бы для начала определил на каком этапе это происходит с помощью отладчика или отладочного вывода (например, выводить прочитанные значения в load).
Так вот, я сделал cout << id << name << surname << adds << number << endl; Оно вывелось на экран и слетело
После первого контакта или когда?
Я про
static void load(string& str, fstream& fs)
{
size_t len;
fs.read((char*)&len, sizeof(size_t));
+ cout << len << " ";
char* buf = new char[len + 1];
fs.read(buf, len);
buf[len] = 0;
str = buf;
+ cout << str << endl;
delete[] buf;
}
Я ввел два, вывелось два и слетело. Я выводил в функции read()
я сделал так
Если после второго контакта в файле нет ничего, то видимо просто проверка конца файла не работает, и после неудачной попытки чтения в len остается мусор (не инициализированная переменная).
eof()
вроде меняется после попытки чтения после конца файла, а не просто когда прочитали всё.
Вообще в load
неплохо бы проверять успешность чтения и кидать исключения. А в идеале еще и корректность значений len
(не слишком большое).
Не совсем понимаю, что нужно делать
Либо искать другие способы определять конец файла (например может быть сравнивать текущую позицию и размер файла), либо после реализации этого
просто ловить исключения в main и не читать дальше.
А каким образом это сделать?
tellg()
текущую позицию возвращает.
С получением размера файла в С++ по стандарту всё сложно (хотя начиная с С++17 есть std::filesystem::file_size), но для данного случая подойдет вариант перейти в конец и сохранить значение tellg() как тут или тут.
Но проверки при чтении всё равно стоит сделать, чтобы не ронять программу на любом некорректном файле )
static bool load(string& str, fstream& fs)
{
size_t len;
fs.read((char*)&len, sizeof(len));
if (!fs)
return false;
char* buf = new char[len + 1];
fs.read(buf, len);
buf[len] = 0;
str = buf;
delete[] buf;
return true;
}
bool readBin(fstream& fs)
{
return
load(id, fs)&&
load(name, fs)&&
load(surname, fs)&&
load(adds, fs)&&
load(number, fs);
}
Сделал вот так и оно работает.
только еще один момент, вот тут нужно закрывать файл или нет:
if (fs.is_open())
{
while (obj2.readBin(fs))
cont.push_back(obj2);
fs.close();
}
?