Program that counts Uppercase and Lowercase letters in a String in C - 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;
}

Related

I can't figure out how to use the strlen in my C code

I just started learning C. I am supposed to create a password program where the user inputs strings that are at least 8 characters longs. It also needs to have one upper case, one lower case, one digits, and one symbol from this set {#, %, +}. I can't try to figure out the loop where it prints invalid when the user doesn't type in at least 8 characters. I tried using strlen but it gives me an error passing argument 1 of ‘strlen’ makes pointer from integer without a cast can someone help me?
#include <stdio.h>
#include <string.h>
int main()
{
int n;
int k;
char ch;
unsigned char uFlag = 0, cFlag = 0, dFlag = 0, hFlag = 0, aFlag = 0;
printf("Enter a password: ");
ch = getchar();
n = strlen(ch);
k = n - 1;
while (ch != '\n')
{
if(ch >= 'A' && ch <= 'Z')
uFlag = 1;
else if(ch >= 'a' && ch <= 'z')
cFlag = 1;
else if(ch >= '0' && ch <= '9')
dFlag = 1;
else if(ch == '#' || ch == '%' || ch == '+')
hFlag = 1;
else if (k >= 8)
aFlag = 1;
ch = getchar();
}
if (uFlag == 1 && cFlag == 1 && dFlag == 1 && hFlag == 1 && aFlag == 1)
{
printf("Password entered is valid.\n");
}
else
{
printf("Password entered is invalid.\n");
}
return 0;
}
char ch; defines a variable for a single character, not for a string. So you cannot use strlen(ch), because strlen expects a pointer to a string (and not a single character).
As you are reading in one character after another with ch = getchar() in a loop, you actually do not compose any string. The only thing you need to do is increment k with each iteration:
k = 0;
while (ch != '\n')
k++;
...
ch = getchar();
}
You must be used an array of characters and not an char. In your code, you have written -
n = strlen(ch);
However, strlen() accepts char* or an array of character or pointer to a string as parameter. You are passing ch which is of type char and is the wrong parameter data type. This is main reason why you are getting the error.
I have made minor edits in your program which you can refer below -
#include <stdio.h>
#include <string.h>
int main()
{
int i=0; //i to maintain current index in char array-ch
char ch[100],c; //or you could use dynamic allocation by asking user for input, c will read user input
unsigned char uFlag = 0, cFlag = 0, dFlag = 0, hFlag = 0, aFlag = 0;
printf("Enter a password: ");
c = getchar(); //read the input into character as you did
ch[i]=c; //assign the character to current index in ch array
while (ch[i] != '\n') //check until user hits enter
{
if(ch[i] >= 'A' && ch[i] <= 'Z')
uFlag = 1;
else if(ch[i] >= 'a' && ch[i] <= 'z')
cFlag = 1;
else if(ch[i] >= '0' && ch[i] <= '9')
dFlag = 1;
else if(ch[i] == '#' || ch[i] == '%' || ch[i] == '+')
hFlag = 1;
//the below should be if and not if else as in your posted code for it to work as expected
if (i >= 8) // sets the flag once length of array get over 8
aFlag = 1;
i++; // first increment index since we have already read at current index
c = getchar(); //same as before
ch[i] = c;
}
if (uFlag == 1 && cFlag == 1 && dFlag == 1 && hFlag == 1 && aFlag == 1)
{
printf("Password entered is valid.\n");
}
else
{
printf("Password entered is invalid.\n");
}
return 0;
}
Hope this solves your problem !
regarding:
ch = getchar();
n = strlen(ch);
the function getchar() only inputs a single char, not a string.
the function strlen() expects a NUL terminated array of characters.
Suggest inputting the password using;
fgets( buffer, sizeof( buffer ), stdin );
rather than using many calls to getchar()
then use:
buffer[ strcspn( buffer, "\n" ) ] = '\0';
to remove an newline character
then looping through the buffer[], checking each character
for( size_t i=0; buffer[i]; i++ )
{
// perform all the needed checks of the password
}

Count the number of vowels in a series of strings in C

I'm writing a program in C which counts the numbers of the vowels in a series of strings decided by the user, even the number of elements of the strings is decided by the user. The problem is that the function gives always the same numbers of vowels which is the one of the first string.
Here's the code:
#include <stdio.h>
#include <string.h>
int vowels(char str[]);
int main(){
int n, i, x;
printf("How many strings do you want to insert?");
scanf("%d", &n);
printf("How many characters per string?");
scanf("%d", &x);
char str[x];
if(x < 10){
for(i = 0; i < n; i++){
printf("Insert a string:");
scanf("%s", str);
if(strlen(str) == x){
vowels(str);
}
else{
printf("Error\n");
}
}
}
else{
printf("Error: the number of characters must be < 10");
}
return 0;
}
int vowels(char str[]){
int i, j;
while(str[i] != '\0'){
if(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'){
j++; }
i++;
}
printf("Number of vowels in the string:%d\n", j);
return 0;
}
Your code contains two mistakes:
i and j indexes of vowels() function are not initialized, so they contain garbage and will lead to an unpredictable behavior of your loops. That's because local variables, unlike global variables, are not initialized by default to 0.
Use instead
int i=0, j=0;
The buffer char str[x]; will not be able to contain a string with x characters. In fact, the space required by string terminator character '\0'.
So it should be
char str[x+1];
With these changes your code will work.
But...
... but it is not enough. In fact, when you get the input string, you don't perform any check to the number of characters retreived:
scanf("%s", str);
By inserting a very long string you will go out of bounds far beyond the str string, causing undefined behavior and, likely, a program crash.
How to fix it? Since your input string can have a maximum length of 9, just define a fixed length array:
char str[11];
Why size 11? First of all your array must contain the maximum of 9 characters and the terminator. So 10. But it has also to contain an extra character, so that inputs longer that 9 characters can be detected.
After that, just receive input string with
scanf("%10s", str);
In this way all legit input string can be stored (from size 1 to size 9). All strings long 10 or more characters will be truncated to a ten chars long string, and your length check will fail as expected.
Please note that in case of long string all characters exceeding the first 10 will remain unread in the stdin buffer. So in case of error you need a mechanism to consume those chars, otherwise you will find them at the next scanf. I've written this trick:
while( fgets( str, 10, stdin ) != NULL )
{
if( strlen(str) < 10 )
break;
}
The resulting code, with all the changes I described, is the following one:
#include <stdio.h>
#include <string.h>
int vowels(char str[]);
int main(){
int n, i, x;
printf("How many strings do you want to insert?");
scanf("%d", &n);
printf("How many characters per string?");
scanf("%d", &x);
if(x < 10){
char str[11];
for(i = 0; i < n; i++){
printf("Insert a string:");
scanf("%10s", str);
if(strlen(str) == x){
vowels(str);
}
else{
printf("Error\n");
while( fgets( str, 10, stdin ) != NULL )
if( strlen(str) < 10 )
break;
}
}
}
else{
printf("Error: the number of characters must be < 10");
}
return 0;
}
int vowels(char str[]){
int i=0, j=0;
while(str[i] != '\0')
{
if(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')
{
j++;
}
i++;
}
printf("Number of vowels in the string:%d\n", j);
return 0;
}
I'm pasting your code and adding comments inline. Note: I am not fixing anything, just pointing things out for you to fix.
#include <stdio.h>
#include <string.h>
int vowels(char str[]);
int main(){
int n, i, x;
printf("How many strings do you want to insert?");
scanf("%d", &n); // Consider a more descriptive variable name than 'n'
printf("How many characters per string?");
scanf("%d", &x); // Consider a more descriptive name here too.
char str[x]; // Note, a string needs 1 extra character for the NUL character.
if(x < 10){ // 10 is a very magic number. Consider making a constant.
for(i = 0; i < n; i++){
printf("Insert a string:");
scanf("%s", str);
if(strlen(str) == x){
vowels(str);
}
else{
printf("Error\n"); // Consider breaking or returning here if error...
}
}
}
else{
printf("Error: the number of characters must be < 10");
}
return 0;
}
int vowels(char str[]){ // Do you need a return value? What does it represent?
int i, j;
while(str[i] != '\0'){ // i and j are not initialized (to 0). Turning on compiler warnings would catch this.
// a for() loop may make more sense
if(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'){
j++; }
i++;
}
printf("Number of vowels in the string:%d\n", j);
return 0; // Again, maybe this function returns void if we don't need a return.
}
The problems in the vowels function are caused by uninitialized variables. Neither i nor j is given an initial value. A good compiler will generate a warning about this. If you're compiling with gcc or clang, be sure to compile with -Wall -Wextra. Then read the warnings, and fix all of the warnings.
The variable i can be declared and initialized with a for loop, as shown below. The variable j should be given a more descriptive name, like count, and initialized before the loop. You might also want to return the count from the vowels function, and let main do the printing. That way, you can reuse the vowels function in a different program that needs to count vowels, but doesn't want the count printed.
int vowels(char str[]){
int count = 0;
for (int i=0; str[i] != '\0'; i++){
if(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'){
count++;
}
}
return count;
}
The other problem in the program is that the str array is too small. A C string uses a zero byte (known as the NUL terminator) to mark the end of the string. So, for example, if the strlen of a string is 5, then the array holding the string must be at least 6 bytes, 5 for the string, plus one for the NUL.
In your program, you limit the string length to a number less than 10, so you could just declare the str array with a fixed size, e.g. char str[16], and it will always be big enough. OTOH, the scanf doesn't limit the number of characters written into the string, unless you tell it to. The code below shows how to limit the number of characters that scanf writes into the string.
int main(){
int n, x;
printf("How many strings do you want to insert?");
scanf("%d", &n);
printf("How many characters per string?");
scanf("%d", &x);
char str[16];
if(x < 10){
for(int i = 0; i < n; i++){
printf("Insert a string:");
if (scanf("%15s", str) != 1) {
printf("That wasn't a valid input\n");
break;
}
else if(strlen(str) == x){
int count = vowels(str);
printf("Number of vowels in the string:%d\n", count);
}
else{
printf("Error\n");
break;
}
}
}
else{
printf("Error: the number of characters must be < 10");
}
return 0;
}

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;
}

Calculating the Character frequency in a String using 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;
}

Caesar Cipher shifting characters

I had received this assignment last month and ended up getting it wrong because of the problem I will state after this. Currently, I am doing Caesar's Cipher and I believe I have the right format. I ask the user for a string and I encrypted with a key == 3. However, I want to loop around the alphabet if the plaintext letter is X, Y, Z, x, y, or z. But, when I put those any of those characters in, I do not get A, B, and C, but ]... and other braces. Any hints to fix the problem.
Thank you!
void main()
{
int key = 3;
char string[256];
int i = 0;
printf("Enter the string you want encrypted\n");
fgets(string, sizeof(string), stdin);
for (i = 0; i < strlen(string); i++) {
if (string[i] == ' ') {;}
else if ((string[i] >= 'a' && string[i] <= 'z' || string[i] >= 'A' && string[i] <= 'Z')){
string[i] = string[i] + key;
}
}
printf("Cipher text:%s",string);
}
You need to look at the ASCII table: http://www.asciitable.com/. You're using an ASCII encoding of the characters.
Z has a decimal value of 90, so 93 is ']'. You need to manually wrap back around to the beginning of the alphabet. This is best done with a modulo and adding the ASCII value of the first alphabetic character. It's up to you how you wrap capital letters (back to 'a' or to 'A').
You need to convert the character to its position in the alphabet, then find the result modulo 26 (alphabet length), then convert it back to the character. Something like:
char base = 0;
if(string[i] >= 'a' && string[i] <= 'z'){
base = 'a';
}else if(string[i] >= 'A' && string[i] <= 'Z'){
base = 'A';
}
if(base){
string[i] = ((string[i] - base) + key) % 26 + base;
}
You almost got it:
#include <stdio.h>
#include <string.h>
int main() {
char string[256];
int i = 0;
int key = 3;
const int num_letters = 26;
printf("Enter the string you want encrypted\n");
fgets(string, sizeof(string), stdin);
for (i = 0; i < strlen(string); i++) {
if (string[i] >= 'a' && string[i] <= 'z') {
string[i] = 'a' + (string[i] - 'a' + key) % num_letters;
}
else if (string[i] >= 'A' && string[i] <= 'Z') {
string[i] = 'A' + (string[i] - 'A' + key) % num_letters;
}
}
printf("Encrypted: %s\n", string);
return 0;
}
Enter the string you want encrypted
Zorro
Encrypted: Cruur
In C you can use the modulo operator % to wrap around, as shown above. Good luck!

Resources