56492583
56492583

Reputation: 3

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

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

Upvotes: 0

Views: 163

Answers (2)

Madagascar
Madagascar

Reputation: 7345

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.

Upvotes: 1

Lundin
Lundin

Reputation: 214385

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.

Upvotes: 3

Related Questions