String to uppercase?

Hello guys!
I have a little questions here... I wrote this strtouppercase function which return a pointer to char but I would like to know if there is a shorter version with pointer notation or if it could be improved in any ways:

1
2
3
4
5
6
7
8
9
10
11
12
13
char *strtoupper(char *str){
    int i = 0;
    char *p = (char*) malloc(strlen(str) * sizeof(char));
    while(str[i]){
        if((str[i] >= 'a') && (str[i] <= 'z'))
            p[i] = str[i] + 'A' - 'a';
        else
            p[i] = str[i];
        ++i;
    }
    p[i] = '\0';
    return p;
}


I tried using a *(p+i) kind of syntax and this worked but when I try something like:

1
2
3
4
5
6
7
8
9
10
11
char *strtoupper(char *str){
    char *p = (char*) malloc(strlen(str) * sizeof(char));
    while(*str++){
        if((*str >= 'a') && (*str <= 'z'))
            *p++ = *str + 'A' - 'a';
        else
            *p++ = *str;
    }
    *p = '\0';
    return p;
}


the function doesn't return the correct string. Why is it? I think I might have some missunderstanding on pointer notation or I'm a bit confused with pointers.
Thank you very much in advance!

P.S: BTW this is plain C not C++ but I hope you can help please :P
Last edited on
The issue of the second one is: (*p)++ or *(p++)? Depends on the precedence. So it's certainly not recommended to use the second.

You can improve it somewhat with 'for':
1
2
3
4
5
6
7
8
9
10
11
12
char *strtoupper(char *str){
    int i = 0;
    char *p = (char*) malloc((strlen(str) + 1) * sizeof(char)); // EDIT: + 1 important!
    for(; str[i]; ++i){
        if((str[i] >= 'a') && (str[i] <= 'z'))
            p[i] = str[i] + 'A' - 'a';
        else
            p[i] = str[i];
    }
    p[i] = '\0';
    return p;
}
Last edited on
The second one was the issue, could you please elaborate why isn't it recommended to use the second? And how could I go about writing it with (*p)++? Thank you! And thanks for the EDIT! :)
Last edited on
this (*p)++ increases the content of p (pafter == pbefore but the content (*p) will be e.g. 'A' -> 'B')
this *(p++) increases the pointer and returns the content (pafter == pbefore + 1)

Modifying a variable during an assignment isn't recommended because well, you experienced it yourself: it's to hard to predict what's the result.
It's perfectly predictable what the result is. *p++ makes p point to the next character, so it shouldn't come as a shock that the loop body handles the wrong character.
Ok I forgot 2 further option:

Is it p++; (*p) = ...; or (*p) = ...; p++;

The point is that it's hard to predict
No, those two variants just show the difference between pre-increment and post-increment (i.e. *++p and *p++).
If you know the difference, the code is rather obvious.

Edit: Still, I'm not advocating this over the first variant with separate increment, as that one is more readable.
And the for variant is still better. Oh, and str[i]!='\0'
Last edited on
Ok thank you very much to both of you :)
Then the best way would be just this:
1
2
3
4
5
6
7
8
9
10
11
12
char *strtoupper(char *str){
    int i = 0;
    char *p = (char*) malloc((strlen(str) + 1) * sizeof(char));
    for(; str[i] != '\0'; ++i){
        if((str[i] >= 'a') && (str[i] <= 'z'))
            p[i] = str[i] + 'A' - 'a';
        else
            p[i] = str[i];
    }
    p[i] = '\0';
    return p;
}

right?
Thank you again! :P
closed account (DSLq5Di1)
For your code above it would be wise to have the user provide a char* out variable, if only to make it explicit that memory is being allocated and must be freed afterward.

Here is another example, rather than allocating memory for another string I am modifying the original. This has its own cavets and I wouldn't recommend using any of these examples for anything other than learning.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>

using namespace std;

const char* toUpper(const char* str)
{
    for (char* cp = const_cast<char*>(str); char c = *cp; cp++)
    {
        if (c >= 'a' && c <= 'z')
            *cp = c - 'a' + 'A';
    }
    return str;
}

int main()
{
    char str1[] = "Hello, ";
    string str2("world!");

    cout << toUpper(str1) << toUpper(str2.c_str());


    cin.sync();
    cin.ignore();

    return 0;
}

http://stackoverflow.com/questions/735204/convert-a-string-in-c-to-upper-case
Topic archived. No new replies allowed.