Code counts consonants incorrectly. How to solve this? - c

I have to write a program that selects consonants from a string and counts them, and shows how many times each of them appeared.
I wrote this code, but it also counts vowels. I don't know why.
#include <stdio.h>
int main()
{
char str[100];
int i, consonants;
i = consonants = 0;
int freq[256] = {0};
printf("\n Please Enter any String : ");
scanf("%[^\n]", str);
while (str[i] != '\0')
{
if ((str[i] >= 'a' && str[i] <= 'z') ||
(str[i] >= 'A' && str[i] <= 'Z') &&
(str[i] != 'a' || str[i] != 'A' ||
str[i] != 'e' || str[i] != 'E' ||
str[i] != 'i' || str[i] != 'I' ||
str[i] != 'o' || str[i] != 'O' ||
str[i] != 'u' || str[i] != 'U'))
{
consonants++;
freq[str[i]]++;
}
i++;
}
printf("\n Number of Consonants in this String = %d", consonants);
for (i = 0; i < 256; i++)
{
if (freq[i] != 0)
{
printf("\nThe frequency of %c is %d", i, freq[i]);
}
}
return 0;
}
This is output:
Please Enter any String : We strive to achive peace
Number of Consonants in this String = 21
The frequency of W is 1
The frequency of a is 2
The frequency of c is 2
The frequency of e is 5
The frequency of h is 1
The frequency of i is 2
The frequency of o is 1
The frequency of p is 1
The frequency of r is 1
The frequency of s is 1
The frequency of t is 2
The frequency of v is 2

I just wanted to let you know that you can get rid of the huge if condition by using the standard functions isalpha(), defined in ctype.h, and strchr(), defined in strng.h.
You can change the whole condition to just
if( isConsonant(str[i]) )
With isConsonant() defined as follows
int isConsonant( char c )
{
static char vowels[] = "aeiouAEIOU";
if( ialpha(c) && strchr(vowels, c) == NULL ) {
return 1;
}
else {
return 0;
}
}

This part of your condition (which because of the rest of the logic influences the whole outcome) will always be true:
str[i] != 'a' || str[i] != 'A'
That is why all letters are counted as consonants.
You want the negation of "is a vowel".
!(str[i] == 'a' ||
str[i] == 'A' ||
str[i] == 'e' ||
str[i] == 'E' ||
str[i] == 'i' ||
str[i] == 'I' ||
str[i] == 'o' ||
str[i] == 'O' ||
str[i] == 'u' ||
str[i] == 'U')
which is "not(that or that or that)"
or
the logically equivalent
"not that and not that and not that".
(str[i] != 'a' &&
str[i] != 'A' &&
str[i] != 'e' &&
str[i] != 'E' &&
str[i] != 'i' &&
str[i] != 'I' &&
str[i] != 'o' &&
str[i] != 'O' &&
str[i] != 'u' &&
str[i] != 'U')
Note, I chose to discuss the logic of your code, assuming that it is interesting for you and helpful for your learning. However, I really like the other answer too, which is strong on the wheel-not-inventing philosophy. I won't explain, look there.
Full logic:
if ( ( (str[i] >= 'a' && str[i] <= 'z') ||
(str[i] >= 'A' && str[i] <= 'Z')
)
/* a letter */
&&
/* not a vowel */
( str[i] != 'a' && str[i] != 'A' &&
str[i] != 'e' && str[i] != 'E' &&
str[i] != 'i' && str[i] != 'I' &&
str[i] != 'o' && str[i] != 'O' &&
str[i] != 'u' && str[i] != 'U'
)
)
Without the additional pair of () around "is a letter" you would get
"is a lower case or is an upper case consonant",
i.e. would still be counting lower case vowels.

You just change
||(str[i] >= 'A' && str[i] <= 'Z')
&&(str[i] != 'a' || str[i] != 'A'
||str[i] != 'e' || str[i] != 'E'
||str[i] != 'i' || str[i] != 'I'
||str[i] != 'o' || str[i] != 'O'
||str[i] != 'u' || str[i] != 'U'))
to
&&(str[i] != 'a'
&& str[i] != 'A'
&&str[i] != 'e'
&& str[i] != 'E'
&& str[i] != 'i'
&& str[i] != 'I'
&& str[i] != 'o'
&& str[i] != 'O'
&& str[i] != 'u'
&& str[i] != 'U'))
my code:
#include <stdio.h>
#include <string.h>
int main()
{
char str[100];
int i=0, consonants=0;
int vowels=0,numbers=0;
int freq[256] = {0};
printf("\n Please Enter any String : ");
scanf("%[^\n]", str);
vowels=0,numbers=0,i=0;
while (str[i] != '\0')
{
if((str[i]>= 'a'&&str[i]<= 'z') || (str[i] >= 'A' && str[i] <= 'Z')&&(str[i] != 'a' && str[i] != 'A' &&str[i] != 'e'&& str[i] != 'E' && str[i] != 'i' && str[i] != 'I' && str[i] != 'o' && str[i] != 'O'&& str[i] != 'u' && str[i] != 'U'))
{
consonants++;
freq[str[i]]++;
}
i++;
}
printf("\n Number of Consonants in this String = %d", consonants);
printf("\n\n");
for (i = 0; i < 256; i++)
{
if (freq[i] != 0)
{
printf("\nThe frequency of %c is %d", i, freq[i]);
}
}
printf("\n\n");
return 0;
}

Related

Reverse strings of vowels

I have to find the vowels in an input string and return the string of the vowels in reverse order.
Example input: "woUIW"
The expected output is "IUOo"
But I cannot use pointers, only recursion.
This is my attempt:
void letters_revers(char s[])
{
int i = 0,g,len,right,left;
char reversed[10];
len=strlen(reversed)-1; // get the length of the string
left = 0; // set left index at 0
right = len - 1; // set right index len - 1
while(i!='\0')
{
if (s[i] == 'a' || s[i] == 'A' || s[i] == 'e' || s[i] == 'E' || s[i] == 'i' || s[i] == 'I' || s[i] =='o' || s[i]=='O' || s[i] == 'u' || s[i] == 'U')
{ reversed[i]+=s[i];
for(g = len - 1; g >= 0; g--)
{
printf("%c", reversed[g]);
}
}
}i++;
}

Problem in building a function that counts the letters in a function - Cs50

I am getting an int of the entire string s for 'letter', the conditions in my 'if' statement seem to not be reading properly - is my syntax incorrect?
I get user input:
string s = get_string("Text here: ");
the function is as follows:
int letter_count(string s)
{
int i =0;
int len = strlen(s);
int letter = 0;
while(i < len)
{
if (s[i] != '\0' || s[i] != '.' || s[i] != ',' || s[i] != '!' || s[i] != '?')
{
letter++;
}
i++;
}
return letter;
}
then call the function:
int letter = letter_count(s);
printf("letter Count: %i\n", letter);
Try changing the OR operator with the AND
if (s[i] != '\0' || s[i] != '.' || s[i] != ',' || s[i] != '!' || s[i] != '?')
is ALWAYS true. Because any character is either not "." or not ",". Which letter would you expect to be both?
You want to check whether the current letter is "not ." AND "not ," AND "not !".
I.e.
if (s[i] != '\0' && s[i] != '.' && s[i] != ',' && s[i] != '!' && s[i] != '?')
Almost correct, you have to change the type of the argument to char*, there is no string type on the default libraries. (Documentation of string library).
Working example with the modifications:
#include <stdio.h>
#include <string.h>
int letter_count (char* s)
{
int i = 0;
int len = strlen (s);
int letter = 0;
while (i < len)
{
if (s[i] != '\0' && s[i] != '.' && s[i] != ',' && s[i] != '!'
&& s[i] != '?')
{
letter++;
}
i++;
}
return letter;
}
int main ()
{
char my_word[] = "Sample word";
printf ("'%s' have %d letters",my_word, letter_count (my_word));
return 0;
}
Output:
'Sample word' have 11 letters

Test if the input is integer or symbol in fgets in C

I am constructing a program that takes string input from the keyboard then shows the number of consonants as an output. I have managed to do it in a ridiculous way in the function count_consonants. I tested using if statement whether each character in the input is a number or symbol to ignore them during calculations. I originally wanted to check if the string is not a string using fgets but I don't know how. That's not an effective way, so any ideas for this?
#include <stdio.h>
#include <string.h>
//function to calculate the consonants
int count_consonants(char str[]) {
int idx;
for (idx = 0; idx < 100; ++idx) {
if (str[idx] == '\0') {
break;
}
}
int vowl = 0;
for (int i = 0; i < idx; ++i) { //loop to check if the characters are vowels or not
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o'
|| str[i] == 'u' || str[i] == 'A' || str[i] == 'E' || str[i] == 'I'
|| str[i] == 'O' || str[i] == 'U' || str[i] == ' ') {
vowl += 1;
}
// numbers and symbols are counted here as vowels because if not,
// the compiler will count them the other way around
if (str[i] == '1' || str[i] == '2' || str[i] == '3' || str[i] == '4'
|| str[i] == '5' || str[i] == '6' || str[i] == '7' || str[i] == '8'
|| str[i] == '9') {
vowl += 1;
}
if (str[i] == ':' || str[i] == ',' || str[i] == '.' || str[i] == '$'
|| str[i] == '%' || str[i] == '^' || str[i] == '&' || str[i] == '*'
|| str[i] == '#' || str[i] == '_' || str[i] == '!') {
vowl += 1;
}
}
int cons = idx - vowl; // consonants = whole length of text - vowels
return cons - 1;
}
int main(int argc, char const *argv[]) {
char string[100];
char store[100][100];
int i = 0;
while (string[0] != '\n') {
fgets(string, 100, stdin);
strcpy(store[i], string);
i++;
}
for (int j = 0; j < i - 1; ++j) {
/* code */
printf("Number of consonants=%d\n", count_consonants(store[j]));
}
return 0;
}
shows the number of consonants
A simply way to count consonants, use isalpha(), strchr()
#include <string.h>
#include <ctype.h>
int my_isavowel(char ch) {
const char *p = strchr("aeiouAEIOU", ch); // search for a match
return p && *p; // If p is not NULL, and does not point to \0
}
int count_consonants(const char str[]) {
int count = 0;
while (*str != '\0') { // while not at end of string ...
char ch = *str++; // Get character and advance
count += isalpha((unsigned char) ch) && !my_isvowel(ch);
}
return count;
}
If you look for number of consonants, simply best count consonants instead of other things
#include <stdio.h>
#include <string.h>
int main (int narg,char*args[]){
char cons[ ] = "ZRTPQSDFGHJKLMWXCVBN";
char sentence[ ] = "This is my sentence!";
int i=0;
int sum_cons = 0;
for (i = 0; i < strlen(sentence); ++i)
if (strchr(cons,strupr(sentence)[i])) sum_cons++;
printf ("#CONS>%i\n",sum_cons);
return 0;
}

C function to remove vowels in a string not working?

Here is my function to remove the vowels in a string;
char *removeVowels(char *inString) {
int count = 0; //to count the non vowel characters
for (int i = 0; inString[i]; i++)
if (inString[i] != 'a' || inString[i] != 'e' || inString[i] != 'u' || inString[i] != 'o' || inString[i] != 'i')
inString[count++] = inString[i]; //if character is not a vowel placed at count++
inString[count] = '\0';
return inString;
}
The problem is that it is returning the original string inputted. Any ideas?
There is a confusion between the || and && operators. You want to test that the character is different from 'a' AND different from 'e' etc.
Here is a modified version:
char *removeVowels(char *inString) {
int count = 0; // index for preserved characters
for (int i = 0; inString[i]; i++) {
if (inString[i] != 'a' && inString[i] != 'e' && inString[i] != 'i'
&& inString[i] != 'o' && inString[i] != 'u') {
inString[count++] = inString[i]; // copy the non-vowel character
}
}
inString[count] = '\0'; // set the null terminator.
return inString;
}
Note however that uppercase vowels are not removed by this function, and whether y should be considered a vowel remains to be decided.
As stated in another comment, you need to use && instead of || to make sure that the character does not match any vowels. It might be easier to create a new string and add non-vowels to that string as you go. Something like:
char *removeVowels(char *inString, int size){
char newString[size];
int count = 0;
for(int i = 0; i < size; i++){
if(inString[i] != 'a' && inString[i] != 'e' && inString[i] != 'i' && inString[i] != 'o' && inString[i] != 'u'){
newString[count] = inString[i];
count++;
}
}
newString[count] = '\0';
return newString;
}

Why does loop work this way?

I created a program. It works as I wanted it to work, but I don't understand why.
This is the function.
void LiteraMajuscula(char *str)
{
int i;
i = 0;
while (str[i] != '\0')
{
if (i == 0 && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
if (str[i-1] == ' ' && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
i++;
}
}
It is supposed to make the lowercase character into an uppercase one each time there is a space and only the first one and if the first character from a string is lowercase, make it an uppercase.
The only thing i dont understand is the str[i-1]. I tried str[i], but it doesn't change anything, and str[i-2] changes the second letter into and uppercase instead of the first one. Why is that?
str[i] -= 32; will convert the character at index i. The reason the second if statement uses str[i-1] == ' ' in its check is so it knows whether the current character (at i) is just after a space (at i - 1). The reason it converted the second character of words when you changed it to str[i-2] == ' ' is that you changed it so it converted a character if it (at i) was two characters after a space (at i-2).
As noted in the comments, the code there has undefined behavior, because there's nothing preventing the str[i-1] == ' ' check when i is 0, so str[i-1] would be accessing the character before where str is pointing.
Separately, since most of the conditions and logic are duplicated between the two ifs, this is where you'd use || (logical OR):
while (str[i] != '\0')
{
if ((i == 0 || str[i-1] == ' ') && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
i++;
}
(Note the () around the ||.)
|| short-circuits, so when i is 0 and the first operand is true, the second operand (str[i-1] == ' ') is never evaluated and so you avoid undefined behavior.
The body of the loop is incorrect
while (str[i] != '\0')
{
if (i == 0 && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
if (str[i-1] == ' ' && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
i++;
}
When i is equal tp 0 then in this condition
if (str[i-1] == ' ' && str[i] >= 'a' && str[i] <= 'z')
^^^^^^^^
there is an attempt to access memory beyond the string. The loop should be rewritten at least like
while (str[i] != '\0')
{
if ( ( i == 0 || str[i-1] == ' ' ) && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
i++;
}
That is the condition checks whether the first character of the string is an alpha character or if it is not the first character of the string whether the previous character is space and the current character is an alpha character.
Take into account that the function will not work with EBCDIC characters. It is better to use standard C function toupper declared in header <string.h>. For example
while (str[i] != '\0')
{
if ( i == 0 || str[i-1] == ' ' )
{
if (isalpha((unsigned char)s[i]) ) s[i] = toupper((unsigned char)s[i]);
}
i++;
}
I think it is desirable also to check whether the previous character is the tab character. Also such string functions usually return the target string.
I would write the function the following way
#include <stdio.h>
#include <ctype.h>
char * LiteraMajuscula( char *s )
{
for (size_t i = 0;
s[i += strspn(s + i, " \t")] != '\0';
i += strcspn( s + i, " \t" ))
{
if (isalpha((unsigned char)s[i]) ) s[i] = toupper((unsigned char)s[i]);
}
return s;
}
int main(void)
{
char s[] = "hello,\tworld!";
puts(s);
puts(LiteraMajuscula(s));
return 0;
}
Its output is
hello, world!
Hello, World!
The other answers posted have explained what was wrong with the code.
Here is an alternative way that the function can be rewritten to be more efficient and more portable, with the use of functions from ctype.h:
void do_some_incorrect_capitalization (char str[])
{
if(*str == '\0')
{
return ;
}
*str = toupper(*str); // special case, first letter in the string
str++;
while(*str != '\0')
{
if(isspace(*(str-1)))
{
*str = toupper(*str);
}
str++;
}
}

Resources