Home > Software engineering >  why is my char array printing in lower case after i've converted it to uppercase?
why is my char array printing in lower case after i've converted it to uppercase?

Time:12-22

I'm trying to do the CS50 substitution problem. My code uses cs50.h library to handle strings.

Currently I have a function to convert a string to lower case, and one to convert it to uppercase:

string strtolower(string text)
{
    int length = strlen(text);
    for (int i = 0; i < length; i  )
    {
        text[i] = tolower(text[i]);
    }
    return text;
}

string strtoupper(string text)
{
    int length = strlen(text);
    for (int i = 0; i < length; i  )
    {
        text[i] = toupper(text[i]);
    }
    return text;
}

I have checked and they are returning the correct uppercase and lowercase string.

However when I call them in main as:

string key_upper = strtoupper(key);
string key_lower = strtolower(key);
printf("%s\n", key_upper);
printf("%s\n", key_lower);

I get (using key FFFFFFFFFFFFFFFFFFFFFFFFFF or ffffffffffffffffffffffffff, same result):

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff

if I print like this:

string key_upper = strtoupper(key);
string key_lower = strtolower(key);
printf("%s\n", key_upper);
printf("%s\n", key_lower);
printf("%s\n", strtoupper(key));

then I get:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff
FFFFFFFFFFFFFFFFFFFFFFFFFF

if I do:

printf("%s\n", key_upper);
printf("%s\n", key_lower);
printf("%s\n", strtoupper(key));
printf("%s\n", key_lower);
printf("%s\n", strtolower(key));

then I get:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff
FFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFF
ffffffffffffffffffffffffff

Does anyone know what is happening? Why so I get different results depending on whether I print the return of the function directly vs storing it in a variable first? Is it just some funk related to how cs50.h implements strings? How could I store the return in a variable successfully and call it later?

My full code: https://pastebin.com/pvUzT6iv

Tried:

printf("%s\n", key_upper);
printf("%s\n", key_lower);

Expected:

FFFFFFFFFFFFFFFFFFFFFFFFFF
ffffffffffffffffffffffffff

Got:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff

CodePudding user response:

This is the kind of misconception CS50 teaches. string is actually a char*, declared as typedef char* string which is incredibly bad practice.

So string strtolower(string text) is actually char* strtolower(char* text). And since you modify the passed string key, that one changes in each function call. key_upper is not a copy of it, just a pointer pointing at the same space as key.

The quick fix is something like this:

string key_upper = strdup(key);
string key_lower = strdup(key);
key_upper = strtoupper(key_upper);
key_lower = strtolower(key_lower);

The longterm solution is to drop out of CS50 and find better study material that actually teaches how string handling and pointers work in C.

CodePudding user response:

Q. why is my char array printing in lower case after i've converted it to uppercase?

Because this:

string key_upper = strtoupper(key);

converts all the characters (that weren't already and were lowercase alphabets) to uppercase.

string key_upper is pointing to a char * returned by the strtoupper function.

You then go on to declare another char * (under the hood, string is a char *) and initialising it with the pointer returned by the strtolower function.

Note that you passed the same char * to both the functions, and upper_key and lower_key are pointing at the same address. So if you change the memory contents of the address they were pointing to, the pointers would still be pointing to the same memory address. So this:

string key_lower = strtolower(key);

converts the characters back to lowercase.


 --------                -------- 
                                  
   ptr1    ---> A <---     ptr2    
                                  
 --------                -------- 

 --------                -------- 
                                  
   ptr1    ---> a <---     ptr2    
                                  
 --------                -------- 

See how they're still pointing to the same location? So now if you go on to print their contents, you'd get the same result. In this case, you called strtoupper first, so the output was all lowercase characters.

CodePudding user response:

It looks like the issue is with the way you are passing the key string to the strtolower and strtoupper functions. In C, strings are passed as pointers to the first character in the string, and any changes made to the string within the function will be reflected in the original string.

To fix this issue, you can pass a copy of the string to the functions instead of the original string. One way to do this is to use the strdup function, which creates a duplicate of a string and returns a pointer to the new string. Try this:

string strtolower(string text)
{
    int length = strlen(text);
    char* lower = strdup(text);
    for (int i = 0; i < length; i  )
    {
        lower[i] = tolower(lower[i]);
    }
    string result = lower;
    free(lower);
    return result;
}
  • Related