What is wrong in this program?

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
#include <iostream>
using namespace std;
#include <fstream>
#include <cctype>
int main()
{
    int words=0, u_letters=0, l_letters=0, vowels=0;
    ofstream fout ("Text.txt",ios::out);
    char str[100], s[10], ch;
    cout<<"\nEnter text:";
    cin.getline(str, 100);
    fout<<str;
    fout.close();
    ifstream fin ("Text.txt",ios::in);
    while (!fin.eof())
    {
        fin.getline(s,10,' ');
        words++;
    }
    cout<<"\nNo. of words in the file:"<<words;
    while (!fin.eof())
    {
        fin.get(ch);
        if (islower(ch))
            l_letters++;
        if (isupper(ch))
            u_letters++;
    }
    cout<<"\nNo. of Uppercase letters in the file:"<<u_letters;
    cout<<"\nNo. of Lowercase letters in the file:"<<l_letters;
    while(!fin.eof())
    {
        fin.get(ch);
        switch(ch)
        {
            case 'a':
            case 'A':
            case 'e':
            case 'E':
            case 'i':
            case 'I':
            case 'o':
            case 'O':
            case 'u':
            case 'U':vowels++;
                        break;
            default:break;
        }
    }
    cout<<"\nNo. of vowels in the file:"<<vowels;
    fin.close();
    return 0;
}



Enter text:Hello! My name is Anne.

No. of words in the file:5
No. of Uppercase letters in the file:0
No. of Lowercase letters in the file:0
No. of vowels in the file:0


Output isn't how it is supposed to be!!
Last edited on
while (!fin.eof())
You have this code many times. The first time you get to this code, your code fetches letters in a loop until the end of the file.

So the next time you have this code, will it loop? No. You are already at the end of the file.
Last edited on
Line 15, 21, 31: Do not loop on ! stream.eof(). This does not work the way you expect. The eof bit is set true only after you make a read attempt on the file. This means after you read the last record of the file, eof is still false. Your attempt to read past the last record sets eof, but you're not checking it there. You proceed as if you had read a good record. This will result in reading an extra (bad) record. The correct way to deal with this is to put the >> operation as the condition in the while statement.
1
2
3
  while (stream >> var) 
  {  //  Good operation
  }


Lines 21,31: As repeater mentioned, you're at eof when you reach these lines. Therefore eof() will be true. You need to rewind the file to the beginning.
1
2
  fin.clear ();  // Reset eof bit (if not C++11)
  fin.seekg (0);

http://www.cplusplus.com/reference/istream/istream/seekg/
Thanks!
Now, the input for uppercase and lowercase is correct. But vowels is still not correct.
Here's my new 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
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
#include <iostream>
using namespace std;
#include <fstream>
#include <cctype>
int main()
{
    int words=0, u_letters=0, l_letters=0, vowels=0;
    ofstream fout ("Text.txt",ios::out);
    char str[100], s[10], ch;
    cout<<"\nEnter text:";
    cin.getline(str, 100);
    fout<<str;
    fout.close();
    ifstream fin ("Text.txt",ios::in);
    while (!fin.eof())
    {
        fin.getline(s,10,' ');
        words++;
    }
    cout<<"\nNo. of words in the file:"<<words;
    fin.seekg(0);
    while (!fin.eof())
    {
        fin.get(ch);
        if (islower(ch))
            l_letters++;
        if (isupper(ch))
            u_letters++;
    }
    cout<<"\nNo. of Uppercase letters in the file:"<<u_letters;
    cout<<"\nNo. of Lowercase letters in the file:"<<l_letters;
    fin.seekg(0);
    while(fin)
    {
        fin.get(ch);
        switch(ch)
        {
            case 'a':
            case 'A':
            case 'e':
            case 'E':
            case 'i':
            case 'I':
            case 'o':
            case 'O':
            case 'u':
            case 'U':   vowels++;
                        break;
            default:    break;
        }
    }
    cout<<"\nNo. of vowels in the file:"<<vowels;
    fin.close();
    return 0;
}


And here's the output:
Enter text:Hello! My name is Anne.

No. of words in the file:5
No. of Uppercase letters in the file:3
No. of Lowercase letters in the file:14
No. of vowels in the file:0
You haven't included the fin.clear() advocated by AbstractionAnon.

Actually, your code would also fail on lowercase letters if your sample text ended with a letter, not the period as in your example.

I'm not convinced that using .eof is that safe as a measure for testing the end-of-file, as some operating systems seem to put a number of hidden characters at the ends of lines and files. Better and more efficient perhaps to test on reading from the stream itself, maybe, as below (vowels included with other letter tests):
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
#include <iostream>
#include <fstream>
#include <cctype>
using namespace std;

int main()
{
    int words=0, u_letters=0, l_letters=0, vowels=0;
    ofstream fout ("Text.txt",ios::out);
    char str[100], s[10], ch;
    cout<<"\nEnter text:";
    cin.getline(str, 100);
    fout<<str;
    fout.close();

    ifstream fin ("Text.txt",ios::in);
    while (fin.getline(s,10,' ')) words++;
    cout<<"\nNo. of words in the file:"<<words;

    fin.clear();
    fin.seekg(0);

    while (fin.get(ch))
    {
        if (islower(ch)) l_letters++;
        if (isupper(ch)) u_letters++;
        switch(ch)
        {
            case 'a':
            case 'A':
            case 'e':
            case 'E':
            case 'i':
            case 'I':
            case 'o':
            case 'O':
            case 'u':
            case 'U':   vowels++;
                        break;
            default:    break;
        }
    }
    fin.close();

    cout<<"\nNo. of Uppercase letters in the file:"<<u_letters;
    cout<<"\nNo. of Lowercase letters in the file:"<<l_letters;
    cout<<"\nNo. of vowels in the file:"<<vowels;

    return 0;
}


Your words are still restricted to a maximum length of 10 letters, and the code won't be correct if there is more than one space between them - see your other thread on this.

Could someone point out a better way of checking for vowels than this long switch block.
Last edited on
I see you ignored my advice regarding reading at EOF.
The following loop works correctly:
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 fin.clear();
    fin.seekg(0);
    while(fin >> ch)
    {   switch(ch)
        {
            case 'a':
            case 'A':
            case 'e':
            case 'E':
            case 'i':
            case 'I':
            case 'o':
            case 'O':
            case 'u':
            case 'U':   vowels++;
                        break;
            default:    break;
        }
    }

Enter text:Hello! My name is Anne.

No. of words in the file:5
No. of Uppercase letters in the file:3
No. of Lowercase letters in the file:14
No. of vowels in the file:7
Press any key to continue . . .

Vowel test, maybe:
1
2
        string v = "AEIOUaeiou";
        if (v.find( ch ) != string::npos ) vowels++;
Thanks everyone!
I was usinf .eof() because that's used a lot in my textbook. But honestly, I prefer this as it is much more easier to understand too. I asked my teacher and she said this is a better option and that I can do it this way. So, thanks all!!
Topic archived. No new replies allowed.