I'm confused with pointers. I'm not sure how to get the vowels to show up in Case A.

Also, I would need help by how to get the program to run again after case A instead of ending the program after each case. Should it be in if/else statement instead of switch? Or use while loop with switch statement?

Thanks and I appreciate any hints/help! :)

#include <fstream>
#include <iostream>

using namespace std;

char* getStringFromUser();
int consonants(char* str);  //function to print out consonants
int vowels(char* str);  //function to print out vowels
void stringCopy(char* str1, char* str2);

int main ()
{
	//declare variables to use for storing user's input
	char choice; //first menu
	char line;
	
	//declare variables to use for program
	bool goagain = true;
	int getNumStrings();
	fstream dataFile; //input stream for file	
     
	// introduction to the program 
	cout << "\n\n------------------------------------------------" << endl;
	cout << "\n\nVowels & Consonants" << endl;
	
		dataFile.open("stringFile.txt", ios::out | ios::app); //open file
		if (! dataFile) // test for error
			cout << "Error opening file.\n";	
	
		cout << "\n\nPlease select from the following menu items:\n";
		cout << "\t A)  Count the vowels of a string.\n";
		cout << "\t B)  Count the consonants of a string.\n";
		cout << "\t C)  Count both vowels and consonants of a string.\n";
		cout << "\t D)  Enter a string in the file.\n";
		cout << "\t E)  Count the number of strings in the file.\n";
		cout << "\t F)  Exit this program.\n\n";
		cout << "\t Enter A, B, C, D, E, or F: ";
		cin >> choice; //user choice of menu
		
		switch(choice)
		{
			case 'A':	cout << getStringFromUser();
//						cout << vowels(line, vowels);
						break;
					  
			case 'B': 	cout << "choice B";	  
						break;
						
			case 'C':	cout << "choice C"; 
						break;
			
			case 'D':	cout << "choice D"; 
						break;
			
			case 'E':	cout << "choice E";
						break;
			
			case 'F': 	cout << "\n\nGoodbye!" << endl;		
						break;
			
			default: cout << "That is an invalid choice.\n";
		}	
		
		dataFile.close(); //close text file	

	return 0;
}//end of function

char* getStringFromUser()
{
	char line[100];
	
	cout << "Enter a string: ";
	cin.ignore();
	cin.getline(line, 100, '\n');
}			

int vowels(char* str)
{
	char vowelsArray[] = {'A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u', '\0'};
	char *vowelsPtr = vowelsArray;
	int numVowels = 0;
	int count;
	
	cout << "The vowels in the string are: ";

	while(*str != '\0')
	{
		for(count = 0; count <10; count++)
		{
			if (*str == *vowelsPtr)
			{
				numVowels++; //Point to next element
				cout << "The vowels in the string are: " << *vowelsPtr << endl;
				break;
			}
		}		
		str++;
		vowelsPtr = vowelsArray; //set vowelsPtr to first element again
	}
	cout << "\n\n";
	return numVowels;
}

>I'm not sure how to get the vowels to show up in Case A.
The problem isn't the pointer, it's the fact that you're returning a pointer to a local array. When the function returns, the memory for that array is reclaimed. In other words, it's not yours anymore. There are a few ways to do what you want, but I'd recommend one of the following:

1) Use a std::string instead of an array. std::strings have copy semantics, and you don't need to worry about pointers:

#include <iostream>
#include <string>

std::string get_string_from_user()
{
  std::string line;

  std::cout<<"Enter a string: ";
  std::getline(std::cin, line);

  return line;
}

int main()
{
  std::cout<< get_string_from_user() <<'\n';
}

2) If you can't use std::string, or don't want to for some reason, pass an array into the function as an argument. That way you don't have to worry about returning it, but you can return a pointer to it safely:

#include <cstddef>
#include <iostream>

char *get_string_from_user(char *line, std::size_t size)
{
  std::cout<<"Enter a string: ";
  std::cin.getline(line, size);

  return line;
}

int main()
{
  char line[1024];

  std::cout<< get_string_from_user(line, sizeof line) <<'\n';
}

The latter option is harder to get right and requires more diligence on your part.

>how to get the program to run again after case A
>instead of ending the program after each case.

Wrap the whole thing in a loop, and only break from the loop when you reach the exit case.

I'm confused with pointers.

pointer-type variables hold memory addresses.. just like int's hold integers, char's hold ascii values etc.

I'm not sure how to get the vowels to show up in Case A

Although I do not agree with your current scheme of prompting for user input after a menu selection is made (I think it should be done before being that all your menu options are based on the same user input), here is one way to "get the vowels to show up"...

void getStringFromUser()
{	
     char line[100]; 	
     cout << "Enter a string: ";		
     cin.getline(line, 100, '\n');
     cin.ignore();

     for(int i=0, i<strlen(line), i++)
     {
          switch(toupper(line[i]))
          {
               case 'A':
               case 'E':
               case 'I':
               case 'O':
               case 'U':  vowel_counter++;
         }
     }
}

Also, I would need help by how to get the program to run again after case A instead of ending the program after each case.

Although this may seem rather complex, I'll break it down for you as best as I can:

char ans = '\0';

//Add this at line #29
do{

//Add this at line #63
cout << "Do you wish to make another menu selection?  (Y/N) ";
cin >> ans;
}while(toupper(ans) == 'Y');

Should it be in if/else statement instead of switch?

No. Menu options should be handled using switch structure.

Or use while loop with switch statement?

Yes, and this is what I've done for you.

The code I have given you is untested and my contain small easy to fix errors. If anyone has a better suggestion please let me know as there are many ways to accomplish a given task.

Edited 7 Years Ago by Clinton Portis: under diress of a code ninja.

>pointer-type variables hold memory addresses..
>just like int's hold integers, char's hold ascii values etc.

Yay! Finally people are starting to get it.

>here is one way to "get the vowels to show up"...
Yes yes, give him code that's broken and encourages poor programming practices. Brilliant!

>for(int i=0, i<strlen(line), i++)
Barring the dyslexic use of commas instead of semicolons, it's important that you understand the cost of the functions you call. In the case of strlen, it loops over the string every. single. time. Not a good idea for a loop condition because your O(n) loop over the length of the string suddenly jumps to O(n*n). Even worse, the whole issue is easily avoided:

size_t len = strlen ( line );

for ( int i = 0; i < len; i++ )

>Menu's should be done using switch structure.
...

Hey kyrz!
If you can post your complete code in here or email it to me at <<removed e-mail>>, then I can look at the program and help you.

Thank You

I'm confused with pointers. I'm not sure how to get the vowels to show up in Case A.

Also, I would need help by how to get the program to run again after case A instead of ending the program after each case. Should it be in if/else statement instead of switch? Or use while loop with switch statement?

Thanks and I appreciate any hints/help! :)

#include <fstream>
#include <iostream>

using namespace std;

char* getStringFromUser();
int consonants(char* str);  //function to print out consonants
int vowels(char* str);  //function to print out vowels
void stringCopy(char* str1, char* str2);

int main ()
{
	//declare variables to use for storing user's input
	char choice; //first menu
	char line;
	
	//declare variables to use for program
	bool goagain = true;
	int getNumStrings();
	fstream dataFile; //input stream for file	
     
	// introduction to the program 
	cout << "\n\n------------------------------------------------" << endl;
	cout << "\n\nVowels & Consonants" << endl;
	
		dataFile.open("stringFile.txt", ios::out | ios::app); //open file
		if (! dataFile) // test for error
			cout << "Error opening file.\n";	
	
		cout << "\n\nPlease select from the following menu items:\n";
		cout << "\t A)  Count the vowels of a string.\n";
		cout << "\t B)  Count the consonants of a string.\n";
		cout << "\t C)  Count both vowels and consonants of a string.\n";
		cout << "\t D)  Enter a string in the file.\n";
		cout << "\t E)  Count the number of strings in the file.\n";
		cout << "\t F)  Exit this program.\n\n";
		cout << "\t Enter A, B, C, D, E, or F: ";
		cin >> choice; //user choice of menu
		
		switch(choice)
		{
			case 'A':	cout << getStringFromUser();
//						cout << vowels(line, vowels);
						break;
					  
			case 'B': 	cout << "choice B";	  
						break;
						
			case 'C':	cout << "choice C"; 
						break;
			
			case 'D':	cout << "choice D"; 
						break;
			
			case 'E':	cout << "choice E";
						break;
			
			case 'F': 	cout << "\n\nGoodbye!" << endl;		
						break;
			
			default: cout << "That is an invalid choice.\n";
		}	
		
		dataFile.close(); //close text file	

	return 0;
}//end of function

char* getStringFromUser()
{
	char line[100];
	
	cout << "Enter a string: ";
	cin.ignore();
	cin.getline(line, 100, '\n');
}			

int vowels(char* str)
{
	char vowelsArray[] = {'A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u', '\0'};
	char *vowelsPtr = vowelsArray;
	int numVowels = 0;
	int count;
	
	cout << "The vowels in the string are: ";

	while(*str != '\0')
	{
		for(count = 0; count <10; count++)
		{
			if (*str == *vowelsPtr)
			{
				numVowels++; //Point to next element
				cout << "The vowels in the string are: " << *vowelsPtr << endl;
				break;
			}
		}		
		str++;
		vowelsPtr = vowelsArray; //set vowelsPtr to first element again
	}
	cout << "\n\n";
	return numVowels;
}

Edited 7 Years Ago by Nick Evan: removed e-mail

Thanks for trying to help. My function just based on the teacher's methods for the vowels function. Anyhow, I'm even more confused about how to call the vowels function. Thought it'll be numVowels = vowels(); but I keep getting error like "too few arguments" or invalid conversion from int to *int. No clue here...

#include <fstream>
#include <iostream>

using namespace std;

char* getStringFromUser();
int consonants(char* str);  //function to print out consonants
int vowels(char* str);  //function to print out vowels
int getNumStrings();
void stringCopy(char* str1, char* str2);

int main ()
{
	//declare variables to use for storing user's input
	char choice; //first menu
	char line[100];
	char* cPtr;
	int *numVowels;
	
	//declare variables to use for program
	fstream dataFile; //input stream for file	
     
	// introduction to the program 
	cout << "\n\n------------------------------------------------" << endl;
	cout << "\n\nVowels & Consonants" << endl;
	
		cout << "\n\nPlease select from the following menu items:\n";
		cout << "\t A)  Count the vowels of a string.\n";
		cout << "\t B)  Count the consonants of a string.\n";
		cout << "\t C)  Count both vowels and consonants of a string.\n";
		cout << "\t D)  Enter a string in the file.\n";
		cout << "\t E)  Count the number of strings in the file.\n";
		cout << "\t F)  Exit this program.\n\n";
		cout << "\t Enter A, B, C, D, E, or F: ";
		cin >> choice; //user choice of menu
		
		switch(choice)
		{
			case 'A':	cPtr = getStringFromUser();
						// numVowels = vowels(); //<--- how to call the vowels function?
						break;
					  
			case 'B': 	cout << "choice B";	  
						break;
						
			case 'C':	cout << "choice C"; 
						break;
			
			case 'D':	
						dataFile.open("stringFile.txt", ios::out | ios::app); //open file
						if (! dataFile) // test for error
							cout << "Error opening file.\n";	
			
						cout << "choice D";
						
						dataFile.close(); //close text file	
						break;
			
			case 'E':	cout << "choice E";
						break;
			
			case 'F': 	cout << "\n\nGoodbye!" << endl;		
						break;
			
			default: cout << "That is an invalid choice.\n";
		}	
		


	return 0;
}//end of function

char* getStringFromUser()
{
	char line[100];
	char * cPtr;
	int length;

	cout << "Enter a string: ";
	cin.ignore();
	cin.getline(line, 100, '\n');
	
	length = strlen(line) + 1;
	cPtr = new char[length];
	stringCopy(line, cPtr);

	return cPtr;
}			

int vowels(char* str)
{
	char vowelsArray[] = {'A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u', '\0'};
	char *vowelsPtr = vowelsArray;
	int numVowels = 0;
	int count;
	
	cout << "The vowels in the string are: ";

	while(*str != '\0')
	{
		for(count = 0; count <10; count++)
		{
			if (*str == *vowelsPtr)
			{
				numVowels++; //Point to next element
				cout << "The vowels in the string are: " << *vowelsPtr << endl;
				break;
			}
		}		
		str++;
		vowelsPtr = vowelsArray; //set vowelsPtr to first element again
	}
	cout << "\n\n";
	return numVowels;
}

int consonants(char* str)
{
	char vowelsArray[] = {'A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u', '\0'};
	char *vowelsPtr = vowelsArray;
	int numConsonants = 0;
	int count;
	
	cout << "The vowels in the string are: ";

	while(*str != '\0')
	{
		for(count = 0; count <10; count++)
		{
			if (!*str == *vowelsPtr)
			{
				numConsonants++; //Point to next element
				cout << "The vowels in the string are: " << *vowelsPtr << endl;
				break;
			}
		}		
		str++;
		vowelsPtr = vowelsArray; //set vowelsPtr to first element again
	}
	cout << "\n\n";
	return numConsonants;
}

int getNumStrings()
{
	char* cPtr;
	char str[100];
	
	cPtr = str;
	cout << "Give String: ";
	cin.getline(cPtr, 50, '\n');
	cout << cPtr << endl;	
}

void stringCopy(char *str1, char *str2)
{
	int index = 0;
	
	while(*str1 != '\0')
	{
		*str2 = *str1;
		index++;
	}
	
	*str2 = '\0';
}

Edited 7 Years Ago by kryz: n/a

Try the following:

case 'A':	 cPtr = getStringFromUser();
          numVowels = vowels(cPtr);
          break;

Edited 7 Years Ago by Clinton Portis: a, e, i, o, you!

Try the following:

case 'A':	 cPtr = getStringFromUser();
          numVowels = vowels(cPtr);
          break;

Tried that actually... got that error: invalid conversion from 'int' to 'int*'

In that case, you either have to do this:

//line #18
int numVowels;

Or this:

//line #114
return &numVowels;

But not both, just do one or the other.

This article has been dead for over six months. Start a new discussion instead.