bug with input of text files

I took this function from one of my bigger programs, and made it a program in itself for the convenience of you.

anyway, it reads from a given text file, and everything works fine with it, but there is a bug:
if the file contents ends with a space, the last word is repeated. therefore, if the text file contains "hello " the output to the screen is "hello hello".
but if the text file just contains "hello" it outputs "hello" just fine..
the problem seems to lie in "filein.eof"'s ability to detect the end of the file. can anyone tell me how to fix this bug?

and i suggest compiling and running this yourself so you understand what i mean better. all you have to do is create a text file named sunday in the same folder as the project for this code (atleast if your using code::blocks), and type a sentence inside that text file. compile and run. then try it again with a space at the end. see what i mean? the last word always gets repeated if there is a space at the end of the file... please help

oh and by the way, im using windows at the moment, but if you are using linux, you must change line 10 from:

if (nday==0)*filename=((char*)"sunday.txt");

to
if (nday==0)*filename=((char*)"sunday");

since text files dont have ".txt" in linux.. anyway.. heres my code:


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 <fstream>
using namespace std;

void readnote(int nday)
{
    char b[256];
    char* filename[256];
    cout << "Your note: \n" << endl;
    if (nday==0)*filename=((char*)"sunday.txt");
    ifstream filein(*filename);
    for (;!filein.eof(); cout << " ")
    {
        filein >> b;
        cout << b;
        if (filein.eof()) break;
        if (filein.fail()) break;
    }
    return;
}
int main()
{
    readnote(0);
    return 0;
}


any help on how to fix this bug would be greatly appreciated. sorry for the lengthy description =P just trying to be specific..

and by the way, i simplified my source code alot so you can focus on the bug.
This is because a whitespace is still data, so after you read your last word, if there is a whitespace in the file then "eof()" does not return true. But the ">>" operator you use to copy the stream from "filein" to "b" generally ignores whitespace.

You could clear "b" at the start of every iteration in your loop.
and by
clear "b"
you mean..?
Last edited on
Inseart a line between Lines 13 and 14 and put b = ""; There by setting it to nothing. This way if you hit a white space at the end of file, you won't see a repeat of the last word read because "b" won't contain anything.
Last edited on
while( filein >> b ) std::cout << b << " ";

because there is a defined conversion between a stream and a boolean (equivalent to stream.good(), I believe)
This is probably a better solution, less code always is.
hmm i found this to work.. although a quick solution i admit, ill revise it later
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
#include <iostream>
#include <fstream>
using namespace std;

void readnote(int nday)
{
    char b[256];
    char* filename[256];
    cout << "Your note: \n" << endl;
    if (nday==0)*filename=((char*)"sunday.txt");
    ifstream filein(*filename);
    for (;!filein.eof(); cout << " ")
    {
        for (int i=0; i<256; i++)
        {
            b[i]=' ';
        }
        filein >> b;
        cout << b;
        if (filein.eof()) break;
        if (filein.fail()) break;
    }
    return;
}
int main()
{
    readnote(0);
    return 0;
}


thanks for the help computergeek. & others

EDIT:: actually, my for loop doesnt really fix it. it fixed it on my linux laptop, but when i put the program back on my windows desktop, it prints a weird charactor at the end... grr...
i guess i could use a new variable every time, but that would take up some unnecessary memory
Last edited on
The problem is that when you fill your array with ' 's , it doesn't have a terminating 0 char.
Any way, don't use this method. Instead of ending the loop if an error occurred now you get an empty line.
If you find the line I posted difficult to understand, you might as well write
1
2
3
4
5
6
for(;/*this check is redundant*/;/*the increment is weird..*/){
   filein >> b;
   if (filein.eof()) break;//these two could be replaced with "if(!filein.good()) break"
   if (filein.fail()) break;//or "if(!filein) break;
   cout << b << " ";
}
@hamsterman
your code fixes the repeat bug, but now if there is a word without a space at the end, it doesnt even get printed

now if the text file contains "hello " output is "hello " // which is good
but if the text file contains "hello" output is ""

=(

if only there was a way i could test if there is a space with nothing after it...
Last edited on
Move the "cout << " above the if checks.
ill try when i get home. all i have is access to my ubuntu laptop at the moment, and it wants to act funny with linux... i got windows xp pro at home though =)
Move the "cout << " above the if checks.
That would just bring back the previous problem. I'll look into it in a minute..
Apparently you shouldn't check for eof. When you read the last word, eof is set even though the reading was successful. You only need to skip printing if there was a failure (in which case fail() returns true).
If you used the line I posted previously, it would work too, because conversion to bool is equivalent to !fail(). Note that good() cares about eof, so can't be used here.
Last edited on
Topic archived. No new replies allowed.