1

I'm trying to perform case insensitive strcmp on two C-style strings.

I have a function to convert C-style strings to lowercase.

char* ToLowerCase(const char* str)
{
    char buffer[strlen(str)];
    for (int i=0; i<strlen(str); ++i)
        buffer[i] = char(tolower(str[i]));
    return buffer;
}

One string comes from function char* GetMyString(int i), and the second is in array of C-style strings char* myStrings[5].

So assuming that both GetMyString(0) and myString[0] both return "TEXT"

strcmp(ToLowerCase(GetMyString(0)), ToLowerCase(myStrings[0]));

compares strings like "mytextxaogs5atx" "mytextxabs5atx" (some random text gets added...)

whilst

strcmp(GetMyString(0), myStrings[0]);

works just fine, so that I assume there's nothing to do with the null termination as some of you might think.

What is wrong with my code? Did I miss something? I've looked at many questions about tolower but none of them were able to help with my problem.

Treycos
  • 7,373
  • 3
  • 24
  • 47
Ilo
  • 35
  • 6
  • You have undefined behavior, that's why. – πάντα ῥεῖ Oct 26 '16 at 12:14
  • If you have to use such function for a serious project, go for boost library to avoid different character set issues. – seccpur Oct 26 '16 at 12:15
  • You are returning a buffer which becomes undefined after return. what means `char(tolower(str[i]))`? `tolower(str[i])` should be enough – Holger Oct 26 '16 at 12:16
  • I'm just trying to make it work for past 2 days... I'm guessing something wrong with my buffer. I also tried doing this char buffer[strlen(str)]{}; but that also didn't help – Ilo Oct 26 '16 at 12:17
  • 2
    "I'm trying to perform case insensitive strcmp on two C-style strings." -- Then at no point do you need to store the *whole* string as lowercase. You only need to convert the characters you're comparing at the moment to lowercase. Do that, and you no longer need an answer to this question. –  Oct 26 '16 at 12:18
  • @Holger, I'm casting it to char, since tolower returns me an int but my function should return a char array. So I either do (char) or char() – Ilo Oct 26 '16 at 12:19
  • @hvd, nice! I'll try that right now and convert my ToLowerCase function to CompareCStrings! I'll get back later, thanks! – Ilo Oct 26 '16 at 12:21
  • There's a function to do case insensitive comparisons. On Posix systems you have `strcasecmp`. Under MSVC, use `stricmp` instead. – dbush Oct 26 '16 at 12:21
  • @πάνταῥεῖ Although the error in this question matches exactly the problem described in the famous duplicate, I think OP's question is less about "what's broken" and more about "how do I fix it". – Sergey Kalinichenko Oct 26 '16 at 12:34
  • @dbush I'm using MinGW so none of these ... – Ilo Oct 26 '16 at 12:34
  • @dasblinkenlight yep! I didn't even think of that, so every time I did a wrong search on "tolower". Maybe this thread will help someone else too! – Ilo Oct 26 '16 at 12:39
  • @hvd you are genius. Thank you again! That's perfect :) – Ilo Oct 26 '16 at 12:39

2 Answers2

3

You cannot return local variables from functions, so returning buffer is undefined behavior.

You have three choices to make this API:

  • Take a non-const str and perform modifications in place
  • Take a buffer for the string from the caller, and either assume that it has sufficient length, or also take the size of the buffer (much safer)
  • Return a malloc-ed string. This would require the caller to free the result. Should you decide to go this route, note that you need to malloc strlen(str)+1 bytes to accommodate null terminator.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2
return buffer;

You return a pointer to a variable that's local to ToLowerCase, the pointer will point to garbage after the call, resulting in undefined behaviour when trying to dereference the pointer. Either change the str itself or dynamically allocate the memory for buffer.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122