fstream help

Sorry for the Bad Title

So lets say i have a program and a file, 'Program' and 'stuff.txt'. stuff.txt conatins the following.

NAME: "John Doe"
AGE: 12
GENDER: IceCream
....blah blah and so on.

How would i have my program to view this file and when its see's NAME it creates a new string called NAME and then in that stores in that string "John Doe" and then goes onto the second line recogonizes the word AGE creates a int then stores the age in that int. How will i be able to do this and have the program read this file like that and then store that data.
I would use getline to read each line into a string. Then I would parse that string to see if it contained "NAME:". if it does, I would assign the string that follows "NAME:" In your input to another string name "Name". if it doesn't match "NAME:", I would then check to see if it matched "AGE:", and so forth.
Would i be able to use this article?http://www.cplusplus.com/articles/4N3hAqkS/
Yes, I think that would be a great starting point.
its nice article
For spaces you reall don't need getline(...):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>
#include <iostream>
#include <sstream>

int main(int argc, char** arv)
{
    // initialize input stream with data
    std::istringstream ins("this is a    text    ");
    
    // load words to this container
    std::string out;
    
    // read the words until some data in the input stream
    while (ins >> out)
    {
            std::cout << out << std::endl;
    }
    return 0;
}
I am doing this because i am making a config file parser with comment parsing as well
So i got the getline to stop at the ':' symbol and store NAME into a variable but then how would i be able to get the actual value to another variable?
NAME: John Doe
I have the entire word NAME in a string but how would i be able to store the rest of the line "John Doe" from the ':' character?

getline(config, variable, ':');

(config is the file im reading from) the code above reads all of the word NAME but i want to get the rest
You could call getline a second time (this time without the ':', so the default '\n' is used) to get the rest of the line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

const char testdata[] =
"NAME: \"John Doe\"\n"
"AGE: 12\n"
"GENDER: IceCream\n"
"BLAHBLAH: blah blah and so on.\n";

int main() {
    istringstream config(testdata);

    string name;
    string value;

    while(    getline(config, name, ':')
           && getline(config, value    ) ) {
        cout << "[" << name << "] = [" << value << "]\n";
    }

    return 0;
}


[NAME] = [ "John Doe"]
[AGE] = [ 12]
[GENDER] = [ IceCream]
[BLAHBLAH] = [ blah blah and so on.]


(You can see there's some leading space for the values here, so you might want to trim the string before storing it.)

But I would prob read the whole line and then split it using string::find() and string::substr() so I can handle badly formed lines.

Changing testdata to ("forgetting" the : on the AGE line):

const char testdata[] =
"NAME: \"John Doe\"\n"
"AGE 12\n"
"GENDER: IceCream\n"
"BLAHBLAH: blah blah and so on.\n";

the output is:

[NAME] = [ "John Doe"]
[AGE 12
GENDER] = [ IceCream]
[BLAHBLAH] = [ blah blah and so on.]


where we get three values [NAME] and [BLAHBLAH] and

[AGE 12
GENDER]

(a name with a newline in it.)

Whereas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

const char testdata[] =
"NAME: \"John Doe\"\n"
"AGE 12\n"
"GENDER: IceCream\n"
"BLAHBLAH: blah blah and so on.\n";

int main() {
    istringstream config(testdata);

    string line;
    while(getline(config, line)) {
        size_t pos = line.find(':');
        if(line.npos == pos) {
            cout << "!skipping invalid line!\n";
        } else {
            string name  = line.substr(0, pos);
            string value = line.substr(pos + 1);
            cout << "[" << name << "] = [" << value << "]\n";
        }
    }

    return 0;
}


can spot the error more easily:

[NAME] = [ "John Doe"]
!skipping invalid line!
[GENDER] = [ IceCream]
[BLAHBLAH] = [ blah blah and so on.]


(Still need to trim the leading spaces.)

Andy
Last edited on
I'm not esp. impressed with Viktar Khutko's article:
How to split text into two or more characters
http://www.cplusplus.com/articles/4N3hAqkS/

As coder777 has already pointed out, splitting strings on spaces is better done using operator>> instead of getline with a ' ' delimiter. To start with, there's no need to ignore empty strings, as you don't get any.

And it's better to use

14
15
16
    while (getline(ins, out, ' '))
    {
        // etc 


than

14
15
16
17
    while (ins.good())
    {
        getline(ins, out, ' ');
        // etc 


(in parallel with the way coder777 is using operator>> above.)

operator>> also deals with other whitespace chars while the article's first example does not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    const char testdata[] =
    "this is a    text\n"
    "with more than  \n"
    "\n"
    "\n"
    "one line!\n";

    std::istringstream ins(testdata);
    
    std::string out;
    
    while (getline(ins, out, ' '))
    {
        if (!out.empty())
            std::cout << "[" << out << "]\n";
    }

    return 0;
}


Output (strings now in []s so can spot newline infested strings]

[this]
[is]
[a]
[text
with]
[more]
[than]
[


one]
[line!
]


whereas changing the while loop to

18
19
20
21
    while (ins >> out)
    {
        std::cout << "[" << out << "]\n";
    }


results in the following output (as preferred)

[this]
[is]
[a]
[text]
[with]
[more]
[than]
[one]
[line!]


Andy
Last edited on
Topic archived. No new replies allowed.