1

I'm writing a function to capitalize every lowercase character in a string. It takes a string from the user and that is the input to the function. My program works if the user doesn't enter spaces, but when there is a space in the string, the function ends.

#include <stdio.h>

char *uppercase(char *c) {
    int i = 0;
    while (c[i] != '\0') {
        if (123 > c[i] && c[i] > 96)
            c[i] = c[i] - 'a' + 'A';
        i++;
    }
    return c;
}

int main() {
    char input[100];
    printf("Enter the phrase: ");
    scanf("%s", input);
    printf("%s", uppercase(input));
    return 0;
}

Examples:

Input: test test
Output: TEST

Input: Hello
Output: HELLO

Input: How are you
Output: HOW

I think it has to do with the while statement? Thanks for the help.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
21mustard
  • 21
  • 1
  • 1
    Use `fgets` to read text with whitespace – UnholySheep Nov 21 '21 at 22:19
  • 1
    Does this answer your question? [How do you allow spaces to be entered using scanf?](https://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-using-scanf) – UnholySheep Nov 21 '21 at 22:20

2 Answers2

1

The problem is not in the while statement, but rather due to the scanf() format: %s reads a single word from the input, leaving the rest of the line in the stdin buffer. Note also that typing a word with more than 99 characters will cause undefined behavior because scanf() will write beyond the end of the input array. Using %99s would prevent this problem, but not solve your issue.

You should use fgets() to read a full line of input from stdin.

Furthermore, instead of using hard coded ASCII values, you should use character constants such as 'a' and 'z' or the functions from <ctype.h>.

Here is a modified version using ASCII:

#include <stdio.h>

char *uppercase(char *s) {
    int i = 0;
    while (s[i] != '\0') { 
        if (s[i] >= 'a' && s[i] <= 'z')
            s[i] = s[i] - 'a' + 'A';
        i++;
    }
    return s;
}

int main() {
    char input[100];
    printf("Enter the phrase: ");
    if (fgets(input, sizeof input, stdin)) {
        fputs(uppercase(input), stdout);
    }
    return 0;
}

Here is a more portable one using <ctype.h>:

#include <ctype.h>
#include <stdio.h>

char *uppercase(char *s) {
    int i = 0;
    unsigned char c;
    while ((c = s[i]) != '\0') {
        if (islower(c))
            s[i] = toupper(c);
        i++;
    }
    return s;
}

This can be further simplified as toupper() can be called for all byte values from 0 to UCHAR_MAX:

#include <ctype.h>
#include <stdio.h>

char *uppercase(char *s) {
    for (size_t i = 0; s[i] != '\0'; i++) {
        s[i] = toupper((unsigned char)c);
    }
    return s;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

Either use

scanf ("%99[^\n]", input);

or

fgets( input, sizeof( input ), stdin );

Also it is a bad practice to use magic numbers like 123 or 96

if (123 > c[i] && c[i] > 96)

The code will be more readable if you will write at least

if ( 'a' <= c[i] && c[i] <= 'z' )

Also instead of the while loop it is better to use the for loop like

for ( char *p = c; *p; ++p )
{
    if ( 'a' <= *p && *p <= 'z' )
    {
        *p = *p - 'a' + 'A'; 
    } 
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • `scanf("%99[^\n]", input);` and `fgets(input, sizeof(input), stdin);` behave differently in obvious and more subtle ways: `scanf()` will leave the newline pending in the `stdin` buffer and will fail and return `0` if the user enters an empty line. – chqrlie Nov 21 '21 at 22:42
  • @chqrlie And what? How this prevents to use either of the functions? – Vlad from Moscow Nov 21 '21 at 22:44
  • It does not, but I meant to warn the OP about these non obvious pitfalls. – chqrlie Nov 21 '21 at 22:45