3

I have a struct:

typedef struct entry {
char *surname;
int house_no;
char *postcode;
} BEntry;

and a function to convert strings to upper case:

void toUpper(char *str){
    while (*str != '\0')
    {
        *str = toupper(*str);
        str++;
    }
}

and in my main function I assign values to the struct members and want to convert the surname to upper case:

mentry->surname = "bob";
mentry->house_no = 17;
mentry->postcode = "GK116BY";
toUpper(me->surname);

What is the correct way to convert a string to upper case by passing a char pointer to a function like this? My program is returning a segmentation fault. Any help is most appreciated, thanks.

Highway62
  • 800
  • 1
  • 10
  • 25
  • What is wrong with what you have? – Scott Hunter Nov 06 '14 at 18:41
  • 7
    `"bob"` is a string literal present in read only location. You can't modify it. Copy and then modify it. – Mahesh Nov 06 '14 at 18:41
  • The problem is the assignment of `"bob` -- a constant string -- to `surname` which is of type `char*`. You should at least have got a warning that you this is ignoring const'ness in the assignment. Always use full warnings. One way of solving it is by running `char * strdup(const char s)` as part of the assignment. You then get ` char *` that you can modify. Don't forget to release the memory when you are through. – Dov Grobgeld Nov 06 '14 at 18:43

3 Answers3

3

Your toUpper() implementation should work fine. However, you should pay attention to the warnings from your compiler (or turn up the warning levels if you didn't get any -- you should see something when you assigne a string literal to a char * like that). String literals are const, i.e. they cannot be modified. When you try to write to them, this will cause the segmentation fault you are seeing.

You need something like:

mentry->surname = malloc(4);
strcpy(mentry->surname, "bob");

or the more convenient, but not part of the C standard way:

mentry->surname = strdup("bob");

And of course, be sure to call free() later, either way.

FatalError
  • 52,695
  • 14
  • 99
  • 116
  • String literals are not `const` in C. I think it's wrong of the standard to define it that way but unfortunately it is so. So OP won't get a warning. On gcc you can force warnings for that case with `-Wwrite-strings`, in that case the program violates the standard but it is imho better this way. – Patrick Schlüter Nov 07 '14 at 13:32
  • @tristopia: I thought for sure they were but I took a look and you're absolutely correct. It does say modifying them is undefined behavior, which begs the question why they're not... but yeah, so no obvious warning from this then. – FatalError Nov 07 '14 at 15:13
1

String literals like "Hello, World!" are not writeable. Either duplicate the string literal:

hw = strdup("Hello, World!");

or declare a char[] variable and initialize it to a string literal. As a special case, string literals used this way are writeable:

char hw[] = "Hello, World!";
fuz
  • 88,405
  • 25
  • 200
  • 352
  • 1
    Literals aren't writeable, also in the 2nd case you show it's not the literal that will be writable but the content of `hw`. – alk Nov 06 '14 at 18:44
  • @alk That's because it isn't a literal; I know. I wrote the answer in this slightly incorrect way because it's less complicated to formulate and easier to understand than the correct version. – fuz Nov 06 '14 at 18:49
  • 1
    In both cases `"Hello, World!"` **is** a literal. In both cases it is **not** writable. – alk Nov 06 '14 at 18:51
  • @alk Technically yes, but it's a special case where the contents of the string literal are implicitly initializing the array (cf. ISO 9899:2011§6.7.9.14). You could see this as if the string literal was actually writeable from a programmers perspective. I know it's not quite correct, but easier to understand. – fuz Nov 06 '14 at 19:39
1

The easiest way of converting char * to lowercase or uppercase in c, is by using strdup

#include <string.h>

char    *to_uppercase(char *s)
{
    int i = 0;
    char    *str = strdup(s);

    while (str[i])
    {
        if (str[i] >= 97 && str[i] <= 122)
            str[i] -= 32;
        i++;
    }
    return (str);
}
Junius L
  • 15,881
  • 6
  • 52
  • 96