C++ Counting vowels problem

Hello everyone.

I seem to be having a problem with my coding. I need to write a program that reads a text file and counts the number of vowels, and lists them like the following:
A=4,E=2,I=4,O=2,U=2
My problem is that it is giving me the wrong amount of vowels per letter, here is my coding:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>

using namespace std;
int main()
{
	
	
	int a=0,e=0,i=0,o=0,u=0;
	char str[3000];
	int v=0;
   //Read from the text file
        fstream file_op("c:\\proj3cpp.txt",ios::in);
        while(!file_op.eof())
        {
              file_op.getline(str,3000);
              cout <<str;
        }         file_op.close();
        cout <<endl;
	while(str[v] != '\0')
	
	{

	  switch (str[v])

	  {
      //Lowercase vowels
	  case 'a':
	  a=a+1;
	  break;

	  case 'e':
	  e=e+1;
	  break;	 
	  
	  case 'i':
	  i=i+1;
	  break;

	  case 'o':
	  o=o+1;
	  break;

	  case 'u':
	  u=u+1;
	  break;

      
	  //Capital vowels
	  case 'A':
        a=a+1;
	  break;

	  case 'E':
	  e=e+1;
	  break;	  
	  
	  case 'I':
	  i=i+1;
	  break;

	  case 'O':
	  o=o+1;
	  break;

	  case 'U':
	  u=u+1;
	  break;
	  }
	   v++;
	  }
   
	//Results
	cout <<"A= " <<a<<endl;
	cout <<"E= " <<e<<endl;
	cout <<"I= " <<i<<endl;
	cout <<"O= " <<o<<endl;
	cout <<"U= " <<u<<endl;

	return 0;
}

This is the file I am trying to count vowels for:

Two of the most important things in your LIFE right
now are your HEALTH and yor EDUCATION. Your EDUCATION
will provide you the better things in life providing
of course you are HEALTHY enough to ENJOY them. So
study hard, take care of your self, and always THINK.

I get the following:
A=6
E=3
I=1
O=2
U=2

Thanks in advanced!
Last edited on
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
#include <windows.h>
#include <stdio.h>

int __cdecl main(__in int argc, __in_ecount_z(argc) char* argv[], __in_z char* envp[])
{
	UNREFERENCED_PARAMETER(argc);
	UNREFERENCED_PARAMETER(argv);
	UNREFERENCED_PARAMETER(envp);

	FILE*		pFile;
	DWORD		dwSize = 0;
	LPSTR		lpszBuffer;
	UINT		A = 0, E = 0, I = 0, O = 0, U = 0;

	if(!(pFile = fopen("file.txt" , "r")))
	{
		printf("epic fail opening file");
		return EXIT_FAILURE;
	}
	
	fseek(pFile , 0 , SEEK_END);
	dwSize = ftell(pFile);
	rewind(pFile);

	lpszBuffer = new char[1000];
	if(fread(lptszBuffer, 1, dwSize, pFile) != dwSize)
	{
		printf("epic fail reading file");
		fclose(pFile);
		delete lpszBuffer;
		return EXIT_FAILURE;
	}
	fclose(pFile);
	delete lpszBuffer;

	for(UINT i = 0; i < strlen(lpszBuffer); i++)
	{
		if(toupper(lpszBuffer[i]) == 'A')
			A++;
		else if(toupper(lpszBuffer[i]) == 'E')
			E++;
		else if(toupper(lpszBuffer[i]) == 'I')
			I++;
		else if(toupper(lpszBuffer[i]) == 'O')
			O++;
		else if(toupper(lpszBuffer[i]) == 'U')
			U++;
	}

	printf("A = %i, E = %i, I = %i, O = %i, U = %i", A, E, I, O, U);
	return EXIT_SUCCESS;
}
Last edited on
I was hoping to receive help from my own coding :X, thanks for the reply Kiana
Last edited on
Yes, people need to fix their own problems...

ViperVenom
But as it goes, your program needs to reset v to zero after every count.
Also, the vowel counting for each line needs to be in the loop.
Finally, don't test against EOF. Test against the 'goodness' of the file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        fstream file_op("c:\\proj3cpp.txt",ios::in);

        // while there are lines to be read
        while (file_op.getline( str, 3000 ).good())
        {
                // for each character in the string
                for (v = 0; str[ v ] != '\0'; v++)
                {
                        // update your counts here
                        ...
                }
        }

        // Only close the file when done using it
        file_op.close();

Line 4 needs some expanation:

The ifstream::getline() method only reads to the end of each line, not the entire file.

The method also returns the stream... so you can use it in a test condition (like an if statement or loop of some kind).
So we test it against the good() attribute. It is shorthand for this:
1
2
3
4
5
6
7
        file_op.getline( ... );
        while (file_op.good())
        {
                ...

                file_op.getline( ... );
        }
The nice thing about the 'shorthand' is that it combines lines 1 and 6 here into a single line -- meaning less chance for errors (do one thing once).

Finally, the good() part can be omitted to get the same result:
1
2
        while (file_op.getline( ... ))
        {
In this case, good() is presumed, and the result is the same.

As Kiana indicated, you can use toupper() to help a bit... but you must #include <cctype> to use it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cctype>

...


        switch (toupper( str[ v ] ))
        {
                case 'A':
                        a += 1;
                        break;

                case 'E':
                        ...

                ...
        }


Finally, be careful with your indentation. I find that it helps to always write the { and } braces immediately after writing the while, if, function header, etc. This helps things to be properly lined-up and properly terminated.

if (fooey)_ if (fooey) if (fooey) if (fooey) if (fooey)
{_ { {_ {
}_ } cout << "fooey!\n";_
}


Hope this helps.
Thank you so much for your reply and the tip on indentation Duoas.
I've done the first set of code that you put. Now it doesn't show any of the text, like if it's not reading from the file. Did I do something wrong?
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;
int main()
{
	int a=0,e=0,i=0,o=0,u=0;
	char str[3000];
	int v=0;
  
	   //Read from the text file
        fstream file_op("c:\\proj3cpp.txt",ios::in);
        while (file_op.getline(str,3000).good())
        {
	       for (v = 0; str[ v ] != '\0'; v++)
			{

              file_op.getline(str, 3000);
              
			}
        }         
		file_op.close();
        cout <<endl;
	while(str[v] != '\0')
	
	{
      
	  switch (toupper( str[ v ] ))

	  {
      //Lowercase vowels
	  case 'a':
	  a+=1;
	  break;

	  case 'e':
	  e+=1;
	  break;	 
	  
	  case 'i':
	  i+=1;
	  break;

	  case 'o':
	  o+=1;
	  break;

	  case 'u':
	  u+=1;
	  break;

      
	  //Capital vowels
	  case 'A':
          a+=1;
	  break;

	  case 'E':
	  e+=1;
	  break;	  
	  
	  case 'I':
	  i+=1;
	  break;

	  case 'O':
	  o+=1;
	  break;

	  case 'U':
	  u+=1;
	  break;
	  }
	}
   
	//Results
	cout <<"A= " <<a<<endl;
	cout <<"E= " <<e<<endl;
	cout <<"I= " <<i<<endl;
	cout <<"O= " <<o<<endl;
	cout <<"U= " <<u<<endl;

	return 0;
}

Last edited on
Multiple logical probems:
-You are overwriting 'str' variable every time you read a line. If you read the whole file into the memory, you should use an array of strings. (I recomend : std::vector < std::string > ). Or you can chose the more memory-friendly approach and read the file char by char, and the do the appropriate calculations.
-Varible 'v' value at the line while(str[v] != '\0'), is the number of lines you had in your input file. You either have to use a new variable, or reset it back to 0.

Also if I remember correctly 'str' should have 3001 elements as you are reading 3000 chars, plus you have to have space for the closing '\0' character. But that's only going to be a problem if you have longer lines than 3000 chars. But if you use std::string, that problem completely disappears.

Hope this helps!
Last edited on
I've gotten the program to work well, it counts perfect. The only problem I'm having is that it was grouping the first word of a line with the last word of the previous line, example:

Two of the most important things in your LIFE
rightnow are your HEALTH and yor EDUCATION. Your
EDUCATIONwill provide you the better things in life
providingof course you are HEALTHY enough to ENJOY them.
Sostudy hard, take care of your self, and always THINK.

I've fixed this by adding a cout<<" ";
But my program is not reading the last line on the text file, what seems to be the problem?

Coding:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Project3(6).cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;
int main()
{
	int a=0,e=0,i=0,o=0,u=0;
	char str[3001];
	int v=0;

	   //Read from the text file
        fstream file_op("c:\\proj3cpp.txt",ios::in);
        while (file_op.getline(str,3001).good())
        {
	       for (v = 0; str[ v ] != '\0'; v++)
			{

              
              	  switch (toupper( str[ v ] ))

	                     {
                          //Lowercase vowels
	                          case 'A':
	                          a+=1;
	                          break;

	                          case 'E':
	                          e+=1;
	                          break;	 
	  
	                          case 'I':
	                          i+=1;
	                          break;

	                          case 'O':
	                          o+=1;
	                          break;

	                          case 'U':
	                          u+=1;
	                          break;
							  
							
				        }
		   }
		cout<<" ";
		cout<<str;
		
		}         
		file_op.close();
        cout <<endl;



   
	//Results
	cout <<"A= " <<a<<endl;
	cout <<"E= " <<e<<endl;
	cout <<"I= " <<i<<endl;
	cout <<"O= " <<o<<endl;
	cout <<"U= " <<u<<endl;

	return 0;
}
Last edited on
ViperVenom
Good job.

The reason for the joined outputs is that getline() does not store the newline delimiter in the string. (You would have to use get() for that.) However, you can fix it by outputting the newline yourself.

Get rid of line 52 and replace line 53 with just:
53 cout<<str<<endl;

Also, don't forget to fix the comment on line 28.

Hope this helps.


R0mai, before posting, please be careful that you say only true things, and that you attend to the way things work before suggesting something completely different.

-You are overwriting 'str' variable every time you read a line.

Yes, that is the natural result of reading the file one line at a time with getline().

If you read the whole file into the memory, you should use an array of strings.

Why tell him to read the whole file into memory when he doesn't need to. More than that, why recommend he mess with a vector of things when he still has to deal with each individual line? All that does is add complexity without helping to solve the problem -- which is still dealing with each line one at a time.

Or you can chose the more memory-friendly approach and read the file char by char, and the do the appropriate calculations.

What? Again, what's wrong with the line-by-line approach he's got?

-Varible 'v' value at the line while(str[v] != '\0'), is the number of lines you had in your input file.

It most certainly is not.

In his first post, he never modified it from zero.
In his second post, v represents the length of the last line in the file.

Pay attention: v counts through the characters in each line.

You either have to use a new variable, or reset it back to 0.

Hmm, something like I suggested about 17 hours before?

Also if I remember correctly 'str' should have 3001 elements as you are reading 3000 chars, plus you have to have space for the closing '\0' character.

You remember incorrectly. I've done that too... so now I make it a rule to check the documentation before I open my mouth
http://www.cplusplus.com/reference/iostream/istream/getline/
Characters are extracted until either (n - 1) characters have been extracted or the delimiting character is found
Specifying 3000 was correct.

Sorry to be so harsh... (I have had to learn from the same harsh treatment...) Hope this helps.
Duoas, thank you so much for your help with my coding.

Ive added cout << str << " "; before the while loop ends and after the while loop ends, now it displays all of the lines


However, Ive taken a second look at my output again and I still have a problem calculating the vowels correctly. I get A=8,E=17,I=14,O=21,U=9 instead of A=13,E=19,I=14,O=22,U=11

"I" seems to be the only one correct, and it is the same coding as all the others.


I also have another question, how can i make it appear exactly like the text appears in the text file, The output i get continues to the end of the window then the next line appears, in stead of:

Two of the most important things in your LIFE right
now are your HEALTH and yor EDUCATION. Your EDUCATION
will provide you the better things in life providing
of course you are HEALTHY enough to ENJOY them. So
study hard, take care of your self, and always THINK.

I get


Two of the most important things in your LIFE rightnow are your HEALTH and yor EDUCATION. Your EDUCATION will provide you the better things in life providing of course you are HEALTHY enough to ENJOY them. So study hard, take care of your self, and always THINK.


Last edited on
The text:
Two of the most important things in your LIFE right
now are your HEALTH and yor EDUCATION. Your EDUCATION
will provide you the better things in life providing
of course you are HEALTHY enough to ENJOY them. So
study hard, take care of your self, and always THINK.

contains the following vowels:

A : 14
E : 20
I : 15
O : 23
U : 11
83 vowels total

This is exactly what your program is reporting to me:

Two of the most important things in your LIFE right now are your HEALTH and yor
EDUCATION. Your EDUCATION will provide you the better things in life providing
of course you are HEALTHY enough to ENJOY them. So study hard, take care of your
self, and always THINK.
A= 14
E= 20
I= 15
O= 23
U= 11



If "your" was not misspelled as "yor" then you would see the reason why your output doesn't match the source (and there would be 12 'U's).
Make sure to use either: cout << str << endl;
or cout << str << "\n";

Hope this helps.
Thank you for all of your help Duoas,

I've got my program to work perfectly, thank you for all of your time. I've learned a lot from your posts.
Topic archived. No new replies allowed.