Чтение и запись в файл .dat в c ++ - PullRequest
0 голосов
/ 27 мая 2020

Я сейчас учусь программировать на C ++. Я пробиваюсь через проект программирования, который нашел в Интернете, и пытаюсь воссоздать его построчно, ища, почему определенные вещи работают именно так. Проект представляет собой простую систему бронирования отелей, которая имеет систему меню и сохраняет вводимые пользователем данные, например имя, адрес, номер телефона и т. Д. c.

Я пытался понять, что делают определенные части этого кода. Я хочу ввести пользовательский ввод и сохранить его в файле .dat, однако он, похоже, не работает, и я не уверен, почему. Есть ли лучший способ чтения и записи в текстовый файл.

Это функция, которая проверяет, свободна ли комната или зарезервирована:

#include <fstream>
#include "Hotel.h"

int Hotel::check_availabilty(int room_type){

    int flag = 0;
    std::ifstream room_check("Room_Bookings.dat",std::ios::in);

    while(!room_check.eof()){

        room_check.read((char*)this, sizeof(Hotel));

        //if room is already taken
        if(room_no == room_type){

            flag = 1;
            break;

        }
    }
    room_check.close();//close the ifstream
    return(flag);//return result
}

Это код, который бронирует номер:

#include "Hotel.h"
#include "check_availability.cpp"

void Hotel::book_a_room()
{

    system("CLS");//this clears the screen

    int flag;
    int room_type;


    std::ofstream room_Booking("Room_Bookings.dat");

    std::cout << "\t\t" << "***********************" << "\n";
    std::cout << "\t\t  " << "THE GREATEST HOTEL" << "\n";
    std::cout << "\t\t" << "***********************" << "\n";
    std::cout << "\t\t " <<"Type of Rooms "<< "\t\t Room Number" "\n";
    std::cout << "\t\t" << " Standard" << "\t\t   1 - 30" "\n";
    std::cout << "\t\t" << " Luxury" << "\t\t\t  31 - 45" "\n";
    std::cout << "\t\t" << " Royal" << "\t\t\t  46 - 50" "\n";

    std::cout << "Please enter room number: ";
    std::cin >> room_type;

    flag = check_availabilty(room_type);

    if(flag){
        std::cout << "\n Sorry, that room isn't available";
    }
    else{

        room_no = room_type;
        std::cout<<" Name: ";
        std::cin>>name;
        std::cout<<" Address: ";
        std::cin>>address;
        std::cout<<" Phone No: ";
        std::cin>>phone;

        room_Booking.write((char*)this,sizeof(Hotel));
        std::cout << "Your room is booked!\n";

    }
    std::cout << "Press any key to continue...";
    getch();
    room_Booking.close();


}

А это файл Hotel.h

class Hotel
{
    int room_no;
    char name[30];
    char address[50];
    char phone[10];

    public:
        void main_menu();
        void book_a_room();
        int check_availabilty(int);
        void display_details();
};

Я не совсем понимаю, что делает эта часть в то время как l oop:

room_check.read((char*)this, sizeof(Hotel));

Если вам нужна дополнительная информация, спрашивайте. Приветствуются любые подсказки и советы, как сделать это лучше.

Ответы [ 3 ]

4 голосов
/ 27 мая 2020

Hotel - полностью автономный тип без выделения кучи или ссылок на внешние объекты. Следовательно, можно сериализовать его состояние, просто записав представление объекта в память, и десериализовать, выполнив обратное. и сохраните их прямо там, где находится объект Hotel, на который указывает this. Фактически, вы восстанавливаете содержимое памяти в том виде, в каком оно было до записи на диск.

(Обратите внимание, что (char*)this лучше записать как reinterpret_cast<char *>(this) в C ++.)

Это обратное этой операции:

room_Booking.write((char*)this,sizeof(Hotel));

Такой способ сериализации дает некоторые преимущества вместо создания собственной структуры данных.

  • Это действительно просто; с помощью одной строки кода вы можете сериализовать, а с помощью другой - десериализовать.
  • Сериализация и десериализация выполняются очень быстро, поскольку не выполняется синтаксический анализ или преобразование.

Однако есть Также некоторые недостатки:

  • Формат на диске диктуется расположением объектов в памяти. Если вы переупорядочите или измените какие-либо члены данных класса, старые сериализованные объекты больше не будут загружаться правильно. Более того, операция чтения будет успешной, но вы останетесь с состоянием объекта мусора.
  • Вы зависите от порядка байтов хоста для числовых типов. Файл данных, созданный на машине с прямым порядком байтов, будет бесполезен на машине с прямым порядком байтов.
  • Очень легко случайно создать уязвимость в системе безопасности. Например, с помощью только этого кода злоумышленник может легко создать файл .dat, который вызывает чтение за пределами диапазона, когда вы go читаете элементы «строки» (символьного массива), просто не завершая NUL ни один из эти массивы.

Использование другого механизма сериализации, например, JSON, XML, протокольных буферов и т. д. c. требует больше работы, но результаты более переносимы, потому что ваша структура данных на диске больше не привязана к макету объекта в памяти.

1 голос
/ 27 мая 2020

room_check содержит данные в виде потока. room_check.read((char*)this, sizeof(Hotel)); считывает данные из потока и сохраняет их в текущем экземпляре Hotel (this). sizeof(Hotel) сообщает функции, сколько байтов должно быть прочитано из потока.

room_check содержит данные класса Hotel в том порядке, в котором они указаны в объявлении класса:

int room_no;
char name[30];
char address[50];
char phone[10];

С этим объявлением известен размер экземпляра гостиницы в байтах: sizeof(1*int + 30*char + 50*char + 10*char). Содержимое файла данных хранится в членах этого самого текущего экземпляра Hotel.

1 голос
/ 27 мая 2020

при выполнении

room_check.read((char*)this, sizeof(Hotel));

вы читаете из потока и записываете в буфер, но вам нужно указать, сколько символов должно быть прочитано ...

...