6 Replies - 217 Views - Last Post: 23 June 2013 - 11:35 AM Rate Topic: -----

#1 Hero26  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 03-May 13

Strings Program - Parameters problem

Posted 23 June 2013 - 06:41 AM

Hello and thank you for looking at my problem.
This is in C and running on Visual Studio.
It is a program which counts the number of consonants, vowels, words and punctuation marks in a user inputted sentence.
However the program is only ever printing out 0 or garbage. I must not used the pointers correctly but I wasn't getting any errors and since then I've got a little lost.
Please help point out how my parameters and pointers are wrong.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define WELCOME_MESSAGE "\n*** Welcome to the sentence counting program ***\n\n"
#define PI 3.142
#define POUND_SIGN 156
#define TRUE 1
#define FALSE 0
void ConvertSentenceToUpper(char Sentence[]);
void CountSentence(char Sentence[], int* Consonants, int* Vowels, int* Words, int* Punctuation);
void Display(char Sentence[], int* Consonants, int* Vowels, int* Words, int* Punctuation);
int GetValidatedInteger(int Min, int Max);
char* GetValidatedString(char Name[], int MinLength, int MaxLength);
void Pause();
int main()
{
	int* Consonants = 0,* Vowels = 0,* Words = 0,* Punctuation = 0;
	char Sentence[100];
	WELCOME_MESSAGE;
	printf("Enter a sentence:\n");
	GetValidatedString(Sentence, 1, 99);
	ConvertSentenceToUpper(Sentence);
	CountSentence(Sentence, Consonants, Vowels, Words, Punctuation);
	Display(Sentence, Consonants, Vowels, Words, Punctuation);
	Pause();
	return 0;
}

void ConvertSentenceToUpper(char Sentence[])
{
	int x = 0;
	for(x = 0; Sentence[x] != '\0'; x++)
		{
			Sentence[x] = toupper(Sentence[x]);
		}
}

void CountSentence(char Sentence[], int* Consonants, int* Vowels, int* Words, int* Punctuation)
{
	int i = 0;
	
	int sp = 0;
	char temp = 'a'; 

	while(Sentence[i] != '\0')
	{
		if(Sentence[i] > 64 && Sentence[i] < 91)
		{
			if(Sentence[i] == 'A' || Sentence[i] == 'E' || Sentence[i] == 'I' || Sentence[i] == 'O' || Sentence[i] == 'U')
			{
				Vowels++;
			}
			else
			{
				Consonants++;
			}
		}
		else
		{
			if(Sentence[i] == 32)
			{
				//sp++;
				//if(temp!=32)
				//{
					Words++;
				//}
			}
			else
			{
				if(Sentence[i] != (Sentence[i] > 47 && Sentence[i] < 58))			// Eliminating numbers from ASCII values so the only remaining value is a special character or punctuation.
				{
					Punctuation++;
				}
			}
		}
		//temp=Sentence[i];
		i++;
	}
}

void Display(char Sentence[], int* Consonants, int* Vowels, int* Words, int* Punctuation)
{
	printf("\nNumber of consonants: %d\nNumber of vowels: %d\nNumber of words: %d\nNumber of punctuation marks: %d", Consonants, Vowels, Words, Punctuation);
}

/* Gets user-inputted integer value. Validated for data type & value (Min->Max). */
int GetValidatedInteger(int Min, int Max)
{
	int ItemRead = FALSE;
	double Input = 0; /* NB Input read into a FLOAT */
	int Valid = FALSE; /* MUST be initialised to FALSE */

	do
	{
		/* Read. NB scanf() returns the number of items successfully read */
		ItemRead = scanf("%lf", &Input);
		fflush(stdin);

		/*Validate - Non-numeric? (In which case scanf() will not have read in anything)*/
		if(ItemRead == FALSE)
		{
			printf("Invalid - can only be a number (not a letter, a string or a symbol)");
		}
		/* Validate - Not whole number? */
		else if(Input != (int)Input) /* NB (int)Input truncates a float value */
		{
			printf("Invalid - must be whole number! Please try again (%d-%d): ", Min, Max);
		}
		/* Validate - Invalid value? (ie Not in range Min->Max) */
		else if((Input < Min) || (Input > Max))
		{
			printf("Invalid - out-of-range! Must be a number between %d & %d! Please try again: ", Min, Max);
		}
		else
		{
			Valid = TRUE;
		}
	} while(Valid == FALSE);

	return((int)Input); /* NB Cast (store) as int before returning */
}

/* Note: Validated, user-inputted array passed back twice:
			1. as reference parameter, and
			2. as a return value (Note “pointer” syntax "char*"). 
		Reason - To offer calling code maximum flexibility of use. */
char* GetValidatedString(char String[], int MinLength, int MaxLength)
{
	char Input[260]; /* Very big to avoid array over-run. */
	
	do
	{
		gets(Input);
		
		if((strlen(Input) < MinLength) || (strlen(Input) > MaxLength))
		{
			printf("Invalid! Please try again (Length %d-%d): ", MinLength, MaxLength);
		}
	} while((strlen(Input) < MinLength) || (strlen(Input) > MaxLength));
	
	/* Using string handling library function (strcpy()) */
	strcpy(String, Input); /* 1. Populate reference parameter */
	return(String); /* 2. Return value */
}

void Pause()
{
	printf("\n\nPress enter to exit.\n");
	getch();
}



Is This A Good Question/Topic? 0
  • +

Replies To: Strings Program - Parameters problem

#2 jimblumberg  Icon User is offline

  • member icon


Reputation: 3993
  • View blog
  • Posts: 12,323
  • Joined: 25-December 09

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 07:11 AM

Look at the following snippet:
	char Input[260]; /* Very big to avoid array over-run. */
	
	do
	{
		gets(Input);

Why don't you insure you won't have an array overrun by using fgets()? Never, NEVER use gets(), just using a "Very big" array size won't insure you won't get a buffer overrun. Always use a function that limits the number of characters you receive, like fgets(), to eliminate that possibility.

Next why all the "Magic Numbers"
		if(Sentence[i] > 64 && Sentence[i] < 91)

What does the 64 and 91 represent? Why not just use the character and the proper operators?
if(Sentence[i] >= 'A' && Sentence[i] <= 'Z')


Quote

However the program is only ever printing out 0 or garbage. I must not used the pointers correctly but I wasn't getting any errors and since then I've got a little lost.

In main you have this line:
	int* Consonants = 0,* Vowels = 0,* Words = 0,* Punctuation = 0;

This is wrong for a couple of reasons. First if you do use pointers here you must allocate memory for these pointers. But you don't really want pointers, you just want normal variables.
	int Consonants = 0, Vowels = 0, Words = 0, Punctuation = 0;

You then pass the address of these variables to your functions.

You may want to study the function tutorials contained in my signature for information on how to properly pass these variables to your functions.

Next look at this function:
void Display(char Sentence[], int* Consonants, int* Vowels, int* Words, int* Punctuation)

Why are you passing the variables by pointer? This function should not be changing these values so just pass by value.

Quote

I must not used the pointers correctly but I wasn't getting any errors and since then I've got a little lost.

When trying to learn a new feature of the language it is usually better to start simple. Create some simple functions where you pass a single value into the functions. Create one function to show the results of passing by value, another to help show the results of passing the value by pointer. Once you understand how to use these basic functions it'll be easier to use functions with more complexities.

Jim
Was This Post Helpful? 0
  • +
  • -

#3 Hero26  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 03-May 13

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 08:03 AM

In answer to your first point about gets(), I was given the GetValidatedString function to use for now. Thank you for pointing it out but I will deal with it after I have the program working because right now I want to focus on getting my head around Strings and Pointers.

I have addressed your next two points about initialising my variables not as pointers but just as variables, and sending the variables to Display by value instead of reference. However in the CountSentence function the integers don't seem to be working. Have I de-referenced them incorrectly? Please see what you think.
I am pretty sure that my string is being passed correctly throughout my program. Is that correct?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define WELCOME_MESSAGE "\n*** Welcome to the sentence counting program ***\n\n"
#define PI 3.142
#define POUND_SIGN 156
#define TRUE 1
#define FALSE 0
void ConvertSentenceToUpper(char Sentence[]);
void CountSentence(char Sentence[], int *Consonants, int *Vowels, int *Words, int *Punctuation);
void Display(int Consonants, int Vowels, int Words, int Punctuation);
int GetValidatedInteger(int Min, int Max);
char* GetValidatedString(char Name[], int MinLength, int MaxLength);
void Pause();
int main()
{
	int Consonants = 0, Vowels = 0, Words = 0, Punctuation = 0;
	char Sentence[100];
	WELCOME_MESSAGE;
	printf("Enter a sentence:\n");
	GetValidatedString(Sentence, 1, 99);
	ConvertSentenceToUpper(Sentence);
	CountSentence(Sentence, &Consonants, &Vowels, &Words, &Punctuation);
	Display(Consonants, Vowels, Words, Punctuation);
	Pause();
	return 0;
}

void ConvertSentenceToUpper(char Sentence[])
{
	int x = 0;
	for(x = 0; Sentence[x] != '\0'; x++)
		{
			Sentence[x] = toupper(Sentence[x]);
		}
}

void CountSentence(char Sentence[], int *Consonants, int *Vowels, int *Words, int *Punctuation)
{
	int i = 0;
	
	int sp = 0;
	char temp = 'a'; 

	while(Sentence[i] != '\0')
	{
		if(Sentence[i] > 64 && Sentence[i] < 91)
		{
			if(Sentence[i] == 'A' || Sentence[i] == 'E' || Sentence[i] == 'I' || Sentence[i] == 'O' || Sentence[i] == 'U')
			{
				Vowels++;
			}
			else
			{
				Consonants++;
			}
		}
		else
		{
			if(Sentence[i] == 32)
			{
				//sp++;
				//if(temp!=32)
				//{
					Words++;
				//}
			}
			else
			{
				if(Sentence[i] != (Sentence[i] > 47 && Sentence[i] < 58))			// Eliminating numbers from ASCII values so the only remaining value is a special character or punctuation.
				{
					Punctuation++;
				}
			}
		}
		//temp=Sentence[i];
		i++;
	}
}

void Display(int Consonants, int Vowels, int Words, int Punctuation)
{
	printf("\nNumber of consonants: %d\nNumber of vowels: %d\nNumber of words: %d\nNumber of punctuation marks: %d", Consonants, Vowels, Words, Punctuation);
}

/* Gets user-inputted integer value. Validated for data type & value (Min->Max). */
int GetValidatedInteger(int Min, int Max)
{
	int ItemRead = FALSE;
	double Input = 0; /* NB Input read into a FLOAT */
	int Valid = FALSE; /* MUST be initialised to FALSE */

	do
	{
		/* Read. NB scanf() returns the number of items successfully read */
		ItemRead = scanf("%lf", &Input);
		fflush(stdin);

		/*Validate - Non-numeric? (In which case scanf() will not have read in anything)*/
		if(ItemRead == FALSE)
		{
			printf("Invalid - can only be a number (not a letter, a string or a symbol)");
		}
		/* Validate - Not whole number? */
		else if(Input != (int)Input) /* NB (int)Input truncates a float value */
		{
			printf("Invalid - must be whole number! Please try again (%d-%d): ", Min, Max);
		}
		/* Validate - Invalid value? (ie Not in range Min->Max) */
		else if((Input < Min) || (Input > Max))
		{
			printf("Invalid - out-of-range! Must be a number between %d & %d! Please try again: ", Min, Max);
		}
		else
		{
			Valid = TRUE;
		}
	} while(Valid == FALSE);

	return((int)Input); /* NB Cast (store) as int before returning */
}

/* Note: Validated, user-inputted array passed back twice:
			1. as reference parameter, and
			2. as a return value (Note “pointer” syntax "char*"). 
		Reason - To offer calling code maximum flexibility of use. */
char* GetValidatedString(char String[], int MinLength, int MaxLength)
{
	char Input[260]; /* Very big to avoid array over-run. */
	
	do
	{
		gets(Input);
		
		if((strlen(Input) < MinLength) || (strlen(Input) > MaxLength))
		{
			printf("Invalid! Please try again (Length %d-%d): ", MinLength, MaxLength);
		}
	} while((strlen(Input) < MinLength) || (strlen(Input) > MaxLength));
	
	/* Using string handling library function (strcpy()) */
	strcpy(String, Input); /* 1. Populate reference parameter */
	return(String); /* 2. Return value */
}

void Pause()
{
	printf("\n\nPress enter to exit.\n");
	getch();
}


Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is offline

  • member icon


Reputation: 3993
  • View blog
  • Posts: 12,323
  • Joined: 25-December 09

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 08:51 AM

Quote

Have I de-referenced them incorrectly?

No, look at the following snippet.
oid CountSentence(char Sentence[], int *Consonants, int *Vowels, int *Words, int *Punctuation)
{
...
				Vowels++;


This is incrementing the pointer not the value is that what you want?

What about my other points about the "magic numbers"? If you use the characters instead of the numbers you'll find following your logic much easier.

Jim
Was This Post Helpful? 0
  • +
  • -

#5 Hero26  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 03-May 13

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 09:23 AM

Regarding the 'magic numbers'. I was using the ASCII values for characters etc. For example in the first 'if' statement I only had to put '(Sentence[i] > 64 && Sentence[i] < 91)' instead of a '||' or statement for every letter in the alphabet. Also I found it more precise for determining punctuation. Because I eliminated characters, digits and spaces, all that is left for the 'Punctuation' if statement is any kind of special character or punctuation. So they are all there instead of having to list ever special character with more '||' statements.

I believe I have the program working now. Is this what you had in mind for fixing the de-reference problem?

You have been very kind helping me through this, thank you very much.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define WELCOME_MESSAGE "\n*** Welcome to the sentence counting program ***\n\n"
#define PI 3.142
#define POUND_SIGN 156
#define TRUE 1
#define FALSE 0
void ConvertSentenceToUpper(char Sentence[]);
void CountSentence(char Sentence[], int *Consonants, int *Vowels, int *Words, int *Punctuation);
void Display(int Consonants, int Vowels, int Words, int Punctuation);
int GetValidatedInteger(int Min, int Max);
char* GetValidatedString(char Name[], int MinLength, int MaxLength);
void Pause();
int main()
{
	int Consonants = 0, Vowels = 0, Words = 1, Punctuation = 0;
	char Sentence[100];
	WELCOME_MESSAGE;
	printf("Enter a sentence:\n");
	GetValidatedString(Sentence, 1, 99);
	ConvertSentenceToUpper(Sentence);
	CountSentence(Sentence, &Consonants, &Vowels, &Words, &Punctuation);
	Display(Consonants, Vowels, Words, Punctuation);
	Pause();
	return 0;
}

void ConvertSentenceToUpper(char Sentence[])
{
	int x = 0;
	for(x = 0; Sentence[x] != '\0'; x++)
		{
			Sentence[x] = toupper(Sentence[x]);
		}
}

void CountSentence(char Sentence[], int *Consonants, int *Vowels, int *Words, int *Punctuation)
{
	int i = 0;
	char temp = 'a'; 
	while(Sentence[i] != '\0')
	{
		if(Sentence[i] > 64 && Sentence[i] < 91)			//ASCII values saves putting an '||' or statement for every letter
		{
			if(Sentence[i] == 'A' || Sentence[i] == 'E' || Sentence[i] == 'I' || Sentence[i] == 'O' || Sentence[i] == 'U')
			{
				*Vowels = *Vowels + 1;
			}
			else
			{
				*Consonants = *Consonants + 1;
			}
		}
		else
		{
			if(Sentence[i] == 32)
			{
				if(temp!=32)
				{
					*Words = *Words + 1;
				}
			}
			else
			{
				if(Sentence[i] < 48 || Sentence[i] > 57)			// Eliminating numbers from ASCII values so the only remaining value is a special character or punctuation.
				{
					*Punctuation = *Punctuation + 1;
				}
			}
		}
		temp = Sentence[i];
		i++;
	}
}

void Display(int Consonants, int Vowels, int Words, int Punctuation)
{
	printf("\nNumber of consonants: %d\nNumber of vowels: %d\nNumber of words: %d\nNumber of punctuation marks: %d", Consonants, Vowels, Words, Punctuation);
}

/* Gets user-inputted integer value. Validated for data type & value (Min->Max). */
int GetValidatedInteger(int Min, int Max)
{
	int ItemRead = FALSE;
	double Input = 0; /* NB Input read into a FLOAT */
	int Valid = FALSE; /* MUST be initialised to FALSE */

	do
	{
		/* Read. NB scanf() returns the number of items successfully read */
		ItemRead = scanf("%lf", &Input);
		fflush(stdin);

		/*Validate - Non-numeric? (In which case scanf() will not have read in anything)*/
		if(ItemRead == FALSE)
		{
			printf("Invalid - can only be a number (not a letter, a string or a symbol)");
		}
		/* Validate - Not whole number? */
		else if(Input != (int)Input) /* NB (int)Input truncates a float value */
		{
			printf("Invalid - must be whole number! Please try again (%d-%d): ", Min, Max);
		}
		/* Validate - Invalid value? (ie Not in range Min->Max) */
		else if((Input < Min) || (Input > Max))
		{
			printf("Invalid - out-of-range! Must be a number between %d & %d! Please try again: ", Min, Max);
		}
		else
		{
			Valid = TRUE;
		}
	} while(Valid == FALSE);

	return((int)Input); /* NB Cast (store) as int before returning */
}

/* Note: Validated, user-inputted array passed back twice:
			1. as reference parameter, and
			2. as a return value (Note “pointer” syntax "char*"). 
		Reason - To offer calling code maximum flexibility of use. */
char* GetValidatedString(char String[], int MinLength, int MaxLength)
{
	char Input[260]; /* Very big to avoid array over-run. */
	
	do
	{
		gets(Input);
		
		if((strlen(Input) < MinLength) || (strlen(Input) > MaxLength))
		{
			printf("Invalid! Please try again (Length %d-%d): ", MinLength, MaxLength);
		}
	} while((strlen(Input) < MinLength) || (strlen(Input) > MaxLength));
	
	/* Using string handling library function (strcpy()) */
	strcpy(String, Input); /* 1. Populate reference parameter */
	return(String); /* 2. Return value */
}

void Pause()
{
	printf("\n\nPress enter to exit.\n");
	getch();
}


Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is offline

  • member icon


Reputation: 3993
  • View blog
  • Posts: 12,323
  • Joined: 25-December 09

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 09:55 AM

Quote

Regarding the 'magic numbers'. I was using the ASCII values for characters etc

Why use the numbers? Using the characters instead will make you program easier to read because you won't need to translate the numbers into the characters. We humans usually deal better with the character 'A' than the number 65.

You also still need to get rid of that gets(). That function is so dangerous that it has been removed from the current C standard.

Also the fflush() function is not defined to work with input streams. Using it on input streams produces undefined behavior.

Also the following two lines are equivalent.
*Words = *Words + 1;
(*Words)++;


Jim
Was This Post Helpful? 0
  • +
  • -

#7 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3485
  • View blog
  • Posts: 10,742
  • Joined: 05-May 12

Re: Strings Program - Parameters problem

Posted 23 June 2013 - 11:35 AM

To reinforce jimblumberg's point about magic numbers... if you claim that 65 and 91 are just as readable, then it should also make sense that the following are also equally as readable:
if(Sentence[i] > 0x41 && Sentence[i] < 0x5B)


Or
if(Sentence[i] > 0101 && Sentence[i] < 0133)


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1