2

I am trying to make a function toLowerCase(char *string) but I am unable to make it work properly.

This is my code

void toLowerCase(char *string) {
    int i = 0;
    while (*(string+i) != '\0') {
        if (*(string+i) >= 'A' && *(string+i) <= 'Z') {
            *(string+i) = *(string+i) + 32;
        }
        i++;
    }
    printf("%s", string);
}

I am trying to loop through the string that is a char * pointer by accessing each element using *(string + i) and using ASCII to convert to Lowercase.

I am new here, if this was answered before I am sorry, but I am asking because I couldn't find a specific solution to my problem. I've tried what's in this thread: Converting Char * to Uppercase in C but it didn't work for me either.

EDIT: This is how I call my function

int main() {
    toLowerCase("HELLO WORLD");
    return 0;
}

EDIT 2: So, I did this, as showed by PSkocik. And it worked, but I don't know why it works like this. Will the toLowerCase() function work with any char * pointer? even if I don't declare it as char array?

This also fixes the problem that Vlad from Moscow pointed out that I am using a string literal

#define T 100
int main() {
    char string[T] = "HELLO WORLD";
    toLowerCase(&string);
    return 0;
}

EDIT 3: Thank you very much for your help! I wasn't expecting to get help so quickly! I didn't know what a string literal was!

Thank you very much for your time

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
David Choi
  • 145
  • 1
  • 10
  • 3
    It seems you are passing a string literal to the function. Show how you call the function. – Vlad from Moscow May 31 '20 at 20:56
  • Works fine for me: https://gcc.godbolt.org/z/X4YA5B . `*(string+i)` instead of `string[i]` is slightly unusual and I'd at least replace the magic constant `32` with `('a'-'A')`, but it does work as is. – Petr Skocik May 31 '20 at 21:06
  • What is the error you're getting? Is it a segmentation fault? – Daniel Walker May 31 '20 at 21:09
  • I just added where I call the function. I get no error, It gets stuck after the ''' *(string+i)= *(string+i)+32; ''' line and returns -1073741819 – David Choi May 31 '20 at 21:13
  • What returns that value? When you say that it gets stuck, do you mean that the loop never ends? – Daniel Walker May 31 '20 at 21:15
  • The compiler returns that value. When I say it gets stuck I mean that it doesn't go further than that, because I added a '''print("something");''' after that line and the compiler didn't print it once. But if the loop never ended it would have printed it multiple times. Maybe it doesn't even detect the if condition as true, so I guess in a way, the loop never ends. – David Choi May 31 '20 at 21:18

4 Answers4

2

C string literals are typed char[] for historical reasons, but they're effectively char const[]—you are not allowed to modify them.

Fortunately C makes it very easy to create a writable copy by letting you initialize a writable char array with a string literal:

#include <stdio.h>
void toLowerCase(char* string)
{
    int i=0;
    while(*(string+i)!= '\0'){
        if (*(string+i) >= 'A' && *(string+i)<='Z'){
            *(string+i)= *(string+i)+32;
        }
        i++;
    }
}
int main()
{
     char string[]="HELLO WORLD";
     toLowerCase(&string[0]);
     puts(string);
    //prints: hello world
}

https://gcc.godbolt.org/z/X4YA5B

(*(string+i) instead of string[i] is slightly unusual and I'd at least replace the magic constant 32 with ('a'-'A'), but the callee's code is otherwise OK.)

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • 1
    This should be a comment. – Vlad from Moscow May 31 '20 at 21:05
  • 1
    Why write `toLowerCase(&string[0]);` instead of `toLowerCase(string);`? – chqrlie May 31 '20 at 21:30
  • @chqrlie because it looks more serious – 0___________ May 31 '20 at 21:32
  • 1
    @P__J__: not as serious as `toLowerCase(&0[string]);` or `toLowerCase(0[&string]);` :) – chqrlie May 31 '20 at 21:35
  • @chqrlie agreed – 0___________ May 31 '20 at 21:35
  • @chqrlie LOL. I've simply been liking to write it like that lately. I like to see an `&` where an argument can be changed in the callee. – Petr Skocik May 31 '20 at 21:38
  • @PSkocik: I understand your approach, but it makes `string[0]` stand out as if `ToLowerCase` was going to modify this `char` only. When passing an array, it is more idiomatic to pass the array name or a pointer value, as in `printf("%s\n", string);`, so the `&...[0]` periphrasis is unexpected and somewhat counterproductive. – chqrlie May 31 '20 at 21:46
  • @chqrlie `puts("%s\n",string)` is different -- the array won't get modified in the call. I wouldn't do the "serious" thing there either. :) It's just a style I use. – Petr Skocik May 31 '20 at 22:06
  • @PSkocik: how about `fgets(buf, sizeof buf, fp)`? or `snprintf(buf, sizeof buf, ...)`? Do you use the serious version for those too? – chqrlie May 31 '20 at 22:30
1

You are passing a string literal to the function toLowerCase and then trying to change it using *(string+i)= *(string+i)+32;.

You should contain Hello World in a variable and then pass it to the function if you want to change the case of characters.

Agrudge Amicus
  • 1,033
  • 7
  • 19
1

You may not change string literals. Any attempt to change a string literal results in undefined behavior.

From the C Standard (6.4.5 String literals)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

So instead of this call

toLowerCase("HELLO WORLD");

use at least

char s[] = "HELLO WORLD";

toLowerCase( s );

Pay attention to that it will be much better when the function will return pointer to the modified string and will not output the string. It is the caller of the function that will decide whether to output the modified string.

So define the function like

char * toLowerCase( char *string )
{
    // ...
    return string;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

toLowerCase("HELLO WORLD"); => toLowerCase((char[]){"HELLO WORLD"}); as changing the strings literal is an UB.

your function should return the string for easy use as parameter.

char *toLowerCase(char* string)
{
    int i=0;
    while (string[i])
    {
        if (string[i] >= 'A' && string[i] <= 'Z')
        {
            string[i] += 'a' - 'A';
        }
        i++;
    }
    return string;
}



int main() 
{
    puts(toLowerCase((char[]){"HELLO WORLD"}));
    return 0; 
}
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
0___________
  • 60,014
  • 4
  • 34
  • 74