I have written a program that counts words and vowels in an external file. I was able to achieve this by writing two while loops. However, it can only produce the desired results if I comment out one of the while loops, which means it will output just the correct result of one loop. I don't know how to solve this particular case.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int words = 0, vowels = 0;
string word;
char letter;
ifstream inFile;
int main() {
//open file
inFile.open("lorem.txt");
//process file
while (inFile >> word) {
words ;
}
while(inFile.get(letter)){
if (letter == 'a' || letter == 'A' || letter == 'e' || letter == 'E' || letter == 'i'|| letter == 'I' || letter == 'o' || letter == 'O' || letter == 'u' || letter == 'U'){
vowels ;
}
}
cout << "The input file contains "<< words << " words and " << vowels<< " vowels"<<endl;
return 0;
}
CodePudding user response:
At the end of either of your while loops, inFile
has reached the end of the file.
It is clear that both of your while
loops expect to begin reading from the beginning of the file.
Put this line between your two while loops to start reading from the beginning of the file again.
inFile.seekg(0); // Return to byte 0 of the file
CodePudding user response:
I would not recommend to reset the file pointer. Because you would then read the file 2 times.
This is not necessary. If have read the word, then you can check also, if this word has vowels. This can be simply done by iterating over the letters of the word.
So, the preferred solution is something like the below:
#include <iostream>
#include <fstream>
int main() {
std::ifstream inFile("lorem.txt");
int words = 0;
int vowels = 0;
std::string word;
while(inFile >> word) {
words ;
for (char letter : word)
if (letter == 'a' || letter == 'A' || letter == 'e' || letter == 'E' || letter == 'i'|| letter == 'I' || letter == 'o' || letter == 'O' || letter == 'u' || letter == 'U'){
vowels ;
}
}
std::cout << "The input file contains "<< words << " words and " << vowels<< " vowels\n";
}
And, if you want to use a more modern C solution, there are probably additional millions of solutions. One is below:
#include <iostream>
#include <fstream>
#include <sstream>
#include <regex>
#include <iterator>
struct in {
in(const std::initializer_list<char>& il) : ref(il) {}
const std::initializer_list<char>& ref;
};
bool operator,(const char& lhs, const in& rhs) {
return std::find(rhs.ref.begin(), rhs.ref.end(), lhs) != rhs.ref.end();
}
const std::regex re{R"(\w )"};
int main() {
// Open a file and check, if it could be opened
if (std::ifstream inFile("lorem.txt"); inFile) {
// Read the complete file into a string
std::string text(std::istreambuf_iterator<char>(inFile),{});
// Count all words
size_t wordsCount = std::distance(std::sregex_token_iterator(text.begin(), text.end(), re), {});
size_t vowelsCount{};
// Go over all characters in the file (in a string)
for (char c : text)
// If the character is a vowel
if (c, in{'a','e','i','o','u','A','E','I','O','U'})
vowelsCount;
// Show result
std::cout << "The input file contains "<< wordsCount << " words and " << vowelsCount<< " vowels\n";
}
else std::cerr << "\nError: Could not open inpute file\n\n";
}