HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppModerate

Parsing text file in C++

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
textfileparsing

Problem

I have a text file that contains name, age, salary, hoursWorked, randomText and are filled with different delimiters.

Text file:

susan:25-2600,28[asd]
mary:21-2200,38[asd]
john:23-3400,46[asd]


Instead of breaking them into individual strings using the code shown below:

string name,age,salary,hoursWorked,randomText;
ifstream readFile("textfile.txt");

while(getline(readFile,line))   {
    stringstream iss(line);
    getline(iss, name, ':');
    getline(iss, age, '-');
    getline(iss, salary, ',');
    getline(iss, hoursWorked, '[');
    getline(iss, randomText, ']');
}
readFile.close();


What are some better strategies other than coding it this way?

Side note

I declared all the variables to strings because of the getline() method.

Solution

I would create a class and define an input operator:

struct Person
{
    std::string name;
    std::string age;
    std::string salary;
    std::string hoursWorked;
    std::string randomText;

    friend std::istream& operator>>(std::istream& str, Person& data)
    {
        std::string line;
        Person tmp;
        if (std::getline(str,line))
        {
            std::stringstream iss(line);
            if ( std::getline(iss, tmp.name, ':')        && 
                 std::getline(iss, tmp.age, '-')         &&
                 std::getline(iss, tmp.salary, ',')      &&
                 std::getline(iss, tmp.hoursWorked, '[') &&
                 std::getline(iss, tmp.randomText, ']'))
             {
                 /* OK: All read operations worked */
                 data.swap(tmp);  // C++03 as this answer was written a long time ago.
             }
             else
             {
                 // One operation failed.
                 // So set the state on the main stream
                 // to indicate failure.
                 str.setstate(std::ios::failbit);
             }
        }
        return str;
    }
    void swap(Person& other) throws() // C++03 as this answer was written a long time ago.
    {
        swap(name,        other.name);
        swap(age,         other.age);
        swap(salary,      other.salary);
        swap(hoursWorked, other.hoursWorked);
        swap(randomText,  other.randomText)
    }
};


Now your code looks like this:

Person   data;
while(readFile >> data)
{
    // Do Stuff
}


PS. I noticed you were using string and ifstream without the std::. This suggests you have using namespace std; in your code. Please don't do that. see Why is “using namespace std;” considered bad practice?

Don't explictly close() a file unless you are going to check that it worked (or are going the re-open). Prefer to let the destructor do the closing (that way it is exception safe). See: My C++ code involving an fstream failed review

Code Snippets

struct Person
{
    std::string name;
    std::string age;
    std::string salary;
    std::string hoursWorked;
    std::string randomText;

    friend std::istream& operator>>(std::istream& str, Person& data)
    {
        std::string line;
        Person tmp;
        if (std::getline(str,line))
        {
            std::stringstream iss(line);
            if ( std::getline(iss, tmp.name, ':')        && 
                 std::getline(iss, tmp.age, '-')         &&
                 std::getline(iss, tmp.salary, ',')      &&
                 std::getline(iss, tmp.hoursWorked, '[') &&
                 std::getline(iss, tmp.randomText, ']'))
             {
                 /* OK: All read operations worked */
                 data.swap(tmp);  // C++03 as this answer was written a long time ago.
             }
             else
             {
                 // One operation failed.
                 // So set the state on the main stream
                 // to indicate failure.
                 str.setstate(std::ios::failbit);
             }
        }
        return str;
    }
    void swap(Person& other) throws() // C++03 as this answer was written a long time ago.
    {
        swap(name,        other.name);
        swap(age,         other.age);
        swap(salary,      other.salary);
        swap(hoursWorked, other.hoursWorked);
        swap(randomText,  other.randomText)
    }
};
Person   data;
while(readFile >> data)
{
    // Do Stuff
}

Context

StackExchange Code Review Q#38879, answer score: 15

Revisions (0)

No revisions yet.