Calculating the Character frequency in a String using C - c

I have written a program to calculate the character frequency in a string entered by the user. It's giving correct output for all lower case letters but it's not working for upper case letters. I am unable to find the problem in the code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int c = 0, count[26] = {0};
printf("Enter a string\n");
fgets(string,100,stdin);
while(string[c] != '\n') {
c++;
}
string[c] = '\0';
c = 0;
while (string[c] != '\0')
{
/** Considering characters from 'a' to 'z' only
and ignoring others */
if (string[c] >= 'a' && string[c] <= 'z')
count[string[c]-'a']++;
else if(string[c] >= 'A' && string[c]<= 'Z')
count[string[c]-'A']++;
c++;
}
for (c = 0; c < 26; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (count[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'a',count[c]);
}
return 0;
}
Please Help!
Here is the screenshot. Hopefully you will understand what problem I am facing:
It's not counting the upper case letters.

The only issue that I can see is bounds...
EDIT
This can be entirely skipped since fgets() ensures a trailing '\0' and you handle '\n' gracefully later in your checks.
while(string[c] != '\n') {
c++;
}
string[c] = '\0';
To remove the '\n' it should be
while(string[c] && string[c] != '\n') {
c++;
}
string[c] = '\0';
and
while (string[c] != '\0')
is good because of the semantics of fgets().

It works fine, but the output may be confusing you!
For the input string "Foo", the output is this:
f occurs 1 times in the entered string.
o occurs 2 times in the entered string.
Lower and uppercase are counted together, so you don't see "F occurs 1 times".
http://ideone.com/ACJnPD

IGuessing that the problem is to separate count of Upper and Lower case character you could use different arrays to count frequencies:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int c = 0, countLower[26] = {0};
int countUpper[26] = {0};
printf("Enter a string\n");
fgets(string,100,stdin);
while((string[c] != '\0') && (string[c] != '\n')) {
c++;
}
string[c] = '\0';
c = 0;
while (string[c] != '\0')
{
/** Considering characters from 'a' to 'z' only
and ignoring others */
if (string[c] >= 'a' && string[c] <= 'z')
countLower[string[c]-'a']++;
else if(string[c] >= 'A' && string[c]<= 'Z')
countUpper[string[c]-'A']++;
c++;
}
for (c = 0; c < 26; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (countLower[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'a',countLower[c]);
if (countUpper[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'A',countUpper[c]);
}
return 0;
}

Related

How can I capitalize each word in string c program

I just code a program about string. My problem is how can I capitalize word at even number position of a string in c. My logic is a word at even can divide 2 equal 0. anyone can help me please, thank so much. here is my code:
#include <stdio.h>
void upper_string(char []);
int main()
{
char string[100];
printf("Enter a string to convert it into upper case\n");
gets(string);
upper_string(string);
printf("The string in upper case: %s\n", string);
return 0;
}
void upper_string(char s[]) {
int c = 0;
while (s[c] != '\0') {
if (s[c] >= 'a' && s[c] <= 'z')
{
s[c] = s[c] - 32;
}
c++;
}
}
You need to use space counter to keep track of the words.
if space counter is odd then capitalize the letters until you reach the next word.
Example:
void upper_string(char s[]) {
int c = 0;
int spaceCounter = 0; //First word not to be capitalized
while (s[c] != '\0')
{
if ((spaceCounter %2 == 1) && s[c] >= 'a' && s[c] <= 'z')
{
s[c] = s[c] - 32; // You can use toupper function for the same.
}
else if(s[c] == ' ')
{
spaceCounter++; //Reached the next word
}
c++;
}
}

C language - return a value from function as function parameter

I have a problem with my homework. I need to count quantity of upper case and quantity of vowels in string. Unfortunately, it always returns number 0 which looks as it doesn't change in function. Everything works until this one.
Here is my code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[40];
int upper, chars;
puts("Type a string");
gets(text);
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white spece to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d", chars);
getch();
return 0;
}
char *StringChange(char *text, int *upper, int *chars) {
int i, length;
length = strlen(text);
for (i = 1; i <= length; i++) {
if (text[i - 1] == '*' && (text[i] >= 'a' && text[i] <= 'z')) {
text[i] = text[i] - 32;
}
if (text[i] == ' ') {
text[i] = '*';
}
if (text[i] >= 'A' && text[i] <= 'Z') {
*upper = *upper + 1;
/* *upper++; that also doesn't work */
}
if (text[i] == 'a' || text[i] == 'e' || text[i] == 'i' || text[i] == 'o' || text[i] == 'u' || text[i] == 'y') {
*chars = *chars + 1;
/* *chars++; that also doesn't work */
}
}
if (text[0] >= 'a' && text[0] <= 'z') {
text[0] = text[0] - 32;
}
return (text);
}
I tried your code and I do get non-zero results -- depending on the input, of course, so maybe you are only testing on strings that produce zero.
However, the results are not always correct. There are two problems I found in the code:
1) As pointed out in a comment, you should initialize upper and chars to 0.
2) You are starting the loop at index 1, not index 0. I think you did this so you could look at text[i-1] inside the loop, but it is causing you to exclude the first character from your totals. You should start the loop index and 0 and figure out a different way to handle it within the loop. (Hint - note that the first if within the loop and the one following the loop have similar conditions and the same body.)
There are multiple issues in your code:
you should never use gets().
the variables upper and chars are not initialized
the function StringChange make a special case of text[0] but does not update the counts for this initial byte.
you hard code the conversion of lowercase to uppercase for ASCII.
you should stop at the end of the string
all white space is not replaced, on whitespace followed by a lowercase letter.
uppercase vowels should be counted too.
Here is a modified version:
#include <stdio.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[200];
int upper, vowels;
puts("Type a string");
if (fgets(text, sizeof text, stdin)) {
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white space to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d\n", vowels);
}
getchar();
return 0;
}
char *StringChange(char *text, int *upper, int *vowels) {
int i, at_start = 1;
*upper = *vowels = 0;
for (i = 0; text[i] != '\0'; i++) {
char c = text[i];
if (at_start && c >= 'a' && c <= 'z') {
c += 'A' - 'a';
text[i] = c;
}
if (c == ' ') {
c = '*';
text[i] = c;
at_start = 1;
} else {
at_start = 0;
}
if (c >= 'A' && c <= 'Z') {
(*upper)++; // *upper++ would just increment the pointer, leading to undefined behavior
}
if (strchr("aeiouyAEIOUY", c) {
(*vowels)++;
}
}
return text;
}

there is a test that stuck at infinity loop can you find it?

int main() {
int s, b;
int hist[26] = { 0 };
int hist2[26] = { 0 };
char char1, char2;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
scanf("%c", &char2);
while (char2 != '$') {
if (char2 >= 'A' && char2 <= 'Z')
char2 = char2 + 32;
int char3 = char2 - 'a';
hist2[char3]++;
scanf("%c", &char2);
if (char2 < 0)
break;
}
printf("How many times would you like to loop?\n");
if (!scanf("%d", &s))
return 0;
printf("Enter the string you would like to be checked ending with $:\n");
scanf("%c", &char1);
if (char1 >= 'A' && char1 <= 'Z')
char1 = char1 + 32;
while (char1 != '$' && char1 > 0) {
int char3 = char1 - 'a';
hist[char3]++;
scanf("%c", &char1);
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
b = 0;
break;
} else {
b = 1;
}
}
if (b)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}
//so basically this a homewrok in my university they asked us to do the program input is char and a loop and it compare it with one more input how many times you can loop each letter (no need to check that the input is true but the loop number int
Your program has many problems:
scanf() returns the number of successful conversions. Compare the return value to 1 in your program instead of testing 0, which would never happen for "%c" anyway. Furthermore, the char2 would not be modified if the stream is at end of file.
You must check of char2 is a letter before indexing into the array, otherwise you may access beyond the array boundaries and have undefined behavior.
presentation is important: use proper indentation and spacing for the program to be readable.
include the necessary headers such as <stdio.h>
Here is an improved version:
#include <stdio.h>
int main() {
int hist[26] = { 0 };
int hist2[26] = { 0 };
int s;
char c;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
while ((scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist2[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist2[c - 'a']++;
}
printf("How many times would you like to loop?\n");
if (scanf("%d", &s) != 1)
return 1;
printf("Enter the string you would like to be checked ending with $:\n");
while (scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist[c - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
break;
}
}
if (i == 26)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}

Program that counts Uppercase and Lowercase letters in a String in C

so I want to make a code where you can find the number of upper and lowercase letters in a string (no spaces)
So I want something like this:
input:
HEllO
Output:
2 3
So what I have of code is this:
#include<stdio.h>
int main() {
int upper = 0, lower = 0;
char ch[80];
int i;
printf("\nEnter The String : ");
gets(ch);
i = 0;
while (ch[i] != '') {
if (ch[i] >= 'A' && ch[i] <= 'Z')
upper++;
if (ch[i] >= 'a' && ch[i] <= 'z')
lower++;
i++;
}
printf("%d %d", upper, lower);
return (0);
}
There is a problem with the code, but I cannot find the mistake. Can someone please fix it? Thanks.
Corrected code-
#include <stdio.h>
int main(void)
{
int upper = 0, lower = 0;
char ch[80];
int i = 0;
printf("\nEnter The String : ");
fgets(ch, sizeof(ch), stdin);
while (ch[i] != '\0')
{
if (ch[i] >= 'A' && ch[i] <= 'Z')
upper++;
if (ch[i] >= 'a' && ch[i] <= 'z')
lower++;
i++;
}
printf("\nuppercase letter(s): %d \nlowercase letter(s): %d", upper, lower);
return 0;
}
Note: I have used fgets() instead of gets() as the latter suffers from a buffer overflow issue.
In C a string always terminates with '\0'. The empty string '' and the escape null character are not identical.
while (ch[i] != '') should be while (ch[i] != '\0')
Your program should work then.
The problem is the expression ''. A character constant must have something between the single quotes. In this case, you want to test for end of string, so you would use the null character constant: '\0'.
#include <stdio.h>
int main(void) {
int upper = 0, lower = 0;
char ch[80];
int i;
printf("\nEnter The String : ");
fgets(ch, sizeof(ch), stdin);
i = 0;
while (ch[i] != '\0') {
if (ch[i] >= 'A' && ch[i] <= 'Z')
upper++;
if (ch[i] >= 'a' && ch[i] <= 'z')
lower++;
i++;
}
printf("%d %d\n", upper, lower);
return 0;
}
Note that I also replaced gets with fgets. You should never use gets(). It doesn't get passed the length of your buffer, so if the input is more than 79 characters long, it will overflow the ch array, causing undefined behavior. fgets takes a size argument and stops reading once it's read size - 1. It also includes the newline in the resulting string if one is present in the input, which gets does not.
A better approach that works properly for all input lengths is to read the string in one character at a time, and not bother storing it, since all you care about is the count of upper and lower.
#include <stdio.h>
int main(void) {
unsigned upper = 0, lower = 0;
printf("\nEnter The String : ");
int c;
while (EOF != (c = getchar())) {
if ('\n' == c) break;
if (c >= 'A' && c <= 'Z')
upper++;
if (c >= 'a' && c <= 'z')
lower++;
}
printf("%u %u\n", upper, lower);
return 0;
}

Adding scanf and EOF to program

#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int c = 0, count[26] = {0};
int accum = 0;
printf("Enter a string\n");
gets(string);
while ( string[c] != '\0' )
{
if ( string[c] >= 'a' && string[c] <= 'z' ){
count[string[c]-'a']++;
accum++;
}
else if (string[c] >= 'A' && string[c] <= 'Z'){
count[string[c]-'A']++;
accum++;
}
c++;
}
for ( c = 0 ; c < 26 ; c++ )
{
if( count[c] != 0 )
printf( "%c %f\n", c+'a', ((double)count[c])/accum);
}
return 0;
}
This should be an easy question, but I can't seem to get it to work. Right now, I have the print statement "Enter a string". I want to change it so that the user can keep inputting a string using scanf instead of printf until EOF is reached. Basically I want to remove the "Enter a string" statement and just have input a string until EOF and then have the letter frequency run once on all the strings inputted. How would I do that?
To do this using scanf() for input.
scanf() returns EOF when the EOF condition or IO error occurs.
// printf("Enter a string\n");
char ch;
while (scanf("%c", &ch) == 1) {
if ( ch >= 'a' && ch <= 'z' ){
count[ch-'a']++;
accum++;
}
...
}
Using int ch = fgetc(stdin) would make more sense.
"The fscanf function returns the value of the macro EOF if an input failure occurs
before the first conversion (if any) has completed. Otherwise, the function returns the
number of input items assigned, which can be fewer than provided for, or even zero, in
the event of an early matching failure." C11dr ยง7.21.6.2 16
Add your printf and gets statements inside the while loop
printf("Enter a string\n");
gets(string);
while ( string[c] != '\0' )
{
...//remaining code inside while loop
printf("Enter a string\n");
gets(string);
}
... //for loop code and return 0;
Here you go. I zeroed the variables for each loop. And I treated a blank entry (just press Enter) as EOF. But if you wanted the statistics for all the strings, don't zero the values at the start of the while loop
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char string[100];
int c = 0, count[26] = {0};
int accum = 0;
do {
c = 0;
accum = 0;
memset (count, sizeof count, 0);
gets(string);
if (strlen (string) < 1)
break; // terminate
while ( string[c] != '\0' ) {
if ( string[c] >= 'a' && string[c] <= 'z' ) {
count[string[c]-'a']++;
accum++;
}
else if (string[c] >= 'A' && string[c] <= 'Z') {
count[string[c]-'A']++;
accum++;
}
c++;
}
for ( c = 0 ; c < 26 ; c++ ) {
if( count[c] != 0 )
printf( "%c %f\n", c+'a', ((double)count[c])/accum);
}
}
while (1);
return 0;
}

Resources