Home > Blockchain >  Why do I get "forbids converting a string constant to ‘char*’" in C ?
Why do I get "forbids converting a string constant to ‘char*’" in C ?

Time:03-22

I'm trying to invert the case manually, and I tried this:

char* invertirCase(char* str){
    int size = 0;
    char* iterador = str;
    char* retorno = str;

    while (*iterador != '\0') {

        if (retorno[size] < 96) {
            retorno[size] = *iterador   32;
        }
        else {
            retorno[size] = *iterador - 32;
        }
        iterador  ;
        size  ;
    }

    return retorno;
}

I'm trying to figure out where's the error, but I don't get it since I'm pretty new at C language.

CodePudding user response:

Why do I get "forbids converting a string constant to ‘char*’" in C ?

The error message means that you are trying to pass a string literal to the function.

String literals in C have types of constant character arrays that passed by value to functions are implicitly converted to the type const char *. And any attempt to change a string literal results in undefined behavior.

You could pass to the function a character array initialized by a string literal as for example

char s[] = "Hello";
std::cout << invertirCase( s ) << '\n';

In turn the function can be defined the following way

#include <cctype>

char * invertirCase( char *str )
{
    for ( char *p = str; *p;   p )
    {
        unsigned char c = *p;

        if ( std::isalpha( c ) )
        {
            if ( std::islower( c ) )
            {
                *p = std::toupper( c );
            }
            else
            {
                *p = std::tolower( c );
            }
        }
    }

    return str;
}

or

char * invertirCase( char *str )
{
    for ( char *p = str; *p;   p )
    {
        unsigned char c = *p;

        if ( std::islower( c ) )
        {
            *p = std::toupper( c );
        }
        else if ( std::isupper( c ) )
        {
            *p = std::tolower( c );
        }
    }

    return str;
}

CodePudding user response:

There is no "string constant" in the code you have shown, so it would have to be at the call site, ie if you were doing something like invertirCase("string"), which will not work, for 2 reasons:

  1. since C 11 onward, C does not allow a string literal to be assigned to a char* pointer. This is because a string literal is a const char[] array, and you can't have a pointer-to-non-const pointing at const data. So you need to use const char* instead.

  2. however, that will still not work, because invertirCase() modifies the data pointed at by its str parameter. You can't modify the data of a string literal.

So, you will have to make a copy of the string literal into writable memory. You can either make that copy at the call site, eg:

char str[] = "string";
invertirCase(str);

Or, you can make the copy inside of invertirCase() (but then the caller will have to free the copy when done using it), eg:

char* invertirCase(const char* str){
    int size = 0;
    char* retorno = new char[strlen(str) 1];

    while (*str != '\0') {
        retorno[size] = (*str < 96) ? (*str   32) : (*str - 32);
        str  ;
        size  ;
    }

    retorno[size] = '\0';

    return retorno;
}
char *str = invertirCase("string");
...
delete[] str;

Otherwise, simply don't use char* at all. Use std::string instead, eg:

std::string invertirCase(const std::string &str){
    std::string retorno;
    retorno.reserve(str.size());
    for(char ch : str) {
        retorno.push_back((ch < 96) ? (ch   32) : (ch - 32));
    }
    return retorno;
}
std::string str = invertirCase("string");
...
  • Related