Mason
Mason

Reputation: 31

Reading in line by line from a file with different variable types

For a project I'm doing we have to populate a queue with "House" objects. The "House" objects get their information from a file called "data.dat". Each line of the file is another thing that goes into the house object. So first I take a char* for the address, then an int, another int, a third int, and then another char*.

We aren't allowed to use strings to get the char* variables which I believe is where I'm running into my problem. Every time I compile it tells me I have a segmentation fault. Here is the area of my queue.cpp that I'm pretty sure the error is in

    #include"queue.h"
    #include<iostream>
    #include<fstream>
    #include<istream>

    Queue::Queue(const char *filename){
        head = NULL;
        tail = NULL;

        std::ifstream infile(filename);

        char * address = NULL;
        int footage = 0;
        int bedrooms = 0;
        int bathrooms = 0;
        char * features = NULL;

        while(!infile.eof()){
                while(infile.get() != '\n'){
                        //std::cout << infile.get(); 
                        infile.get(address[i]);
                }
                infile >> footage >> bedrooms >> bathrooms;
                while(infile.get() != '\n'){
                        infile.get(features[i]);
                }

                enqueue(House(address, footage, bedrooms, bathrooms, features));
                }
        infile.close();
}

Here is the house object header file:

        House();
        House(char * ad, int fo, int be, int ba, char * fe);
        char * getAddress();
        int getFootage();
        int getBedrooms();
        int getBathrooms();
        char * getFeatures();

        void setAddress(char * ad);
        void setFootage(int fo);
        void setBedrooms(int be);
        void setBathrooms(int ba);
        void setFeatures(char * fe);
        friend std::ostream& operator<<(std::ostream& out, House& house);

    private:
        char * address;
        int footage;
        int bedrooms;
        int bathrooms;
        char * features;
};

Upvotes: 1

Views: 68

Answers (2)

sehe
sehe

Reputation: 393924

For fun, here's a cleaned up version

  • mainly it replaces char* with std::string (since we're doing C++)
  • it makes the whole thing self-contained.
  • It uses correct input validation (don't use while (!infile.eof()), check extraction operators)

I didn't implement your Queue :)

Live On Coliru

#include <iostream>
#include <fstream>
#include <sstream>

struct House {
    House()
        : address(), footage(0), bedrooms(0), bathrooms(0), features() 
    { }
    House(std::string ad, int fo, int be, int ba, std::string fe) 
        : address(ad), footage(fo), bedrooms(be), bathrooms(ba), features(fe) 
    { }

    std::string getAddress()   const { return address;   }
    int         getFootage()   const { return footage;   }
    int         getBedrooms()  const { return bedrooms;  }
    int         getBathrooms() const { return bathrooms; }
    std::string getFeatures()  const { return features;  }

    void setAddress(std::string  ad) { address   = ad; }
    void setFootage(int          fo) { footage   = fo; }
    void setBedrooms(int         be) { bedrooms  = be; }
    void setBathrooms(int        ba) { bathrooms = ba; }
    void setFeatures(std::string fe) { features  = fe; }

    friend std::ostream &operator<<(std::ostream &out, House const &house) {
        return out << "Address: "      << house.getAddress()   << '\n'
                   << "Footage: "      << house.getFootage()   << '\n'
                   << "Bed rooms:   "  << house.getBedrooms()  << '\n'
                   << "Bath rooms:   " << house.getBathrooms() << '\n'
                   << "Features: "     << house.getFeatures()  << '\n';
    }

  private:
    std::string address;
    int         footage;
    int         bedrooms;
    int         bathrooms;
    std::string features;
};

struct Queue {
    Queue(std::string  filename);

    struct Node {
        House value;
        Node* next;
    };

    Node *head, *tail;

    void enqueue(House const& h) {
        // TODO
        std::cout << h << "\n";
    }
};

Queue::Queue(std::string filename) : head(nullptr), tail(nullptr) {

    std::ifstream infile(filename);

    std::string address;
    int footage = 0;
    int bedrooms = 0;
    int bathrooms = 0;
    std::string features;

    std::string line; // lines

    while (getline(infile, address) && getline(infile, line)) {
        std::istringstream iss(line);

        if (iss >> footage >> bedrooms >> bathrooms && getline(iss, features)) {
            enqueue(House(address, footage, bedrooms, bathrooms, features));
        }

    }
}


int main()
{
    Queue q("data.dat");
}

For input:

Blv. Dreams Abroken 24, 78377d XG, ClassyCode
2 4 1 pool sauna porch indoor-parking
Oyi. Qernzf Noebxra 24, 78377q KT, PynfflPbqr
3 8 2 cbby fnhan cbepu vaqbbe-cnexvat

It prints the output:

Address: Blv. Dreams Abroken 24, 78377d XG, ClassyCode
Footage: 2
Bed rooms:   4
Bath rooms:   1
Features:  pool sauna porch indoor-parking

Address: Oyi. Qernzf Noebxra 24, 78377q KT, PynfflPbqr
Footage: 3
Bed rooms:   8
Bath rooms:   2
Features:  cbby fnhan cbepu vaqbbe-cnexvat

Upvotes: 0

Roman Pustylnikov
Roman Pustylnikov

Reputation: 1932

You need to initialize the features and address first, either by using new or by creating it as array of chars of some length. The way you do it you're trying to write to the memory that was't assigned yet - hence buffer overflow.

Upvotes: 0

Related Questions