[Linux & gcc]

I'm taking C courses and pluralsight.com and I'm both getting an error with a program I got from one of their videos as well as having some trouble understanding something in the code

#include <stdio.h>
#include <ctype.h>

int main()
{
    char message[] = "Hello world!";

    for(char *p = message; *p; ++p)
    {
        if(isupper(*p)) *p = (char)tolower(*p);
        else if(islower(*p)) *p = (char)toupper(*p);
    }

    printf(message);
}

When I try to compile this program in gcc I get this error ->

stringpointer.c:8:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
     for(char *p = message; *p; ++p)
     ^
stringpointer.c:8:5: note: use option -std=c99 or -std=gnu99 to compile your code
stringpointer.c:14:5: warning: format not a string literal and no format arguments [-Wformat-security]
     printf(message);
     ^

Also I'm having trouble understanding the for loop because I don't see a condition that says, if we hit '\0' we are done.

When I try to compile this program in gcc I get this error

As the error message says, you need to supply the mentioned language options to make the code compile. Alternatively, if you want to make your code compile in C89 mode, you need to replace char *p = message with p = message and then put char *p; at the beginning of the function. I'd personally prefer using C99(or even C11) though.

Also I'm having trouble understanding the for loop because I don't see a condition that says, if we hit '\0' we are done.

The condition is *p. In C an expression counts as false if it evaluates to 0 and true otherwise and \0 is simply another way of writing 0. So the conditions *p, *p != 0 and *p != '\0' are all equivalent.

Thanks. Can you tell me how to make gcc compile in c99 or c11? Again, this is on a Linux system.

By providing the flags mentioned in the error message: -std=c99 for standard C99 mode or -std=gnu99 for C99 with GNU extensions. For C++11 mode just replace 99 with 11.

Your printf() function should be printf("%s", message); You could have used message as you did if you cast it to a const char* as in printf((const char*)&message[0]);, but the first example I provided is preferable.

It is indeed better to use printf("%s", message) than printf(message), but only because it prevents problems if the string contains characters that have special meaning to printf (like %), which isn't the case here anyway. As long as message does not include special characters, printf(message) will work fine.

Replacing message with (const char*)&message[0] makes no difference at all. Arrays decay to pointers to their first element implicitly and converting from a pointer to a const pointer also happens implicitly. There is no need for an explicit cast there.

#include <stdio.h>
#include <ctype.h>

main()
{
    char msg[] = "Hello World!";
    char* pmsg = msg;
    int i = 0;
    while (*(pmsg + i) != '\0')
    {
        if (isupper(*(pmsg + i)))
        {
            *(pmsg + i) = tolower(*(pmsg + i));
        }
        else if (islower(*(pmsg + i)))
        {
            *(pmsg + i) = toupper(*(pmsg + i));
        }
        i++;
    }
    putchar('\n');
    printf("The value is: %s", pmsg);
    getchar();
    return 0;
}
commented: Way more changes (without any explanations) than were necessary to fix the problem (which was already solved anyway), many of which are bad practice. -2
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.