0

I have a strange problem. I don't even know if it's the code. When reading a binary file, two consecutive strings with length 3 have to be read and stored. I do this with a char array. This is then simply set to the string variable.

Strange is that with the first string at the end always an F is appended and with the second not.

Console output

In the console output you can see that the string has a length of 4 at the first mark. The second one has a length of 3.

The strange thing is that the creation and reading of both strings from the binary file were handled with the same procedure in the code and that in the first one an F is always appended.

Here is the code places with which the part in the binary file is read. It is the variable fromDestination in case 'F'.

        switch (type ) {
        case 'F':
            for(size_t i = 0; i < sizeof(aFromDestination); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aFromDestination[i]),sizeof(char));
            }
            //aFromDestination[3] = '\0';
            fromDestination = aFromDestination;
            aFromDestination[0] = 0;
            break;
        case 'R':
            for(size_t i = 0; i < sizeof(aPickupLocation); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aPickupLocation[i]),sizeof(char));
            }
            pickupLocation = aPickupLocation;
            aPickupLocation[0] = 0;
            break;
        case 'H':
            for(size_t i = 0; i < sizeof(aHotel); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aHotel[i]),sizeof(char));
            }
            hotel = aHotel;
            aHotel[0] = 0;
            break;
        }

travelagency.cpp

#include "travelagency.h"
#include "flightbooking.h"
#include "hotelbooking.h"
#include "rentalcarreservation.h"

TravelAgency::TravelAgency()
{

}

void TravelAgency::readFile()
{
    int countFlights = 0, countRents = 0, countHotels = 0;
    double allFlightsCosts = 0, allRentCosts = 0, allHotelCosts = 0;
    std::string zeile;
    std::string fileName = "bookings.txt";
    std::ifstream inputFilestream;

    inputFilestream.open(fileName.c_str(), std::ifstream::in);
    if (!inputFilestream.is_open())
        std::cerr << "Datei konnte nicht geoeffnet werden" << std::endl;

    while(!inputFilestream.eof()) {

        types type;
        std::stringstream zeileStringStream;
        std::string fromDate, toDate, pickupLocation, returnLocation, company, hotel, town, fromDestination, toDestination, airline;
        unsigned int id;
        double price;
        int numberOfAttribute = 1, countFields = 0, numberOfLine = 1;

        getline(inputFilestream, zeile);
        zeileStringStream << zeile;

        for(auto &k : zeile) {
            if(k == '|') {
                numberOfAttribute++;
            }
        }

        while(!zeileStringStream.eof()) {
            std::string attribute;

            switch (countFields) {
            case 0: {
                getline(zeileStringStream, attribute, '|');
                for(char character : attribute) {
                    switch (character) {
                    case 'F': {
                        type = Flight;
                    }
                        break;
                    case 'R': {
                        type = Rent;
                    }
                        break;
                    case 'H': {
                        type = Hotel;
                    }
                        break;
                    }
                }
                break;
                }
            case 1: {
                getline(zeileStringStream, attribute, '|');
                id = stoi(attribute);
                break;
                }
            case 2: {
                getline(zeileStringStream, attribute, '|');
                price = stod(attribute);
                break;
                }
            case 3: {
                getline(zeileStringStream, fromDate, '|');
                break;
            }
            case 4: {
                getline(zeileStringStream, toDate, '|');
                break;
            }
            case 5: {
                switch (type) {
                case Flight:
                    getline(zeileStringStream, fromDestination, '|');
                    break;
                case Rent:
                    getline(zeileStringStream, pickupLocation, '|');
                    break;
                case Hotel:
                    getline(zeileStringStream, hotel, '|');
                    break;
                }
                break;
                }
            case 6: {
                switch (type) {
                case Flight:
                    getline(zeileStringStream, toDestination, '|');
                    break;
                case Rent:
                    getline(zeileStringStream, returnLocation, '|');
                    break;
                case Hotel:
                    getline(zeileStringStream, town);   //end of the line. Fehler bei der ausgabe.
                    break;
                }
                break;
                }
            case 7: {
                switch (type) {
                case Flight:
                    getline(zeileStringStream, airline);    //end of the line. Fehler bei der ausgabe.
                    break;
                case Rent:
                    getline(zeileStringStream, company);    //end of the line. Fehler bei der ausgabe.
                    break;
                default:
                    break;
                }
                break;
                }
            }
            countFields++;
        }

        switch (type) { //obejekte erstellen und speichern
        case Flight: {
            FlightBooking *f = new FlightBooking(id, price, fromDate, fromDestination, toDestination, airline);
            bookings.push_back(f);
            allFlightsCosts += price;
            countFlights++;
            break;
            }
        case Rent: {
            RentalCarReservation *r = new RentalCarReservation(id, price, fromDate, toDate, pickupLocation, returnLocation, company);
            bookings.push_back(r);
            allRentCosts += price;
            countRents++;
            break;
            }
        case Hotel: {
            HotelBooking *h = new HotelBooking(id, price, fromDate, toDate, hotel, town);
            bookings.push_back(h);
            allHotelCosts += price;
            countHotels++;
            break;
            }
            }
        numberOfLine++;
    }

    inputFilestream.close();

    std::cout << "Es wurden " << countFlights << " Flugbuchungen im Wert von " << allFlightsCosts << "," << std::endl;
    std::cout << countRents << " Mietwagenbuchungen im Wert von " << allRentCosts << " und" << std::endl;
    std::cout << countHotels << "  Hotelreservierungen im Wert von " << allHotelCosts << " eingelesen." << std::endl;
}

void TravelAgency::readBinaryFile()
{
    int countFlights = 0, countRents = 0, countHotels = 0;
    double allFlightsCosts = 0.0, allRentCosts = 0.0, allHotelCosts = 0;

    char type;
    char aFromDestination[3], aToDestination[3];
    char aFromDate[8], aToDate[8];
    char aHotel[15], aTown[15], aAirline[15], aCompany[15], aPickupLocation[15], aReturnLocation[15];
    std::string fromDate, toDate, pickupLocation, returnLocation, company, hotel, town, fromDestination, toDestination, airline;
    long id;
    double price;

    std::string inputFileName = "bookingsBinary.bin";
    std::ifstream inputFileStream;

    inputFileStream.open(inputFileName.c_str(),std::ifstream::binary | std::ifstream::in);
    if(!inputFileStream) {
        std::cerr << inputFileName << " kann nicht geoeffnet werden!" << std::endl;
    }

    do{

        //fall 1
        inputFileStream.read(reinterpret_cast<char*>(&type), sizeof(char));
        //fall 2
        inputFileStream.read(reinterpret_cast<char*>(&id),sizeof(long));
        //fall 3
        inputFileStream.read(reinterpret_cast<char*>(&price),sizeof(double));

        //fall4
        for(size_t i = 0; i < sizeof(aFromDate); i++) {
            inputFileStream.read(reinterpret_cast<char*>(&aFromDate[i]),sizeof(char));
        }
        fromDate = aFromDate;
        aFromDate[0] = 0;

        //fall 5
        for(size_t i = 0; i < sizeof(aToDate); i++) {
            inputFileStream.read(reinterpret_cast<char*>(&aToDate[i]),sizeof(char));
        }
        toDate = aToDate;
        aToDate[0] = 0;

        //fall6
        switch (type ) {
        case 'F':
            for(size_t i = 0; i < sizeof(aFromDestination); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aFromDestination[i]),sizeof(char));
            }
            //aFromDestination[3] = '\0';
            fromDestination = aFromDestination;
            aFromDestination[0] = 0;
            break;
        case 'R':
            for(size_t i = 0; i < sizeof(aPickupLocation); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aPickupLocation[i]),sizeof(char));
            }
            pickupLocation = aPickupLocation;
            aPickupLocation[0] = 0;
            break;
        case 'H':
            for(size_t i = 0; i < sizeof(aHotel); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aHotel[i]),sizeof(char));
            }
            hotel = aHotel;
            aHotel[0] = 0;
            break;
        }

        //fall7
        switch (type) {
        case 'F':
            for(size_t i = 0; i < sizeof(aToDestination); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aToDestination[i]),sizeof(char));
            }
            toDestination = aToDestination;
            aToDestination[0] = 0;
            break;
        case 'R':
            for(size_t i = 0; i < sizeof(aReturnLocation); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aReturnLocation[i]),sizeof(char));
            }
            returnLocation = aReturnLocation;
            aReturnLocation[0] = 0;
            break;
        case 'H':
            for(size_t i = 0; i < sizeof(aTown); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aTown[i]),sizeof(char));
            }
            town = aTown;
            aTown[0] = 0;
            break;
        }

        //fall8
        switch (type) {
        case 'F':
            for(size_t i = 0; i < sizeof(aAirline); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aAirline[i]),sizeof(char));
            }
            airline = aAirline;
            aAirline[0] = 0;
            break;
        case 'R':
            for(size_t i = 0; i < sizeof(aCompany); i++) {
                inputFileStream.read(reinterpret_cast<char*>(&aCompany[i]),sizeof(char));
            }
            company = aCompany;
            aCompany[0] = 0;
            break;
        }

        switch (type) { //obejekte erstellen und speichern
        case 'F': {
            FlightBooking *f = new FlightBooking(id, price, fromDate, fromDestination, toDestination, airline);
            bookings.push_back(f);
            allFlightsCosts += price;
            countFlights++;
        }
            break;
        case 'R': {
            RentalCarReservation *r = new RentalCarReservation(id, price, fromDate, toDate, pickupLocation, returnLocation, company);
            bookings.push_back(r);
            allRentCosts += price;
            countRents++;
        }
            break;
        case 'H': {
            HotelBooking *h = new HotelBooking(id, price, fromDate, toDate, hotel, town);
            bookings.push_back(h);
            allHotelCosts += price;
            countHotels++;
        }
            break;
        }

    }while (!inputFileStream.eof());

    inputFileStream.close();

    std::cout << "Es wurden " << countFlights << " Flugbuchungen im Wert von " << allFlightsCosts << "," << std::endl;
    std::cout << countRents << " Mietwagenbuchungen im Wert von " << allRentCosts << " und" << std::endl;
    std::cout << countHotels << "  Hotelreservierungen im Wert von " << allHotelCosts << " eingelesen." << std::endl;
}

void TravelAgency::showAllBookings() const
{
    for (auto &k : bookings) {
        std::cout << k->showDetails() << std::endl;
    }

    //showExpensiveBooking();
}

void TravelAgency::showExpensiveBooking() const
{
    int price;
    int highesPrice = 0;
    int place;

    for(size_t i = 0; i < bookings.size(); i++) {
        price = bookings.at(i)->getPrice();
        if (price > highesPrice) {
            highesPrice = price;
            place = i;
        }
    }
    std::cout << "Hoechster Preis: " << std::endl;
    bookings.at(place)->showDetails();
}

`

I thought it would work to make the char array to length 4 and then shorten it to position 3 after filling.

  • why use a binary file? why allocate things with new? just why in general - something of a monument to bad style. and all calls to read functions must check their return value. – Neil Butterworth Nov 15 '22 at 22:40
  • There's a lot of code there' can you just indicate which read it is that is failing. – john Nov 15 '22 at 22:47
  • @NeilButterworth Reading in a binary file is a task in my internship. The class has a pointer vector. how else should I create an object instead of using new? What do you mean with "all calls to read functions must check their return value"? Is there a other way to do it? – Pittiplatsch Nov 15 '22 at 22:54
  • If you know that the string has a length of three, then just write `str.assign(array, 3)` instead of `str = array;`. The latter code only works if the array contains a null terminated string. – john Nov 15 '22 at 22:54
  • I don't understand. Why are you using `read()` inside a loop that reads one item at a time. The `read()` method is most efficient at replacing the `for` loop and reading a block. – Thomas Matthews Nov 15 '22 at 22:55
  • 2
    `while(!inputFilestream.eof())` is an unforced error. See [Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) for details. – user4581301 Nov 15 '22 at 22:58
  • functions return a value for a reason, such as "i worked/didn't work" - you are supposed to deal with that. and have you heard of unique_ptr? – Neil Butterworth Nov 15 '22 at 23:02
  • *When reading a binary file, two consecutive strings with length 3 have to be read and stored. I do this with a char array. This is then simply set to the string variable.* -- If this is the case, you should write a very simple 5, maybe 10 line `main` program that simply attempts to read your file correctly. All of these other things you're showing us, such as `TravelAgency` classes and what they are doing is actually irrelevant to the problem. – PaulMcKenzie Nov 16 '22 at 00:04

0 Answers0