Thread: Returning a String

  1. #1
    C Beginner
    Join Date
    Dec 2011
    Location
    Portugal
    Posts
    187

    Returning a String

    Hello everyone,
    I'm trying to return a string to then call it on main function.

    My code is the following :

    Code:
    const char* coiso(int chave){
        char str [50];
        sprintf(str,"%d",chave);
        char txt[50] = ".txt";
        strcat(str,txt);
        return str;
    }
    
    
    int main ()
    {
        const char* info = coiso(8);
        printf("%s",info);
    }
    If I do a printf("%s",str) in coiso function it works but the following code doesn't work.

    Any idea why ? :/

    Thanks!

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    RETURN OF LOCAL VARIABLE!!!!!!!!!!!!!!!!!!!!!!!!!
    You should use malloc for this kind of operations Or declare the str as static. However, I would go for malloc, if I were you
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    C Beginner
    Join Date
    Dec 2011
    Location
    Portugal
    Posts
    187
    Quote Originally Posted by std10093 View Post
    RETURN OF LOCAL VARIABLE!!!!!!!!!!!!!!!!!!!!!!!!!
    You should use malloc for this kind of operations Or declare the str as static. However, I would go for malloc, if I were you
    Declared str as static and worked just fine.
    Thanks bud!

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    You are welcome. However, I suggest you take a look at your notes/tutorial/book about local variables and their scope. That's the problem. str was a local variable, function terminated, thus all local variables are killed, thus str is dead outside the function.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by DeanWinchester View Post
    Declared str as static and worked just fine.
    Are you aware that your function will always return the same object if you use static?
    Code:
    #include <stdio.h>
     
    const char *coiso(int chave)
    {
        static char str[50];
        sprintf(str, "%d.txt", chave);
        return str;
    }
    
    int main(void)
    {
        const char *info = coiso(8);
        printf("info: %s\n", info);
        
        // This will also change the string "info" points to
        printf("second call: %s\n", coiso(99));  
    
        printf("info: %s\n", info);
        return 0;
    }
    Output:
    Code:
    info: 8.txt
    second call: 99.txt
    info: 99.txt
    Bye, Andreas

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by std10093 View Post
    RETURN OF LOCAL VARIABLE!!!!!!!!!!!!!!!!!!!!!!!!!
    More precisely, it is returning the address of a local variable, that ceases to exist when the function returns (since the name of an array becomes a pointer in this context).

    Returning the value of a local variable is fine.

    Quote Originally Posted by std10093 View Post
    You should use malloc for this kind of operations Or declare the str as static. However, I would go for malloc, if I were you
    Maybe. It depends.

    Declaring str as static makes the function non-reentrant.

    Using malloc() requires the caller to free() the pointer and causes a memory leak if that is forgotten. Not a problem for small one-off programs. A real problem for long running programs that call the functions multiple times.

    The real problem is that there is no direct way of returning an array.

    If the length of the array is fixed (i.e. known to the compiler, not dependent on runtime data) it is posssible to do this.
    Code:
    #include <stdio.h>
    
    struct TempString
    {
          char data[50];
    };
    
    struct TempString coiso(int chave)
    {
        struct TempString temp;
        sprintf(temp.data,"%d.txt",chave);
        return temp;
    }
     
     
    int main ()
    {
        struct TempString info = coiso(8);
        printf("%s",info.data);
    }
    As to whether that is better or not ..... that depends!
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by grumpy View Post
    As to whether that is better or not ..... that depends!
    Most experienced C programmers expect that if a function returns
    a char * to a new string, that string will be allocated with malloc.
    If you can't call malloc for some reason, the normal way is to pass in the buffer.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Most experienced C programmers expect that if a function returns
    a char * to a new string, that string will be allocated with malloc.
    First I think you're making too many assumptions about what C programmers expect.

    Secondly look at many of the standard functions defined in string.h, most don't return a malloced pointer but return the address of one of the parameters. Look at strcpy() and memmove() for examples.

    Jim

  9. #9
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    If the signature of the coiso() function is given and you are asked to implement its body, then assuming the signature is the one you provide in the 1st post ...

    Code:
    const char *coiso(int chave);
    then I guess your best bet would be to allocate the string inside the function, populate it using the exact size it needs (a wild guess, because of the const ), and then return it.

    So, assuming chave is expressed as a base-10 integer, and that negative values are acceptable, but 0 is not, then it could be something like this...

    Code:
    const char *coiso( int chave )
    {
        const char *const ending = ".txt";   /* needless const nitpicking :P */
        char       *ret = NULL;              /* cstring to be returned */
        size_t     sz = strlen(ending) + 1;  /* init to ending's size */
        int        ndigits = 1;              /* count of chave's digits */
        int        temp = chave;
    
        /* sanity check */
        if ( 0 == chave ) {
            return NULL;
        }
    
        /* count digits in chave (assuming chave is expressed in base-10) */
        while ( 0 != (temp /= 10) ) {
            ndigits++;
        }
    
        /* allocate mem for ret */
        sz += (chave > 0) ? ndigits : ndigits+1;    /* +1 for minus sign, if any */
        ret = malloc( sz /* * sizeof(char) */ );
    
        /* populate ret */
        if ( ret ) {
            sprintf( ret, "%d%s", chave, ending );
        }
    
        return (const char *)ret;
    }
    What puzzles me though a bit with that signature, is the const qualifier for the returned string.

    Since the returned string should be freed by the caller when done using it, that const qualifier forces us to either explicitly cast the string in the caller context when creating it via coiso()...

    Code:
    int main( void )
    {
        char *info = (char *)coiso(1223);
        ...
        free( info );
        return 0;
    }
    or define info as (const char *) and then explicitly cast it to (char *) when passing to free()...

    Code:
    int main( void )
    {
        const char *info = coiso(1223);
        ...
        free( (char *) info );
        return 0;
    }
    otherwise the compiler will complain (usually with just a warning) when trying to free the string.

    It would be better if the const qualifier were missing, but if you must use it, you must use it

    On the other hand, if you are free to choose your own signature for the function, you can do whatever you like... even making it void and pass to it a pre-allocated buffer to be filled-in.

    @jimbluberg:

    Sure, but both those functions expect pre-allocated buffers to get passed to them.

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Malcolm McLean View Post
    Most experienced C programmers expect that if a function returns
    a char * to a new string, that string will be allocated with malloc.
    I've seen a lot of "experienced" C programmers make that claim. Very few consistently get their code right as a result, though.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by jimblumberg View Post
    First I think you're making too many assumptions about what C programmers expect.

    Secondly look at many of the standard functions defined in string.h, most don't return a malloced pointer but return the address of one of the parameters. Look at strcpy() and memmove() for examples.

    Jim
    None of them do. The string library is independent of the memory allocation library. So strdup() is not a standard function.

    Whilst strcpy does return a pointer, this is for historical reasons. Originally the designers of C thought that people would write a lot of code in the style strcat(strcat(strcpy(buff, "FRED"), " "), "BLOGGS")). In fact that never caught on, and the return value is almost always ignored.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 09-06-2011, 02:59 PM
  2. Replies: 10
    Last Post: 12-04-2010, 12:04 AM
  3. returning a string value???
    By mero42 in forum C++ Programming
    Replies: 11
    Last Post: 04-03-2005, 11:01 PM
  4. returning a string
    By StinkyRyan in forum C++ Programming
    Replies: 3
    Last Post: 06-17-2004, 08:26 AM
  5. returning string value
    By vn1 in forum Windows Programming
    Replies: 10
    Last Post: 06-06-2002, 07:10 AM