strings and functions

Discussion in 'C Programming' started by c_monty, Aug 22, 2003.

  1. c_monty

    c_monty Guest

    I am used to Delphi and VB, where functions can return strings. I
    recently starting learning C and my findings are that you can have
    external functions build strings, but the function cannot return the
    string itself, rather, it needs to update a variable that is an array or
    points to an array. Correct?



    Below is a 'simple' test to work with a string that was created in an
    external function (and external file). Based on the result I get (_@),
    I know I don't fully "get it" yet. Any help would be appreciated.



    //MAIN.C

    #include<stdio.h>



    main()

    {

    char *data_from_function;



    my_function(data_from_function);

    printf("Data results from My Function: %s\n");

    }



    //MYFUNCTION.C



    my_function(char *strData)

    {

    strData = "HELLO WORLD\n";

    }



    (Linux 9 i386)

    #gcc main.c myfunction.c

    #./a.out



    Data results from My Function: _@


    --
    Posted via http://dbforums.com
     
    c_monty, Aug 22, 2003
    #1
    1. Advertising

  2. c_monty wrote:
    > I am used to Delphi and VB, where functions can return strings. I
    > recently starting learning C and my findings are that you can have
    > external functions build strings, but the function cannot return the
    > string itself, rather, it needs to update a variable that is an array or
    > points to an array. Correct?
    >
    > Below is a 'simple' test to work with a string that was created in an
    > external function (and external file). Based on the result I get (_@),
    > I know I don't fully "get it" yet. Any help would be appreciated.
    >
    > //MAIN.C
    >
    > #include<stdio.h>
    > main()


    The main() function should have a return type:
    int main(void)


    > {
    > char *data_from_function;
    > my_function(data_from_function);
    > printf("Data results from My Function: %s\n");


    Perhaps this should have been:
    printf("Data results from my_function: %s\n",
    data_from_function); /* you forgot this */
    > }


    > //MYFUNCTION.C
    > my_function(char *strData)
    > {
    > strData = "HELLO WORLD\n";
    > }


    Pointers are passed by value in C.
    If you want to change a pointer, pass the address
    or a pointer to the pointer:
    void my_function(char * * strData)
    {
    *strData = "Hellow World\n";
    }

    or copy the data to the location of the original
    array:
    void my_other_function(char * strData)
    {
    strcpy(strdata, "Hello again.\n");
    return;
    }

    int main(void)
    {
    char string_one[640];
    char * string_two;

    my_function(&string_two);
    my_other_function(string_one);
    printf("Results:\n%s\n%s\n",
    string_one, string_two);
    return 0;
    }

    >
    > (Linux 9 i386)
    > #gcc main.c myfunction.c
    > #./a.out
    >
    > Data results from My Function: _@
    > --
    > Posted via http://dbforums.com



    --
    Thomas Matthews
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.raos.demon.uk/acllc-c /faq.html
     
    Thomas Matthews, Aug 22, 2003
    #2
    1. Advertising

  3. c_monty

    Eric Sosman Guest

    c_monty wrote:
    >
    > I am used to Delphi and VB, where functions can return strings. I
    > recently starting learning C and my findings are that you can have
    > external functions build strings, but the function cannot return the
    > string itself, rather, it needs to update a variable that is an array or
    > points to an array. Correct?


    Pretty much. "C functions can't return strings" is just
    a special case of "C functions can't return arrays," because
    a string in C is just an array of `char' elements formatted
    in a particular way. Recommended reading: Section 6 "Arrays
    and Pointers" in the comp.lang.c Frequently Asked Questions
    (FAQ) list

    http://www.eskimo.com/~scs/C-faq/top.html

    > Below is a 'simple' test to work with a string that was created in an
    > external function (and external file). Based on the result I get (_@),
    > I know I don't fully "get it" yet. Any help would be appreciated.
    >
    > //MAIN.C
    >
    > #include<stdio.h>
    >
    > main()
    >
    > {
    >
    > char *data_from_function;
    >
    > my_function(data_from_function);
    >
    > printf("Data results from My Function: %s\n");


    There are minor solecisms elsewhere, but this is the first
    Real Live Error: You've used the "%s" specifier to tell printf()
    to output a string, but you haven't told printf() what string
    you want it to output! printf() trusts you, looks in the place
    where the string's `char*' pointer would have been if you'd
    supplied one, gets some kind of garbage, and then there's no
    guarantee of what might happen. You've landed yourself in the
    perilous land called Undefined Behavior.

    >
    > }
    >
    > //MYFUNCTION.C
    >
    > my_function(char *strData)
    >
    > {
    >
    > strData = "HELLO WORLD\n";


    Here's the second Real Live Error: You don't understand
    that C arguments are passed by value, not by reference.
    See Question 4.8 in the FAQ.

    > }
    >
    > (Linux 9 i386)
    >
    > #gcc main.c myfunction.c


    Since you're still somewhat shaky in C, it would be a
    good idea to crank up gcc's warning levels a bit. I use

    gcc -Wall -W -ansi -pedantic -O2 ...

    .... except that I omit "-ansi -pedantic" for programs that
    can't tolerate such rigidity, and I raise the optimization
    level higher than "-O2" when circumstances warrant it.

    > #./a.out
    >
    > Data results from My Function: _@


    Could have been anything at all, or nothing at all.
    Undefined Behavior is, well, undefinable. Folks around
    here are fond of saying U.B. might make demons fly out
    of your nose. Years ago on this same newsgroup, people
    had a wider variety of imaginative U.B. examples, but the
    nasal demons seem to have crowded out the creativity.

    --
     
    Eric Sosman, Aug 22, 2003
    #3
  4. c_monty <> writes:

    > I am used to Delphi and VB, where functions can return strings. I
    > recently starting learning C and my findings are that you can have
    > external functions build strings, but the function cannot return the
    > string itself, rather, it needs to update a variable that is an array or
    > points to an array. Correct?


    Correct.

    > Below is a 'simple' test to work with a string that was created in an
    > external function (and external file). Based on the result I get (_@),
    > I know I don't fully "get it" yet. Any help would be appreciated.
    >
    > //MAIN.C
    >
    > #include<stdio.h>
    >
    > main()


    int main (void)

    > {
    > char *data_from_function;
    >
    > my_function(data_from_function);
    >
    > printf("Data results from My Function: %s\n");


    Do you mean `printf("Data results from My Function: %s\n", data_from_function);'?

    > }


    Insert `return 0;' before the closing brace.

    >
    > //MYFUNCTION.C
    >
    > my_function(char *strData)
    > {
    > strData = "HELLO WORLD\n";
    > }


    `strData' is local to `my_function'. You make `strData' point to a string
    literal. Then the function execution ends, and the value of `strData' is
    forgotten.

    You can return a string literal (more precisely: a pointer to the first
    character of string literal) from a function like this:


    #include <stdio.h>

    const char *my_function (void)
    {
    return "HELLO WORLD";
    }

    int main (void)
    {
    printf ("Data results from My Function: %s\n", my_function ());
    return 0;
    }


    A string literal cannot be modified. If you need to modify the string, you
    must copy it to an array:


    #include <stdio.h>
    #include <string.h>

    void my_function (char *const buffer)
    {
    strcpy (buffer, "HELLO WORLD");
    }

    int main (void)
    {
    /* Must be large enough for the string,
    including the terminating '\0' character. */
    char my_buffer [12];

    my_function (my_buffer);

    my_buffer [1] = 'A';

    printf ("Data results from My Function: %s\n", my_buffer);
    return 0;
    }


    > (Linux 9 i386)


    <OT>
    No such thing. Linux is currently at version 2.4.21; the development branch
    is at version 2.6.0-test3.
    </OT>

    > #gcc main.c myfunction.c


    Please invoke gcc with at least the following flags: -O -Wall -ansi -pedantic

    I recommend `-W' in addition to that.

    Martin
     
    Martin Dickopp, Aug 22, 2003
    #4
  5. c_monty

    Ed Morton Guest

    On 8/22/2003 1:31 PM, pete wrote:
    > c_monty wrote:
    >

    <snip>

    > char *my_function(char *strData)
    > {
    > strData = malloc(sizeof "HELLO WORLD\n");
    > if (strData) {
    > strcpy(strData, "HELLO WORLD\n");
    > }
    > return strData;
    > }
    >


    Why would you have "my_function" take an argument in this case? Wouldn't you
    really write this as:

    char *my_function()
    {
    char *strData;
    strData = malloc(sizeof "HELLO WORLD\n");
    if (strData) {
    strcpy(strData, "HELLO WORLD\n");
    }
    return strData;
    }

    so that instead of being called as:

    > data_from_function = my_function(data_from_function);


    it can be called as:

    data_from_function = my_function();

    Regards,

    Ed.
     
    Ed Morton, Aug 22, 2003
    #5
  6. c_monty

    Guest

    Thomas Matthews <> broke the eternal silence and spoke thus:

    > void my_function(char * * strData)
    > {
    > *strData = "Hellow World\n";
    > }


    This is bad (right?) since strData now points to a constant string that will
    vanish when my_function returns...

    > void my_other_function(char * strData)
    > {
    > strcpy(strdata, "Hello again.\n");
    > return;
    > }


    Also bad, since you don't know in general how much space strData has
    associated with it, if any.

    If I've done foot-in-mouth again here, I apologize ;)

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
     
    , Aug 22, 2003
    #6
  7. On Fri, 22 Aug 2003 13:48:54 -0400, c_monty wrote:


    > I am used to Delphi and VB, where functions can return strings. I
    > recently starting learning C and my findings are that you can have
    > external functions build strings, but the function cannot return the
    > string itself, rather, it needs to update a variable that is an array or
    > points to an array. Correct?


    These other environments are likely returning pointers (Java calls them
    references) as well. C permits pointer arthmetic which gives C it's
    razor's edge. Be careful.

    > my_function(data_from_function);
    >
    > printf("Data results from My Function: %s\n");


    You just forgot to add the string you want to print:

    printf("Data results from My Function: %s\n", data_from_function);

    In C the way to "return strings" is to return a pointer to an array
    of characters:

    char *
    tostr(void)
    {
    return "hello";
    }

    Mike
     
    Michael B Allen, Aug 22, 2003
    #7
  8. c_monty

    pete Guest

    Ed Morton wrote:
    >
    > On 8/22/2003 1:31 PM, pete wrote:
    > > c_monty wrote:
    > >

    > <snip>
    >
    > > char *my_function(char *strData)
    > > {
    > > strData = malloc(sizeof "HELLO WORLD\n");
    > > if (strData) {
    > > strcpy(strData, "HELLO WORLD\n");
    > > }
    > > return strData;
    > > }
    > >

    >
    > Why would you have "my_function" take an argument in this case?


    It's a vestigial feature from the original post.

    > Wouldn't you really write this as:
    >
    > char *my_function()
    > {
    > char *strData;
    > strData = malloc(sizeof "HELLO WORLD\n");
    > if (strData) {
    > strcpy(strData, "HELLO WORLD\n");
    > }
    > return strData;
    > }
    >
    > so that instead of being called as:
    >
    > > data_from_function = my_function(data_from_function);

    >
    > it can be called as:
    >
    > data_from_function = my_function();


    Yes, I think that's better.

    --
    pete
     
    pete, Aug 22, 2003
    #8
  9. c_monty

    pete Guest

    wrote:
    >
    > Thomas Matthews <>
    > broke the eternal silence and spoke thus:
    >
    > > void my_function(char * * strData)
    > > {
    > > *strData = "Hellow World\n";
    > > }

    >
    > This is bad (right?) since strData now points to a
    > constant string that will vanish when my_function returns...


    No. Those kinds of strings persist.
    The strData pointer itself, will disappear,
    but the desired side effect will happen.
    The external pointer that *strData points to,
    will be pointed at the string.

    >
    > > void my_other_function(char * strData)
    > > {
    > > strcpy(strdata, "Hello again.\n");
    > > return;
    > > }

    >
    > Also bad, since you don't know in general how much space strData has
    > associated with it, if any.


    That particular criticism is valid.

    This works:

    #include <stdio.h>

    void my_function(char * * strData)
    {
    *strData = "Hellow World\n";
    }

    int main(void)
    {
    char *data_from_function;

    my_function(&data_from_function);
    printf("Data results from My Function: %s\n",
    data_from_function);
    return 0;
    }

    --
    pete
     
    pete, Aug 22, 2003
    #9
  10. wrote:

    > Thomas Matthews <> broke the eternal silence and spoke thus:
    >
    >
    >>void my_function(char * * strData)
    >>{
    >> *strData = "Hellow World\n";
    >>}

    >
    >
    > This is bad (right?) since strData now points to a constant string that will
    > vanish when my_function returns...


    No, the location of the literal will persist.



    >>void my_other_function(char * strData)
    >>{
    >> strcpy(strdata, "Hello again.\n");
    >> return;
    >>}

    >
    >
    > Also bad, since you don't know in general how much space strData has
    > associated with it, if any.
    >
    > If I've done foot-in-mouth again here, I apologize ;)


    Yes, this is also bad, but it is another alternative.
    Welcome to the problem with C arrays.

    --
    Thomas Matthews
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.raos.demon.uk/acllc-c /faq.html
     
    Thomas Matthews, Aug 22, 2003
    #10
  11. pete <> spoke thus:

    >> > void my_function(char * * strData)
    >> > {
    >> > *strData = "Hellow World\n";
    >> > }

    >>
    >> This is bad (right?) since strData now points to a
    >> constant string that will vanish when my_function returns...


    > No. Those kinds of strings persist.
    > The strData pointer itself, will disappear,
    > but the desired side effect will happen.
    > The external pointer that *strData points to,
    > will be pointed at the string.


    So, since it's a string literal, it still ends up in the static section of
    memory or something? The function still doesn't work if strData happens to be
    NULL... And even if it does work, you can't do something like
    *strData[3]='a', right, since the string is literal?

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
     
    Christopher Benson-Manica, Aug 22, 2003
    #11
  12. c_monty

    ark Guest

    "pete" <> wrote in message
    news:...
    > Christopher Benson-Manica wrote:
    >Something like that.
    >

    <snip>
    > > The function still doesn't work if strData happens to be
    > > NULL... And even if it does work, you can't do something like
    > > *strData[3]='a', right, since the string is literal?

    >
    > Yes, you can't do something like that, because of that.
    >
    > --
    > pete


    Being a practitioner, cannot remember what the std says, but I've seen
    different things. A string literal can be a const (in which case, the linker
    can collect identical strings in one) or not. I've seen it also as a
    compiler switch.
    arkk at macroexpressions.com
     
    ark, Aug 23, 2003
    #12
  13. c_monty

    pete Guest

    ark wrote:
    >
    > "pete" <> wrote in message
    > news:...
    > > Christopher Benson-Manica wrote:
    > >Something like that.
    > >

    > <snip>
    > > > The function still doesn't work if strData happens to be
    > > > NULL... And even if it does work, you can't do something like
    > > > *strData[3]='a', right, since the string is literal?

    > >
    > > Yes, you can't do something like that, because of that.


    > Being a practitioner, cannot remember what the std says,


    http://anubis.dkuug.dk/JTC1/SC22/WG14/www/docs/n869/

    It says that attempts at string literal modification,
    result in undefined behavior.
    When I said "you can't do that",
    I meant "Doing that, isn't sanctioned by the standard",
    but ..., you can attempt a lot of things that wind up working
    on your system, which in fact are not sanctioned by the standard.
    People frequently post code which invokes undefined behavior,
    while they insist that the code is correct because it
    produces the desired result on their system.


    > but I've seen different things.
    > A string literal can be a const (in which case, the linker
    > can collect identical strings in one) or not.


    The standard says that that is allowed.

    > I've seen it also as a compiler switch.
    > arkk at macroexpressions.com




    --
    pete
     
    pete, Aug 23, 2003
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xiangliang Meng
    Replies:
    1
    Views:
    1,611
    Victor Bazarov
    Jun 21, 2004
  2. Kurt Krueckeberg
    Replies:
    2
    Views:
    717
    =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=
    Nov 17, 2004
  3. Ben

    Strings, Strings and Damned Strings

    Ben, Jun 22, 2006, in forum: C Programming
    Replies:
    14
    Views:
    767
    Malcolm
    Jun 24, 2006
  4. Replies:
    6
    Views:
    278
    Dan Bishop
    Apr 6, 2008
  5. Tony Augustine
    Replies:
    0
    Views:
    360
    Tony Augustine
    Jul 22, 2010
Loading...

Share This Page