-2

Trying to take a lower case string, and create a new string after making characters uppercase

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

int main (void)
{
    string word = "science";
    char new_word[] = {};

    for (int i = 0, len = strlen(word); i < len; i++)
    {
        if (islower(word[i]))
        {
            new_word = new_word + toupper(word[i]);
        }
    }
}

I am getting "error: array type 'char[0]' is not assignable".

This isn't all, and I am sure with my full program there might be an easier way, but I built out everything else, and the only point that I am struggling with is looping through my string to get a new word that is uppercase.

Any assistance would be greatly appreciated!

ccrund
  • 1
  • 2
    Your variable "new_word" is being declared as a zero length char array. Unlike C# Lists and other IEnumerables, an array (even in C#) is fixed length, so you can't assign something to the zero length array. You need to give the array a length, probably `strlen(word)`. https://www.simplilearn.com/tutorials/c-tutorial/array-in-c And here's a "better way" to do what you want: https://stackoverflow.com/questions/35181913/converting-char-to-uppercase-in-c – computercarguy Dec 15 '22 at 23:51
  • @MM -- I retract that -- right you are, sizeof a pointer. – David C. Rankin Dec 16 '22 at 00:52

4 Answers4

1
char new_word[] = {};

Your new char array has length 0 and any access invokes undefined behaviour (UB) as you access it outside its bounds.

If your compiler supports VLAs:

    string word = "science";
    char new_word[strlen(word) + 1] = {0,};

if not:


    string word = "science";
    char *new_word = calloc(1, strlen(word) + 1);

and

new_word[i] = toupper((unsigned char)word[i]);

If you used calloc do not forget to free the allocated memory

0___________
  • 60,014
  • 4
  • 34
  • 74
1

Undefined behavior when word[i] < 0

Avoid that by accessing the string as unsigned char

As per C reference about toupper()

int toupper( int ch );

ch - character to be converted. If the value of ch is not representable as >unsigned char and does not equal EOF, the behavior is undefined.

This is not correct, compiler gives error , "error: assignment to expression with array type"

new_word = new_word + toupper(word[i]);

which is not allowed with an array type as LHS of assignment. changed to new_word[i] = toupper((unsigned char)word[i]);

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

int main (void)
{
    char word[] = "science";
    char new_word[sizeof word] = ""; 
    int i;

    for (i = 0; i < sizeof(word); i++)
    {
        if (islower(word[i]))
        {
            new_word[i] = toupper(word[i]);
        }
        else    /* for Upper case latter, simply fill the array */
        {
            new_word[i] = word[i];
        }
    }
    new_word[i] = '\0';
    printf("%s", new_word);
}

OUTPUT: SCIENCE

EDIT: Just echo comment from solution given by M.M and comment from David C. Rankin casting is not necessary for this example. read comment below from M.M and David C. Rankin Removed unsigned char from islower() and toupper()

user23
  • 41
  • 7
  • I like your approach. A couple of optimizations: Q: Why call the function "strlen(word)" when, in this particular case, you can use the "sizeof word" instead? Q: Why bother with "if islower())? Why not just assign "toupper()" for every byte? Q: Did you notice the bug for any letter that's ALREADY upper case? – paulsm4 Dec 16 '22 at 00:16
  • You forget about the case of filling in `new_word` with the characters that were not lower-case – M.M Dec 16 '22 at 00:17
  • @paulsm4 Thanks for suggestion. I will edit accordingly – user23 Dec 16 '22 at 00:23
  • @M.M thanks for your comment. I have added handling if uppercase latter present in strnig – user23 Dec 16 '22 at 00:30
  • Good job with the cast to `unsigned char`, but with `char word[] = "science";`, you are guaranteed that all characters are representable as `unsigned char`. You are correct, but good to understand why. – David C. Rankin Dec 16 '22 at 00:31
  • @DavidC.Rankin a reasonable assumption to make in questions like this is that the code is supposed to work for other inputs besides just the sample input shown – M.M Dec 16 '22 at 00:31
  • Yes, that is a good assumption, but so long as you are reading ASCII, or reading with a function that reads bytes into a character array, then the same would hold. Max of any 8-bit value is `255`. Where the type passed to any of the `ctype.h` functions is other than `char`, `unsigned char` or `uint8_t`, then the cast to `unsigned char` is necessary. – David C. Rankin Dec 16 '22 at 00:35
0
This is but one way of accomplishing the task. Make sure to come up with your way of doing.

    #include <stdio.h>
    #include <string.h>
    #define MAX_BUFF 128   
    
    char *upperCase(char *c) {
        //printf("%s, %d", c, strlen(c));
        for(int i=0; i<strlen(c) && i<MAX_BUFF; i++) {
           c[i] = c[i] - ' ';  // convert char to uppercase
           //printf(">> %c", c[i]);
        }
        return c;
     }  
    int main (void)
    {
        char word[MAX_BUFF] = "science";
        char new_word[MAX_BUFF];
        
         printf("in>> %s \n", word);
         strcpy(new_word, upperCase(&word[0]));
         printf("out>> %s\n", new_word);
    }

Output:
in>> science 
out>> SCIENCE
MZM
  • 105
  • 1
  • 3
0

Named arrays cannot be resized in C, you have to set the size correctly to start:

size_t len = strlen(word);
char new_word[len + 1];   // leaving room for null-terminator

Note that no initializer can be used for new_word when its size was determined by a function call (a lame rule but it is what it is); and you can take out the len loop variable since it is now defined earlier.

Then set each character in place:

new_word[i] = toupper(word[i]);

but be careful with the surrounding if statement: if that were false, then you need to set new_word[i] = word[i] instead.

(Pro tip, you can get rid of the if entirely, because toupper is defined to have no effect if the character was not lower case).

Lastly, there should be a null terminator at the end:

new_word[len] = 0;

NB. To be technically correct, the call to toupper should be: toupper((unsigned char)word[i]) -- check the documentation of toupper to understand more about this.

M.M
  • 138,810
  • 21
  • 208
  • 365