Reading .txt file

closed account (iA5S216C)
I want to read a .txt file with multiple lines, like this example and output them
in the program (format: Name/Amount of numbers/Numbers):
1
2
3
4
5
Don     2   2 1
Julia   1   8
Robert  0
Maria   5   2 3 9 8 1
James   3   4 5 7


This is an example of my output using my code below:
1
2
3
4
5
6
Don     2   2 1
Julia   1   8
Robert  0
Maria   5   2 3 9 8 1
James   3   4 5 7
James   7   7 7 7 7 7 7 7


As you see it makes an extra line, using the last voornaam and cijfer, but why?
(Hopefully you can read through the dutch names)

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
void toon_teken_voor_teken ( ifstream& infilevar, ofstream& outfilevar )
{
    while ( infilevar )
    {
        char voornaam[7];
        infilevar >> voornaam;
        if ( voornaam )
        {
            cout << voornaam << "\t";
            outfilevar << voornaam << "\t";
            int cijfer, aantal_cijfers;
            infilevar >> cijfer;
            if ( cijfer == 0 )
            {
                cout << cijfer << endl;
            }
            else
            {
                if ( cijfer )
                {
                    aantal_cijfers = cijfer;
                    cout << aantal_cijfers << "\t";
                    outfilevar << aantal_cijfers << "\t";
                }
                for ( int teller = 0 ; teller <= (aantal_cijfers-1) ; teller++ )
                {
                    infilevar >> cijfer;
                    if ( cijfer )
                    {
                        cout << cijfer << " ";
                    }
                }
                cout << endl;
            }
        }
    }
}

int main ()
{
    cout << "Naam\tAantal\tGemiddeld" << endl;
    ifstream leesbestandsvar ("uitslagen.txt");
    ofstream nieuwbestandsvar ("nieuwuitslagen.txt");
    if ( leesbestandsvar )
    {
        toon_teken_voor_teken(leesbestandsvar, nieuwbestandsvar);
    }
    else
    {
        cout << "Leesbestand niet gevonden." << endl;
    }
    return 0;
}
Last edited on
Put an empty line at the end of the .txt file. I haven't screwed around with C++ in a while, but I do remember that working at least.
closed account (iA5S216C)
Well since this is for homework, I can't change the file. And it should be universal.
Are you allowed to screw with the file through the program, like with input?

If so, you can just open an ifstream into the file with the ios_base::app option, and add a newline.
closed account (iA5S216C)
No, probably not. Just to read it. But why doesnt my program work/does it make an extra line?
Last edited on
Move the while checking after getting input:
1
2
3
4
5
6
while ( true ) // condition moved
{
    char voornaam[7];

    if ( infilevar >> voornaam ) // here
        break; // exit the loop 

Otherwise the last execution of the loop will have an invalid infilevar
closed account (iA5S216C)
Erm if I do that it will only run for the first line [Don 2 2 1].
Sorry, I forgot negation...
if ( !(infilevar >> voornaam) )
closed account (iA5S216C)
Thanks mate, it works now.
But could you explain to me why?
Here is explained what the program does with a simplified version of your code:

1
2
3
4
5
while ( infilevar )
{
    infilevar >> voornaam;
    // ... 
}
while the stream infilevar is good execute the next block

read input - it may fail
do stuff - if input failed it gets executed anyway with odd results
go back to 1


1
2
3
4
5
6
while ( true )
{
    if ( !(infilevar >> voornaam) )
        break;
    // ... 
}
always execute the next block

read input and check for failure - infilevar >> voornaam returns true if after input infilevar is good
if checking failed exit from the while block
do stuff
go back to 1


The only difference between the two version is when you check the file state
The problem is that you execute the entire contents of the loop without regard to the success or failure of attempting to read a voornaam from the file.
1
2
3
4
5
6
7
8
while (infilevar)  // Always true until after an attempt was made to read past EOF
{
  char firstname[7];
  infilevar >> firstname;  // Success or failure happens here

  // Now execute the rest of the loop even though the last input may have failed
  ...
}

The solution is to check for failure after reading but before the rest of the loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while (true)  // It doesn't matter here whether file is good or bad
{
  char firstname[7];

  // Try to get something from the file
  infilevar >> firstname;

  // Now it matters.
  // Check to see if the last attempt to read the file worked or not.
  // If not, then quit the loop.
  if (!infilevar) break;

  // Otherwise we continue with the rest of the loop
  ...
}

Bazzy's code just combined lines 6 and 11 into a single line:
1
2
  // Try to get something from the file. On failure, quit the loop.
  if (!(infilevar >> firstname)) break;

Hope this helps.

[edit] Oops! Sorry Bazzy. I'll go away. :-\
Last edited on
closed account (iA5S216C)
Ah now I understand, thank you so much guys !
Topic archived. No new replies allowed.