towi_parallelism
towi_parallelism

Reputation: 1471

Reading from file in C++, dealing with blanks

I am tying to read from a text file in C++98. It has a pattern, but sometimes a field is empty:

ID Name Grade level  
1 a 80 A
2 b    B
3 c 90 A

How can I read from file such that I can ignore the blanks? ( I wish I could simply use Regex: \d*)

Is there any simple way of doing that?

Upvotes: 1

Views: 106

Answers (1)

mukunda
mukunda

Reputation: 2995

You need to use what knowledge you have about the input to make assumptions about what is missing. You can use std::stringstream to parse individual terms from a text line. In other words std::stringstream deals with blanks by ignoring spaces and getting a complete term only, for example std::stringstream("aaa bbb") >> a >> b will load strings a with "aaa" and b with "bbb".

Here is an example program that parses the input, making a robust parser from scratch can be difficult, but if your input is strict and you know exactly what to expect then you can get away with some simple code:

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

//-----------------------------------------------------------------------------
// holds a data entry
struct Entry {
    int id;
    std::string name;
    int grade;
    std::string level;

    Entry() {
        // default values, if they are missing.
        id = 0;
        name = "Unknown";
        grade = 0;
        level = "?";
    }

    void ParseFromStream( std::stringstream &line ) {

        std::string s;
        line >> s;

        if( s[0] >= '0' && s[0] <= '9' ) {
            // a number, this is the ID.
            id = atoi( s.c_str() );

            // get next term
            if( line.eof() ) return;
            line >> s;
        }

        if( s[0] >= 'a' && s[0] <= 'z' || s[0] >= 'A' && s[0] <= 'Z' ) {
            // a letter, this is the name
            name = s;

            // get next term
            if( line.eof() ) return;
            line >> s; 
        }

        if( s[0] >= '0' && s[0] <= '9' ) {
            // a number, this is the grade
            grade = atoi( s.c_str() );

            // get next term
            if( line.eof() ) return;
            line >> s; 
        }

        // last term, must be level
        level = s;
    } 
};

//-----------------------------------------------------------------------------
int main(void)
{
    std::ifstream input( "test.txt" );

    std::string line;
    std::getline( input, line ); // (ignore text header)

    while( !input.eof() ) {
        Entry entry;

        std::getline( input, line ); // skip header
        if( line == "" ) continue; // skip empty lines.

        entry.ParseFromStream( std::stringstream( line ));

        std::cout << entry.id << ' ' << entry.name << ' ' << 
                     entry.grade << ' ' << entry.level << std::endl;

    }

    return 0;
}

Upvotes: 1

Related Questions