lllook
lllook

Reputation: 749

reading from istringstream using getline and maybe strtok somehow?

I want to read data from stream, which has specific format, such as:

"number:name_that_can_contain_spaces:string,string,string..." without quotes where ... means that I dont know how many strings are there separated with commas and strings can have spaces before and after it but not in the middle of string, I want to stop reading at new line

I only come up with using getline() and store each line into string, but I dont know how to continue, if there is something like strtok(line, ":",":",",","\n") which would parse it for me or I have to parse it myself character by character

example of valid line format is:

54485965:abc abc abc:    some string, next string , third string\n

parsed result would be:

int 54485965
string "abc abc abc"
string "some string"
string "next string"
string "third string"

Upvotes: 1

Views: 1891

Answers (1)

Nikolay K
Nikolay K

Reputation: 3850

You can read line with std::getline and then split it with std::string::find and std::string::substr. In the code below we read line from file data, then find : (so everything before it becomes number which we parse into int with std::stoi) and throw away first part. Similar we do it with name. And in the end we fill std::list with strings separated by ,.

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <exception>
#include <stdexcept>

struct entry {
    std::string            name;
    int                    number;
    std::list<std::string> others;
};

int main(int argc, char** argv) {
    std::ifstream input("data");
    std::list<entry> list;
    std::string line;
    while(std::getline(input, line)) {
        entry e;
        std::string::size_type i = 0;

        /* get number from line */
        i = line.find(":");
        if(i != std::string::npos) {
           e.number = stoi(line.substr(0, i));
           line = line.substr(i + 1);
        } else {
            throw std::runtime_error("error reading file");
        }

        /* get name from line */
        i = line.find(":");
        if(i != std::string::npos) {
           e.name = line.substr(0, i);
           line = line.substr(i + 1);
        } else {
            throw std::runtime_error("error reading file");
        }

        /* get other strings */
        do {
            i = line.find(",");
            e.others.push_back(line.substr(0, i));
            line = line.substr(i + 1);
        } while(i != std::string::npos);
        list.push_back(e);
    }
    /* output data */
    for(entry& e : list) {
        std::cout << "name:   "   << e.name   << std::endl;
        std::cout << "number: " << e.number << std::endl;
        std::cout << "others: ";
        for(std::string& s : e.others) {
            std::cout << s << ",";
        }
        std::cout << std::endl;
    }
    return 0;
}

Upvotes: 2

Related Questions