I have to write a program that requests a file name from the user and then counts all of the words in the file. The hypothetical file has 55 words in it, but my program counts 56 words.
Every change I've tried making to my code has only gotten me farther from the correct answer, either resulting in 0 words or causing it to become an infinite loop. I'm seriously stuck on where the extra word/character is coming from, so I was hoping someone might see an error that I'm missing.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char filename[20];
cout << "Enter a file name: ";
cin >> filename;
ifstream fin;
fin.open(filename);
if (fin.fail())
{
exit(1);
}
char next;
int word = 0;
while (fin)
{
fin.get(next);
if (next == ' ' || next == '\n')
word ;
}
fin.close();
cout << "The file contains " << word << " words.";
return 0;
}
CodePudding user response:
I debugged and modified your code. Here is my version:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
char filename[20];
cout << "Enter a file name: ";
cin >> filename;
ifstream fin;
fin.open(filename);
if (fin.fail()) {
exit(1);
}
char next;
// When the last char in file is not newline or space,
// we need to count the last word manually
bool hasWord = false;
int word = 0;
while (fin) {
fin.get(next);
if (fin.fail()) {
if (hasWord)
word ;
break;
}
if (next == ' ' || next == '\n') {
word ;
hasWord = false;
} else
hasWord = true;
}
fin.close();
cout << "\nThe file contains " << word << " words.";
return 0;
}
Two tips:
- When
ifstream
read the last char of file, it will count it twice. Because the first time ifstream reads it,eof()
will not be true. The second time ifstream reads it,eof()
will be true. But thenext
variable keeps the last value. So it counts twice. Solution is when ifstream read a char, we check it again byfin.fail()
. - If the last char of file is not a space or newline. We need count the last word manually.
BTW, my code is based on your version. I didn't handle the mixed space or newline.
Docs about eof()
:
This function only reports the stream state as set by the most recent I/O operation; it does not examine the associated data source. For example, if the most recent I/O was a get() which returned the last byte of a file, eof() returns false. The next get() fails to read anything and sets the eofbit. Only then does eof() return true.
CodePudding user response:
I changed the while loop to use a string instead of a char as suggested to me in the comments, and it worked. Here's the new code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
char filename[20];
cout << "Enter a file name: ";
cin >> filename;
ifstream fin;
fin.open(filename);
if (fin.fail())
{
exit(1);
}
std::string word;
int count = 0;
while (fin >> word)
{
count ;
}
fin.close();
cout << "The file contains " << count << " words.";
return 0;
}