-2

I'm trying to convert a char array to upper case in C. But it still prints out in lower case. The logic in conversion function looks okay to me. I don't know if the problem could be that the input I'm passing to this function is member of a structure variable.

This is the structure whose member I'm passing to conversion function:

typedef struct AESParams {
   unsigned char output[192];
} AESParams;

My conversion fucntion is shown below:

void stringUpr(char *s)
{
    int i=0;
    while(s[i]!='\0')
    {
        if(s[i]>='a' && s[i]<='z'){
            s[i]=s[i]-32;
        }
        ++i;
    }
}

I call conversion function as follows:

AESParams parameters;
stringUpr(parameters.output);

If I print the output after calling "stringUpr" function, the value is still in lower case. Can anyone tell me what might be causing the issue here?

TIA...

Update: Code that writes value to output.

EVP_EncryptUpdate(&ctx, parameters->output, &outLen, input, length); 
// This call happens in some other file. parameters is passed to the function that calls this function and after computation parameters is passed back to the place where I'm calling stringUpr().

I'm confident that this lines works and it gives the correct results after computation. It's just that I want to take this value and convert to upper case and write to a file.

ARao
  • 261
  • 4
  • 14
  • 6
    Why cant u use toupper? – Sanjeev S Mar 20 '19 at 14:24
  • 1
    Post code that set and prints `parameters`. – chux - Reinstate Monica Mar 20 '19 at 14:27
  • 3
    `parameters` is a typedef and a variable? You code [works](https://onlinegdb.com/rJsHCaJ_N). – KamilCuk Mar 20 '19 at 14:28
  • 1
    [MCVE], please. – Eugene Sh. Mar 20 '19 at 14:29
  • 1
    Attention, that is not the reason of your problem, but if there is no `"\0"` in your char array, you will write somewhere in your memory. @chux Yes I also belive, that the probleme is there. – NelDav Mar 20 '19 at 14:30
  • I've now updated my code... Please see the main question for updates. But still I see only lower case... – ARao Mar 20 '19 at 14:39
  • the update isn't helping, you need to provide code that we can copy and paste into a file, compile, run, and reproduce the problem you're describing. That still is not in the question – yano Mar 20 '19 at 14:39
  • @Patrick ofcourse it is. I am not sure if it is normal, but I would either check if i – NelDav Mar 20 '19 at 14:41
  • In your `EVP_EncrypyUpdate` call, should `parameters->output` be `parameters.output` (a typo), or is this a different `parameters` variable? – Ian Abbott Mar 20 '19 at 14:41
  • EVP_EncryptUpdate() is what writes the value into output variable... It's an OpenSSL call not something I implemented... – ARao Mar 20 '19 at 14:41
  • EVP_EncryptUpdate() `out` parameter can have bytes ranges from `\0` to `\255`, you cannot treat it like "a C string" and assume that only the last byte will be `\0` also, the length of the valid values in out are in outlen, and are *not* marked with `\0`. Not sure what you are trying to do – Ahmed Masud Mar 20 '19 at 14:46
  • I populate a structure called parameters and pass to a function which calls OpenSSL functions. After computation parameters is returned back. The values are perfectly correct. All I'm trying to do is just convert the output to upper case once parameters is passed back to calling function... – ARao Mar 20 '19 at 14:48
  • 2
    Since you have two different variables called `parameters` (one is a struct and the other is a pointer), are you sure you are passing the correct thing to `strUpper`? – Ian Abbott Mar 20 '19 at 14:48
  • your strUpper function works just fine ... you just don't understand what's happening inside `out` – Ahmed Masud Mar 20 '19 at 14:49
  • Yes, because there is only parameters in the function where I'm calling stringUpr(). – ARao Mar 20 '19 at 14:49
  • 1
    Have a look at https://onlinegdb.com/BkJDmA1dV – Ahmed Masud Mar 20 '19 at 14:51
  • The problem is not in the code you have posted. Please post a [mcve]. – Ian Abbott Mar 20 '19 at 14:55
  • I cannot post the code I'm afraid... Thank you all for the helpful comments... I'll look at what I'm missing or what's the culprit in other parts of the code... I definitely did get some helpful comments in this post... – ARao Mar 20 '19 at 14:56
  • 1
    I think you just aim for `void stringUpr(char *s, size_t len) { while(len--) { *s = toupper(*s); s++; } }` and call with `stringUpr(parameters.output, sizeof(parameters.output));` – KamilCuk Mar 20 '19 at 14:58
  • 1
    Now that I'm sure the conversion function works fine (with all your help), I looked for the piece of code writing into file and I saw this: fprintf(outputStream, "%02x", hexString[i]); After fixing this line, my issue seems to be solved now... – ARao Mar 20 '19 at 15:31

1 Answers1

2

Your program assumes that it's running using an ASCII character set, which is not guaranteed. Use the standard functions defined in ctype.h

void stringUpr(char* s)
{
    int i = 0;
    while(s[i] != '\0')
    {
        s[i++] = toupper((unsigned char)s[i]);
    }
}
PC Luddite
  • 5,883
  • 6
  • 23
  • 39
  • 2
    The `if (islower(s[i])` is redundant since `toupper(c)` returns the uppercase representation of `c` if it exists in the current locale and returns `c` otherwise. – Simon Doppler Mar 20 '19 at 14:45
  • Also if the char array is not ASCII, it can't be, that the content of the array is the same after subtract 32 from some characters. The only way would be, if some letters are not between 'a' and 'z' – NelDav Mar 20 '19 at 14:45
  • No need to check with `islower()` as `toupper()` won't change other char values. – Andrew Henle Mar 20 '19 at 14:45
  • 1
    @Ahrtaler `toupper()` is not an ASCII-only function. It converts lower-case letters to the appropriate upper-case letter regardless of the execution character set in use. – Andrew Henle Mar 20 '19 at 14:47
  • I never said, that toupper() is an ASCII only function – NelDav Mar 20 '19 at 14:48
  • @SimonDoppler I was mimicking the original code. I adjusted to remove that check. – PC Luddite Mar 20 '19 at 14:49
  • You need a cast to avoid UB on negative `char`s: `toupper((unsigned char)s[i]);`. – HolyBlackCat Mar 20 '19 at 14:49
  • 1
    @Ahrtaler Then why post a comment about "subtract 32 from some characters". That's an ASCII-only case-conversion from lower- to upper-case. – Andrew Henle Mar 20 '19 at 14:50
  • @HolyBlackCat why would that be undefined behavior? `toupper` takes an `int`. `char` is implicitly converted. – PC Luddite Mar 20 '19 at 14:53
  • @AndrewHenle because the question was not how to convert lowercase charecter into uppercase character. It was why amys solution don't make that. I wanted to point out, that even if non ASCII is used, amys code would change the content of the array. Ofcourse it wouldn't work as expected. But it would change the array. – NelDav Mar 20 '19 at 14:55
  • 4
    @PCLuddite https://en.cppreference.com/w/cpp/string/byte/toupper - *"Like all other functions from ``, the behavior of `std::toupper` is undefined if the argument's value is neither representable as `unsigned char` nor equal to `EOF`. To use these functions safely with plain `char`s (or `signed chars`), the argument should first be converted to `unsigned char`"* – HolyBlackCat Mar 20 '19 at 14:56
  • @HolyBlackCat done. although you may want to find a C source. the semantics can be very different between the two languages even if it happens to be true in both in this case. – PC Luddite Mar 20 '19 at 16:14
  • @PCLuddite I probably should've linked this instead: https://en.cppreference.com/w/c/string/byte/toupper This page doesn't have the explicit remark about the cast, but like the previous page it says that *"If the value of ch is not representable as unsigned char and does not equal EOF, the behavior is undefined."* – HolyBlackCat Mar 20 '19 at 16:17
  • Why not `for ( int i = 0; s[i]; i++ ) s[i] = toupper( (unsigned char)s[i] );` – i486 Mar 20 '19 at 17:52
  • @i486 if I wrote this from scratch, I would probably write it similar to that. But I'm matching the OP's style, which isn't any more or less valid than what you've written. – PC Luddite Mar 20 '19 at 18:01
  • The line in the while loop `s[i++] = toupper((unsigned char)s[i]);` is *absolutely* incorrect. It seems that the original program by @PCLuddite was correct. But many untested edits made it incorrect. It should be `s[i] = toupper((unsigned char)s[i++]);` instead. I've suggested an edit. – Nirav Nov 26 '19 at 16:15