-1

I am doing a project with I/O and structs. My text file is below. I need to make my program store each string in a different part of the array of structs I have created. I am having a problem making it separate them in the array when it senses a blank line.

Steps for the program: 1. Read each line with data and store it in the struct array until it reaches a blank line. 2. Output each string in a different group or on a different line.

Text file:

ecl:gry pid:860033327 hcl:#fffffd
byr:1937 iyr:2017 cid:147 hgt:183cm

iyr:2013 ecl:amb cid:350 pid:028048884
hcl:#cfa07d byr:1929

hcl:#ae17e1 iyr:2013 cid:150
eyr:2024
ecl:brn pid:760753108 byr:1931
hgt:179cm

hcl:#cfa07d eyr:2025 pid:166559648
iyr:2011 ecl:brn hgt:59in cid:230

My code:

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

const int SIZE = 4;

struct Passports {

    std::string singlePass;

};

int main()
{
    Passports records[SIZE];
    std::string fileName = "some_file.txt";
    std::ifstream inFile(fileName);
    std::string line, data;
    if (inFile.is_open()){
        while (!inFile.eof()) {
            getline(inFile, line);
            std::istringstream ss(line);
            for (int i = 0; i < SIZE; i++) {
                while (ss >> records[i].singlePass) {
                    std::cout << records[i].singlePass;
                }
                
            }
        }
    }
    else {
        std::cout << "Error opening file! " << std::endl;
    }   
}
krainey916
  • 17
  • 5
  • [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/) Change `while (!inFile.eof()) { getline(inFile, line); ... }` to `while (getline(inFile, line)) { ... }` Also, your code is not handling the blank lines between records, or the fact that each record has multiple lines. Basically, you are just looping through the file displaying the 1st 4 whitespace-separated tokens of each line. But not all lines have 4 tokens – Remy Lebeau Mar 30 '22 at 19:38
  • 1
    Explain in detail exactly what you want to happen when the program finds a blank line and exactly what happens when the program does not find a blank line. Quite often clearly writing out exactly what you want a program to do is all that's needed to shake the solution loose. If not, add the explanation to the question. – user4581301 Mar 30 '22 at 19:39
  • Each time the program senses a plank like the next information will be initialized as an element in the array. – krainey916 Mar 30 '22 at 19:42
  • Your implementation is not going to work correctly. You need to read two lines and parse them, then decide which variable gets assigned according to the 3 char prompt. The fields are not constant in any of the input. – Thomas Matthews Mar 30 '22 at 19:45
  • That is skipping over the details. What does it really have to do? Step by step. If you cannot describe the process, you stand almost no chance of being able to code the process. – user4581301 Mar 30 '22 at 19:45
  • Steps for the program: 1. Read each line with data and store it in the struct array until it reaches a blank line. 2 Output each string in a different group or on a different line. – krainey916 Mar 30 '22 at 19:48
  • I recommend editing the question rather than adding the information in comments. Comments do not format well, are not permanent, and not having all the question information in one place leads to confusion. – user4581301 Mar 30 '22 at 19:50

1 Answers1

0

You should model the data using a struct.

struct Record
{
    std::string input_line1;
    std::string input_line2;
    friend std::istream& operator>>(std::istream& input, Record& r);
};
std::istream& operator>>(std::istream& input, Record& r)
{
    std::getline(input, r.input_line1);
    std::getline(input, r.input_line2);
    input.ignore(1000000, '\n'); // ignore the blank line.
    return input;
}

Your input code would look like:

std::vector<Record> database;
Record r;
while (inFile >> r)
{
    database.push_back(r);
}

By placing the detailed input inside of the struct, you can modify the input method later without having to change the input code in main().

Detailed Parsing

You could add in a field or two to advance your program (no need to add all the fields at this point, then can be added later).

struct Passport
{
    std::string ecl;
    friend std::istream& operator>>(std::istream& input, Passport& p);
};
std::istream& operator>>(std::istream& input, Passport& p)
{
    std::string  text_line1;
    std::string  text_line2;
    std::getline(input, text_line1);
    std::getline(input, text_line2);
    size_t       position = text_line1.find("ecl:");
    if (position != std::npos)
    {
       // extract the value for ecl and assign to p.ecl
    }
    return input;
}

There are many different methods for parsing the string, the above is alluding to one of them.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154