Detecting the end of line in a text file

Pages: 12
closed account (21R4z8AR)
I need to read 4 variables from a text file but sometimes the line could have less than 4 values to read from. I need to be able to detect if a line has ended and produce an error message and skip to the next line in the file.
This is some of the bits from the code that I'm looking at. Sorry I'm new to all this I don't know the terminology.

for (int i = 0; i <= numLines; i++)
{
inputFile >> firstValue;

if (inputFile.peek() == '\n')
{
cerr << "ERROR: First value only, ignoring line of the input file";
continue;
}

I thought checking for a '\n' would work but apparently the text files that I'm using done have any '\n', so I'm at a complete loss.
closed account (21R4z8AR)
The input text files look like this:

44

100 90 usable BothMatch

110 120 broken NoMatch

183

170 140 usable BothMatch
1
2
3
4
5
6
7
8
9
10
11
12
string line;
while(getline(input, line)){
   stringstream ss(line);
   ss >> a >> b >> c >> d;
   if(not ss){
      //wrong data type or wrong number of parameters
   }
   if(not ss.eof()){
      //remaining characters
      // (¿may you have whitespace at the end? remove them with ss >> std::ws; )
   }
}


> I thought checking for a '\n' would work but apparently the text files that I'm using done have any '\n', so I'm at a complete loss.
¿could it be a windows/linux/mac format issue?
closed account (21R4z8AR)
What is the ss supposed to be?
Just a name of a variable of type stringstream. Read up on stringstream. Makes working with files easier
Last edited on
closed account (21R4z8AR)
Is there any way to check if its the wrong data type and produce an error message for that and separately check if its the wrong number of parameters, AND do it it for each variable in between a b c and d
Yes. Just read each variable separately and test after each one.
closed account (21R4z8AR)
Why is this so difficult lol, when I try the

int a
ss >> a
if (!ss)
{
cerr << "not an integer";
}

The !ss always results in true even when in the file it is an integer.
An example (accepting lines of 1 integer or 3 integers):

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
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

void proc1(int a) {
    cout << a << '\n';
}

void proc3(int a, int b, int c) {
    cout << a << ',' << b << ',' << c <<'\n';
}

int main() {
    string line;
    while (getline(cin, line)) {
        istringstream sin(line);
        int a, b, c;
        if (!(sin >> a)) {
            if (sin.eof())
                cout << "missing a\n";
            else
                cout << "bad a\n";
        }
        else if (!(sin >> b)) {
            if (!sin.eof())
                cout << "bad b\n";
            else
                proc1(a);
        }
        else if (!(sin >> c)) {
            if (sin.eof())
                cout << "missing c\n";
            else
                cout << "bad c\n";
        }
        else {
            if (!(sin >> ws).eof())
                cout << "extra crap\n";
            else
                proc3(a, b, c);
        }
    }
}

Last edited on
closed account (21R4z8AR)
That would be perfect if I could get 'sin >> a' to work properly
I have no idea what the problem could be. You've shown some unformatted code with missing semicolons, but I really don't know what to make of it. You need to paste a complete, runnable program for me to see what's actually going on. Preferably in code tags, if you can manage it.

Anyway, surely my example works for you?
closed account (21R4z8AR)
Okay nevermind as far as im aware right now it all works. A couple more questions
1. idk what I did but cout is "ambiguous" now. What could I have possibly changed?
2. Is there anyway to make an error message if there was extra data in the line?
closed account (21R4z8AR)
never mind lol now its not ambiguous, but I still have my second question.
The "extra crap" branch is where it ends up if it detects non-whitespace after the final integer.
closed account (21R4z8AR)
Ah I see thank you so much for the help :)
closed account (21R4z8AR)
does eof inside the getline loop work like "end of line"?
Yes, in the context of a stringstream, eof means "end of line" (i.e., no more data to read from the input, so really the same thing).

Note that I've simplified that test a little bit. It says "if you don't detect eof (after skipping any whitespace from the current position), then there's extra crap on the line".
Last edited on
closed account (21R4z8AR)
AHH nevermind its not working still :(
Could there be a problem that the data is coming from a file not cin?
Also the last two variables are strings in my code :/
You would obviously need to show me a runnable example of the problem. How else could I possibly help? The devil's in the details.

But of course it needs to be changed for your strings. I assume you've done that. It's not just going to magically work trying to read strings as ints.
Last edited on
closed account (21R4z8AR)
So I broke down the general gist of my program to this and it works so I guess im just missing something in my main program, Ill have to figure it 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
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
#include <iostream>
#include <iomanip>
#include <fstream>
#include <math.h>
#include <string>
#include <sstream>

using namespace std;

int main()
{
	ifstream inputFile;
	char inputName[1024] = { '\0' };
	string c = "c";
	string d = "d";
	int a = 0;
	int b = 0;
	string line;
	istringstream sin;

	cin >> inputName;
	inputFile.open(inputName);

	while (getline(inputFile, line))
	{
		istringstream sin(line);

		if (!(sin >> a))
		{
			if (sin.eof())
			{
				cerr << "\nError no more data";
				break;
			}
			else
			{
				cerr << "\nincorrect datatype";
			}
		}

		else if (!(sin >> b))
		{
			if (sin.eof())
			{
				cerr << "\na value only";
				continue;
			}
			else
			{
				cerr << "\nincorrect data type";
			}
		}
		else if (!(sin >> c))
		{
			cerr << "\na and b value only";
			continue;
		}
		else if (c != "x" && c != "y")
		{
			cerr << "\nC value isnt correct";
			continue;
		}

		else if (!(sin >> d))
		{
			cerr << "\na and b and c value only";
			continue;
		}
		else if (d != "x" && d != "y")
		{
			cerr << "\nd value isnt correct";
			continue;
		}
		else if (!(sin >> ws).eof())
		{
			cerr << "\nignorning extra data";
			continue;
		}
	}
	return 0;
}
Pages: 12