0

I am currently learning to program in c++. I am making my way through a programming project I found online, and try and recreate it line by line looking up why certain things work the way they do. The project is a simple hotel booking system that has a menu system and saves users input i.e name, address, phone number etc.

I have been looking about trying understand what certain parts of this code do. I want to take a users input and save it to a .dat file, however it doesnt seem to work and im not sure why. Is there a better way to read and write to a text file.

This is the function that deals with checking if a room is free or reserved:

#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
}

This is the code that books a room:

#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();


}

And this is the Hotel.h file

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();
};

I dont fully understand what this part of the while loop does:

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

If you need any more info, please ask. Any hints and tips towards making this better would be welcomed.

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
pdhk14
  • 43
  • 2
  • 8
  • 1
    Does ```room_check.read((char*)this, sizeof(Hotel));``` actually do what you think it does? – AksLolCoding May 27 '20 at 15:59
  • 2
    "*I want to take a users input and save it to a .dat file, however it doesnt seem to work and im not sure why.*" What does "doesnt seem to work" mean? What are you expecting to happen and what actually happens? – scohe001 May 27 '20 at 16:00
  • 1
    @MathCoder101 Since there are no references or pointers in the `Hotel` type, there is a good chance that it will actually work. (Not saying it's a good idea.) – cdhowie May 27 '20 at 16:02
  • Thats the thing, im not entirely sure what it does, but im guessing it passes in a char cast and gets the size of the stream based on the variable array size in class Hotel. – pdhk14 May 27 '20 at 16:03
  • im expecting it to take user input and save that to a .dat file. however when i put information into it. it prints on the screen this line "Your room is booked!. but when i open up the .dat file there is nothing in there. – pdhk14 May 27 '20 at 16:08
  • 1
    BTW, there is no significance or standard format for a ".dat" file. It is just another file, and you determine it's format. – Thomas Matthews May 27 '20 at 16:58
  • 1
    I recommend you go through a [good book](https://stackoverflow.com/q/388242/9254539) instead of finding code online and trying to figure out how it works. It will probably be much easier, especially since there are tons of bad C++ code out there. – eesiraed May 27 '20 at 17:17

3 Answers3

4

Hotel is an entirely self-contained type with no heap allocations or references to external objects. Therefore, one can serialize its state by simply writing out the object's representation in memory, and deserialize by doing the opposite.

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

This line of code asks the room_check input stream to read sizeof(Hotel) bytes and store them directly where the Hotel object pointed to by this lives. Effectively, you're restoring the memory contents as they were before being written to disk.

(Note that (char*)this is better written as reinterpret_cast<char *>(this) in C++.)

That's the inverse of this operation:

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

There's some advantages to serializing this way instead of creating your own data structure.

  • It's really easy; with one line of code you can serialize, and with another you can deserialize.
  • Serialization and deserialization is very fast since there is no parsing or conversion happening.

However, there are also some disadvantages:

  • The on-disk format is dictated by the layout of objects in memory. If you reorder or change any class data members, old serialized objects will not load correctly any more. Moreover, the read operation will succeed but you'll be left with a garbage object state.
  • You depend on the endianness of the host machine for number types. A data file created on a little-endian machine will be useless on a big-endian machine.
  • It's very easy to accidentally create a security vulnerability. For example, with just this code, an attacker could easily craft a .dat file that causes out-of-bounds reads when you go to read the "string" (character array) members by simply not NUL-terminating any of those arrays.

Using a different serialization mechanism, such as leveraging JSON, XML, protocol buffers, etc. requires more work but the results are more portable because your data structure on disk is no longer tied to the object's layout in memory.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
1

when doing

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

you are reading from the stream, and write in the buffer, but you need to specify how many characters must be read...

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
1

room_check contains the data as a stream. room_check.read((char*)this, sizeof(Hotel)); reads the data from the stream and stores it in the current instance of Hotel (this). sizeof(Hotel) tells the function how many bites should be read from the stream.

room_check contains the data of the class Hotel in the order it is listed in the class declaration:

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

With this declaration the byte-size of an instance of hotel is known: sizeof(1*int + 30*char + 50*char + 10*char). The content of the dat-file is stored int the members of this very current instance of Hotel.

Thomas Wilde
  • 801
  • 7
  • 15