Search code examples
c++istream

How do I read in a specified number of characters from a file while still iterating through it?


I have a file of data like this:

    Judy Henn      2 Oaklyn Road       Saturday 2001
    Norman Malnark 15 Manor Drive      Saturday 2500
    Rita Fish      210 Sunbury Road    Friday   750

I need to assign the first 20 characters as the name, next 20 as address, next 10 as day, and the number as yardSize, using the istream::get() method. My professor is requiring the use of .get() to accomplish this.

I am having a really hard time figuring out how to assign the data from the file to the right variables while still looping.

struct Customer{
    char name[21];
    char address[21];
    char day[11];
    int yardSize;
};

int main(){
    const int arrSize = 50;
    Customer custArr[arrSize];
    int i = 0;
    
    //set up file
    ifstream dataFile;
    dataFile.open("Data.txt");
       
    //try to open file
    if(!dataFile){
        cout << "couldn't open file";
    }
       
    //while dataFile hasn't ended
    while(!dataFile.eof()){
        dataFile.get(custArr[i].name, 21);   
        cout << custArr[i].name;
        i++;
    }
}; //end  

I would have thought that the while loop would assign the first 21 characters into custArr[i].name, then loop over and over until the end of file. However, when I print out custArr[i].name, I get this and ONLY this:

Judy Henn           2 Oaklyn Road       Saturday   2001

I'm not sure how to go about assigning a specified number of characters to a variable, while still iterating through the entire file.


Solution

  • First off, the character counts you mentioned don't match the data file you have shown. There are only 19 characters available for the name, not 20. And only 9 characters available for the day, not 10.

    After fixing that, your code is still broken, as it is reading only into the Customer::name field. So it will try to read Judy Henn into custArr[0].name, then 2 Oaklyn Road into custArr[1].name, then Saturday into custArr[2].name, and so on.

    I would suggest something more like this instead:

    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    using namespace std;
    
    struct Customer
    {
        char name[21];
        char address[21];
        char day[11];
        int yardSize;
    };
    
    int main()
    {
        const int arrSize = 50;
        Customer custArr[arrSize];
        string line;
        int i = 0;
        
        //set up file
        ifstream dataFile("Data.txt");
        if (!dataFile)
        {
            cout << "couldn't open file";
            return 0;
        }
           
        //while dataFile hasn't ended
        while ((i < arrSize) && getline(dataFile, line))
        {
            istringstream iss(line);
            if (iss.get(custArr[i].name, 21) &&
                iss.get(custArr[i].address, 21) &&
                iss.get(custArr[i].day, 11) &&
                iss >> custArr[i].yardSize)
            {
                cout << custArr[i].name;
                ++i;
            }
        }
    
        return 0;
    }