File parsing help

I am trying to get this file program to parse my text from my file but im having a little trouble. I tried to create some code that gets the last position of the colon but I cant seem to figure it out. I made a new getline with a | delimiter, ideally I would like to use the colon again as a separator and store each piece of text thats separated by a colon in its own. I almost got it working but not quite.

The text in my file is this:

Population UK: 66400000 | Test 1
Population France: 66990000 | Test 2
Population Japan: 126800000 | Test 3


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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

using namespace std;

void OpenFile();
void ParsingText();
void ParsMultipleLines();

int main()
{
	int choice{};

	cout << "What example would you like to view" << endl;
	cout << "1) Open File example" << endl;
	cout << "2) Parsing Text example" << endl;
	cout << "3) Parse Multiple Lines Example" << endl;
	cin >> choice;

	switch (choice)
	{
		case 1:
			OpenFile();
			break;
		case 2:
			ParsingText();
			break;
		case 3:
			ParsMultipleLines();
			break;
		default:
			throw invalid_argument("Invalid Choice");
	}

	return 0;
}

void OpenFile()
{
	string inFileName = "test.txt";

	ifstream inFile;

	inFile.open(inFileName);

	if (inFile.is_open())
	{
		string line;

		while (!inFile.eof())
		{
			getline(inFile, line);
			cout << line << endl;
		}
		inFile.close();
	}
}

void ParsingText()
{
	string filename = "stats.txt";

	ifstream input;

	input.open(filename);

	if (!input.is_open())
	{
		cout << "Error" << endl;
	}

	while (input)
	{
		string line{};

		getline(input, line, ':');

		int population{};

		input >> population;
		input >> ws; //C++ 11 feature that reads and discards white space.

		if (!input) //If the stream reaches the end of the file then stop reading. If this wasnt here we
		{			//would have a malformed string on the next blank line.
			break;
		}

		cout << "'" << line << "' -- '" << population << "'" << endl;
	}

	input.close();
}

void ParsMultipleLines()
{
	string filename = "stats.txt";

	ifstream input;

	input.open(filename);

	if (!input.is_open())
	{
		cout << "Error" << endl;
	}

	while (input)
	{
		string countryName{};

		getline(input, countryName, ':');

		int population{};

		input >> population;


		string test{};

		getline(input, countryName, '|');

		input >> test;

		/*string::size_type position = line.find(':');

		if (line.npos != position)
		{
			line2 = line.substr(position + 1);
			line = line.substr(0, position);
			getline(input, line, ':');
			input >> line2;
		}*/

		input >> ws; //C++ 11 feature that reads and discards white space.


		if (!input) //If the stream reaches the end of the file then stop reading. If this wasnt here we
		{			//would have a malformed string on the next blank line.
			break;
		}
		cout << "Country: " << countryName << endl;
		cout << "Population: " << population << endl;
		cout << "Test: " << test << endl;

		cout << endl;
		cout << endl;


		cout << "'" << countryName << "' -- '" << population << "' " << test << endl;
	}

	input.close();
}
Last edited on
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
void ParsMultipleLines()
{
	string filename = "stats.txt";

//	ifstream input;
//	input.open(filename);
//	if (!input.is_open())
//	{
//		cout << "Error" << endl;
//	}
        istringstream input( "Population UK: 66400000 | Test 1\n"
                             "Population France: 66990000 | Test 2\n"
                             "Population Japan: 126800000 | Test 3\n" );

	string first, middle, last;
	while ( getline( input, first, ':' ) && getline( input, middle, '|' ) && getline( input, last ) )
	{
           string dummy, country;
           unsigned long long population;
           stringstream( first ) >> dummy >> country;
           stringstream( middle ) >> population;
           cout << country << " -- " << population << "     " << last << '\n';
	}

//	input.close();
}


What example would you like to view
1) Open File example
2) Parsing Text example
3) Parse Multiple Lines Example
3
UK -- 66400000      Test 1
France -- 66990000      Test 2
Japan -- 126800000      Test 3
Last edited on
I was thinking more along the lines of this, which i got working. Thanks anyways though, your code gave me a spark and helped me figure this out.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void ParsMultipleLines()
{
	string filename = "stats.txt";

	ifstream input;

	input.open(filename);

	if (!input.is_open())
	{
		cout << "Error" << endl;
	}

	while (input)
	{
		//input >> ws; //C++ 11 feature that reads and discards white space.

		string countryName{};
		unsigned long long population{};
		string test{};
		string test2{};

		getline(input, countryName, ':');

		input >> population;

		getline(input, test, ':');

		getline(input, test2, '\n');

		if (!input) //If the stream reaches the end of the file then stop reading. If this wasnt here we
		{			//would have a malformed string on the next blank line.
			break;
		}
		cout << "Country: " << countryName << endl;
		cout << "Population: " << population << endl;
		cout << "First Test:" << test << endl;
		cout << "Second Test:" << test2 << endl;

		cout << endl;
	}

	input.close();
}




Country: UK
Population: 66400000
First Test: Test 1
Second Test: test1

Country: France
Population: 66990000
First Test: Test 2
Second Test: test2

Country: Japan
Population: 126800000
First Test: Test 3
Second Test: test3
Last edited on
I was thinking more along the lines of this, which i got working.

When I run your code with your input from the original post, I get this output:
Country: Population UK
Population: 66400000
First Test: | Test 1
Population France
Second Test: 66990000 | Test 2

hmm, thats strange, im compiling with VS 2019, not sure if that matters or not, I didnt change any settings, using it vanilla.
stats.txt must look different than
Population UK: 66400000 | Test 1
Population France: 66990000 | Test 2
Population Japan: 126800000 | Test 3


Why? Because there's no second test field, not to mention no way in the current code to handle the | in the middle of the line.

An example of a stats.txt that would produce the desired output is with the current code is
Population UK: 66400000 Test 1: test1
Population France: 66990000 Test 2: test2
Population Japan: 126800000 Test 3: test3


-Albatross

EDIT: Typos.
Last edited on
I modified the code, I still cant get it to work correctly but its much closer i think. Hopefully. Working with files isnt something i've really delved into, but I want to learn to do it and be able to parse and extract text from it. I'm not really sure whats wrong.

EDIT: I got it mostly working with a few issues. Code below
Last edited on
Ok so I got it almost working, It does what I want BUT, I cannot have spaces inbetween the characters which is an issue, I need to be able to get text with spaces:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void ParseMultipleLines()
{
	string filename = "stats.txt";

	ifstream input;

	input.open(filename);

	if (!input.is_open() || input.eof())
	{
		cout << "Error" << endl;
	}

	while (input)
	{
		string countryName{};
		input >>  countryName;
		
		unsigned long long population{};
		input >> population;
		
		string test{};
		input >> test;
		
		string test2{};
		input >> test2;
		
		if (!input) //If the stream reaches the end of the file then stop reading. If this wasnt here we
		{			//would have a malformed string on the next blank line.
			break;
			cout << "No file contents found" << endl;
		};

		//Output Results
		cout << "Data contents of file" << endl;
		cout << "Country: " << countryName << endl;
		cout << "Population: " << population << endl;
		cout << "First Test: " << test << endl;
		cout << "Second Test: " << test2 << endl;

		cout << endl;
	}

	input.close();
}



File contents:

UK 66400000 Test_1 test1
France 66990000 Test_2 test2
Japan 126800000 Test_3 test3
Last edited on
@Ch1156,
It is difficult to answer your questions if you keep changing the problem.

Please FIX your input file and DO NOT FURTHER CHANGE IT. The format has changed several times in this thread.

If you want text with spaces between words then you will:
(a) have to agree on some delimiter (:, |, comma whatever) to identify separate fields, since spaces would no longer be available to fulfil that function. If you are going to rely on the population being the only field starting with a digit then say so; we have no idea what you are putting in your "test" fields.
(b) use getline() rather than >> for input, since the latter would react to any space as a delimiter to end a field.

There is nothing wrong with reading an entire field into a std::string first and then separating it subsequently with, e.g, stringstreams or stoi() etc. if you want some fields to be numeric.
Topic archived. No new replies allowed.