Как исправить эту ошибку?
Написал программу для класса "Автобусный билет". Всё работает отлично, но когда в конце программы виводится вместимое файла (метод set_inf_to_file), программа останавливается и выскакивет ошибка. Как это исправить?
Вот код:
#include <iostream>
#include <ctime>
#include <fstream>
#include <string>
#include <iomanip>
#include <Windows.h>
#pragma warning(disable:4996);
using namespace std;
class bus_ticket
{
public:
bus_ticket();
bus_ticket(int, int, int);
bus_ticket(const bus_ticket&);
~bus_ticket();
void set_inf(int);
void get_inf();
void set_inf_to_file(bus_ticket);
void get_inf_from_file(string);
int selling();
void selling(int);
void selling(bus_ticket);
string passenger;
static int get_count();
private:
time_t current_date_and_time;
string departure;
string arrival;
int ticket_number;
int seat_number;
int bus_number;
bool status = false;
static int count;
protected:
char control[100] = { 0 };
};
int bus_ticket::count = 0;
bus_ticket::bus_ticket()
{
ticket_number = 1000 + rand() % 9000;
seat_number = 10 + rand() % 40;
bus_number = 1000 + rand() % 9000;
current_date_and_time = time(NULL);
count++;
}
bus_ticket::bus_ticket(int ticket_number_1, int seat_number_1, int bus_number_1)
{
ticket_number = ticket_number_1;
seat_number = seat_number_1;
bus_number = bus_number_1;
current_date_and_time = time(NULL);
count++;
}
bus_ticket::bus_ticket(const bus_ticket& other)
{
this->ticket_number = other.ticket_number;
this->bus_number = other.bus_number;
this->seat_number = other.seat_number;
this->passenger = other.passenger;
this->departure = other.departure;
this->arrival = other.arrival;
this->current_date_and_time = other.current_date_and_time;
count++;
}
void bus_ticket::set_inf(int i)
{
cout << endl << "Enter " << i + 1 << " passenger name: ";
cin >> passenger;
cout << "Enter departure: ";
cin >> departure;
cout << "Enter arrival: ";
cin >> arrival;
cout << endl << endl;
}
void bus_ticket::get_inf()
{
char buffer[100];
tm* timeinfo = localtime(¤t_date_and_time);
const char* format = "%A, %B %d, %Y %H:%M:%S";
strftime(buffer, 100, format, timeinfo);
cout << "Passenger: " << passenger << endl;
cout << "Ticket number: " << ticket_number << endl;
cout << "Date and time of purchase: " << buffer << endl;
cout << "Seat number: " << seat_number << endl;
cout << "Bus number: " << bus_number << endl;
cout << "Departure: " << departure << endl;
cout << "Arrival: " << arrival << endl;
}
void bus_ticket::set_inf_to_file(bus_ticket ticket)
{
ofstream fn("text.txt");
if (!fn.is_open())
{
cout << "File does not exist!" << endl;
}
else
{
fn.write((char*)&ticket, sizeof(bus_ticket));
}
fn.close();
ifstream fn1("text.txt");
if (!fn1.is_open())
{
cout << "File does not exist!" << endl;
}
else
{
bus_ticket ticket1;
cout << "Information about passenger from file: " << endl;
while (fn1.read((char*)&ticket1, sizeof(bus_ticket)))
{
ticket1.get_inf();
}
}
fn1.close();
}
void bus_ticket::get_inf_from_file(string str)
{
ifstream fn(str);
if (!fn.is_open())
{
cout << "File does not exist!" << endl;
}
else
{
string str;
cout << endl;
while (!fn.eof())
{
getline(fn, str);
cout << str << endl;
}
}
fn.close();
}
int bus_ticket::selling()
{
return status;
}
void bus_ticket::selling(int i)
{
set_inf(i);
get_inf();
status = true;
}
void bus_ticket::selling(bus_ticket object)
{
object.get_inf_from_file("text1.txt");
status = true;
}
int bus_ticket::get_count()
{
return count;
}
bus_ticket::~bus_ticket()
{
count--;
}
int main()
{
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
srand(time(NULL));
int b = 0;
bus_ticket* object1 = new bus_ticket();
cout << "For entering info about passenger from keyboard press 1, from file - press 2: ";
cin >> b;
switch (b)
{
case 1:
object1->selling(0);
if (object1->selling())
{
cout << "Ticket is sold out!" << endl << endl;
}
cout << "Current number of tickets: " << object1->get_count() << endl << endl;
break;
case 2:
object1->selling(*object1);
if (object1->selling())
{
cout << "Ticket is sold out!" << endl << endl;
}
cout << "Current number of tickets: " << object1->get_count() << endl << endl;
break;
}
delete object1;
bus_ticket object2;
cout << "For entering info about passenger from keyboard press 1, from file - press 2: ";
cin >> b;
switch (b)
{
case 1:
object2.selling(1);
if (object2.selling())
{
cout << "Ticket is sold out!" << endl << endl;
}
cout << "Current number of tickets: " << object2.get_count() << endl << endl;
break;
case 2:
object2.selling(object2);
if (object2.selling())
{
cout << "Ticket is sold out!" << endl << endl;
}
cout << "Current number of tickets: " << object2.get_count() << endl << endl;
break;
}
object2.set_inf_to_file(object2);
return 0;
}
Ошибка текстом: Exception thrown at 0x0095ABF2 in Lab№3.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD.
Ответы (1 шт):
void bus_ticket::set_inf_to_file(bus_ticket ticket)
{
ofstream fn("text.txt");
if (!fn.is_open())
{
cout << "File does not exist!" << endl;
}
else
{
fn.write((char*)&ticket, sizeof(bus_ticket));
Здесь записываете классы string из bus_ticket. В этих классах не строки, а указатели на выделенную память.
}
fn.close();
ifstream fn1("text.txt");
if (!fn1.is_open())
{
cout << "File does not exist!" << endl;
}
else
{
bus_ticket ticket1;
cout << "Information about passenger from file: " << endl;
while (fn1.read((char*)&ticket1, sizeof(bus_ticket)))
Здесь вы загружаете идентичную копию элементов, которую неправильно записали. То-есть bus_ticket ticket1 - это полная копия bus_ticket ticket.
{
ticket1.get_inf();
}
Здесь вызывается деструктор bus_ticket ticket1. И аргумент bus_ticket ticket лишается всех своих строк.
}
fn1.close();
Тут вызывается деструктор bus_ticket ticket, и он пытается удалить память, которой у него уже нет. Происходит исключение неправильного освобождения памяти.
}
Записывать в файл нельзя просто write(..sizeof(структура)). Нужно писать все три строки в файл индивидуально, их содержимое, а не указатели.
Вот пример записи :
void bus_ticket::write(ofstream & fn){
fn << passenger ;
fn.write((char*)¤t_date_and_time,sizeof(current_date_and_time));
fn << departure ;
fn << arrival ;
fn.write((char*)&ticket_number,sizeof(ticket_number));
fn.write((char*)&seat_number,sizeof(seat_number));
fn.write((char*)&bus_number,sizeof(bus_number));
fn.write((char*)&status,sizeof(status));
fn.write(&(control[0]),sizeof(control));
}
