Something wrong in my program

Discussion in 'C Programming' started by Dominique =?ISO-8859-1?Q?L=E9ger?=, Jan 16, 2004.

  1. Hello guys,

    I'm kinda new to C, and I'm having a hard time with strings. What I'm trying
    to do is a simple function that trims spaces & tabs at the beginning of a
    given string. For example, I want this: " Hello World" to become this:
    "Hello World". At first glance, my function seems to work, but returns some
    strange values...

    Here's my code (please pardon the mess):

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

    int main(void){
    char *trimbegin(char *text);
    char *str = " Hello World!";
    char *result = trimbegin(str);
    printf("What the function returns: \"%s\"\n", result);
    return 0;
    }

    char *trimbegin(char *text){
    int i = 0, j = 0, ok = 0;
    int size = strlen(text);
    char buffer[size + 1];
    char *ptr;

    printf("Original text is: \"%s\"\n", text);
    printf("That's %d characters long...\n", size);
    printf("Now, our text buffer can contain %d characters\n", size +
    1);
    for (i = 0; i <= size; i++){
    if (ok == 1){
    buffer[j] = text;
    j++;
    }
    else if (isspace(text) == 0 && ok == 0){
    buffer[j] = text;
    j++;
    ok = 1;
    }
    }
    printf("What the result is supposed to be: \"%s\"\n", buffer);
    ptr = buffer;
    return ptr;
    }

    And here's the output:

    [dom@localhost C]$ ./a.out
    Original text is: " Hello World!"
    That's 14 characters long...
    Now, our text buffer can contain 15 characters
    What the result is supposed to be: "Hello World!"
    What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"


    Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    World!"?

    Thanks for all your help!

    -Dom
    Dominique =?ISO-8859-1?Q?L=E9ger?=, Jan 16, 2004
    #1
    1. Advertising

  2. Dominique =?ISO-8859-1?Q?L=E9ger?=

    lallous Guest

    "Dominique Léger" <> wrote in message
    news:...
    > Hello guys,
    >
    > I'm kinda new to C, and I'm having a hard time with strings. What I'm

    trying
    > to do is a simple function that trims spaces & tabs at the beginning of a
    > given string. For example, I want this: " Hello World" to become this:
    > "Hello World". At first glance, my function seems to work, but returns

    some
    > strange values...
    >
    > Here's my code (please pardon the mess):
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int main(void){
    > char *trimbegin(char *text);
    > char *str = " Hello World!";
    > char *result = trimbegin(str);
    > printf("What the function returns: \"%s\"\n", result);
    > return 0;
    > }
    >
    > char *trimbegin(char *text){
    > int i = 0, j = 0, ok = 0;
    > int size = strlen(text);
    > char buffer[size + 1];
    > char *ptr;
    >
    > printf("Original text is: \"%s\"\n", text);
    > printf("That's %d characters long...\n", size);
    > printf("Now, our text buffer can contain %d characters\n", size +
    > 1);
    > for (i = 0; i <= size; i++){
    > if (ok == 1){
    > buffer[j] = text;
    > j++;
    > }
    > else if (isspace(text) == 0 && ok == 0){
    > buffer[j] = text;
    > j++;
    > ok = 1;
    > }
    > }
    > printf("What the result is supposed to be: \"%s\"\n", buffer);
    > ptr = buffer;
    > return ptr;
    > }
    >
    > And here's the output:
    >
    > [dom@localhost C]$ ./a.out
    > Original text is: " Hello World!"
    > That's 14 characters long...
    > Now, our text buffer can contain 15 characters
    > What the result is supposed to be: "Hello World!"
    > What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >
    >
    > Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    > World!"?
    >
    > Thanks for all your help!
    >
    > -Dom
    >

    Hello, guess you forgot to add a zero terminator to the string.

    From the code, it would be something like: buffer[j] = 0 just right before
    the printf() statement.

    > int size = strlen(text);
    > char buffer[size + 1];

    I wonder how is this accepted by a C compiler?

    --
    Elias
    lallous, Jan 16, 2004
    #2
    1. Advertising

  3. Dominique Léger <> spoke thus:

    > char *trimbegin(char *text){
    > char buffer[size + 1];
    > char *ptr;
    > /* intervening code trimmed */
    > ptr = buffer;
    > return ptr;

    ^^^^^^^^^^ returns the address of buffer! (clc nitpicks
    on that statement welcome!)
    > }


    Surprisingly (at least to you ;)), this is all the code you need to
    see what's going wrong. You are returning the address of an automatic
    variable, and when trimbegin returns, the memory that was reserved for
    buffer (and that ptr pointed to, and that you returned a pointer to)
    is freed. Thus, that memory is no longer guaranteed to be good for
    anything, and you should not use it. If you did something like

    ptr=malloc( strlen(buffer)+1 ); /* sizeof( char ) guaranteed to be 1 */
    strcpy( ptr, buffer );
    return ptr;

    you'd be fine.

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
    Christopher Benson-Manica, Jan 16, 2004
    #3
  4. Christopher Benson-Manica <> scribbled the following:
    > Dominique Léger <> spoke thus:
    >> char *trimbegin(char *text){
    >> char buffer[size + 1];
    >> char *ptr;
    >> /* intervening code trimmed */
    >> ptr = buffer;
    >> return ptr;

    > ^^^^^^^^^^ returns the address of buffer! (clc nitpicks
    > on that statement welcome!)


    Actually it returns the address of a char, which corresponds to the
    exact same machine-level address as the address of buffer. The only
    difference between them is the type.

    >> }


    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "It's not survival of the fattest, it's survival of the fittest."
    - Ludvig von Drake
    Joona I Palaste, Jan 16, 2004
    #4
  5. Christopher Benson-Manica <> spoke thus:

    > If you did something like
    > (blah)
    > you'd be fine.


    Well, that and listened (probably) to a previous poster who wondered why you
    were able to compile

    char buffer[size+1]; /* dynamic size arrays are C99, yes? */

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
    Christopher Benson-Manica, Jan 16, 2004
    #5
  6. Dominique Léger <> wrote:
    >Hello guys,
    >
    >I'm kinda new to C, and I'm having a hard time with strings. What I'm trying
    >to do is a simple function that trims spaces & tabs at the beginning of a
    >given string. For example, I want this: " Hello World" to become this:
    >"Hello World". At first glance, my function seems to work, but returns some
    >strange values...
    >
    >Here's my code (please pardon the mess):
    >
    >#include <stdio.h>
    >#include <string.h>


    #include <ctype.h> /* for isspace */

    >int main(void){
    > char *trimbegin(char *text);

    Function prototypes shouldn't be buried in function definitions,
    IMO. Move the prototype outside main, or define trimbegin before
    main.

    > char *str = " Hello World!";
    > char *result = trimbegin(str);
    > printf("What the function returns: \"%s\"\n", result);
    > return 0;
    >}
    >
    >char *trimbegin(char *text){
    > int i = 0, j = 0, ok = 0;
    > int size = strlen(text);
    > char buffer[size + 1];
    > char *ptr;
    >
    > printf("Original text is: \"%s\"\n", text);
    > printf("That's %d characters long...\n", size);
    > printf("Now, our text buffer can contain %d characters\n", size +
    >1);
    > for (i = 0; i <= size; i++){
    > if (ok == 1){
    > buffer[j] = text;
    > j++;
    > }
    > else if (isspace(text) == 0 && ok == 0){
    > buffer[j] = text;
    > j++;
    > ok = 1;
    > }
    > }


    That's a very complicated way to do the job at hand.

    > printf("What the result is supposed to be: \"%s\"\n", buffer);
    > ptr = buffer;


    Obfuscation is not a cure for undefined behaviour... ;-)

    > return ptr;


    ... which you invoke here by returning an invalid address, since
    buffer will be gone when control reaches end of function.
    Either
    - qualify buffer static (rendering the function non-reentrant
    and making C99 VLAs impossible to use), or
    - provide a second parameter and let the caller provide the
    buffer, or
    - dynamically allocate memory for buffer in the function and
    document that the caller has to free the memory if it's no
    longer needed, or
    - return only a pointer to the first non-whitespace character
    in the original string,
    whatever fits your needs best.

    The last one is particularly easy to implement:

    char *skipspace( char *s )
    {
    while ( isspace( *s ) )
    s++;
    return s;
    }

    >}
    >
    >And here's the output:
    >
    >[dom@localhost C]$ ./a.out
    >Original text is: " Hello World!"
    >That's 14 characters long...
    >Now, our text buffer can contain 15 characters
    >What the result is supposed to be: "Hello World!"
    >What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >
    >
    >Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    >World!"?


    You were lucky, because you invoked undefined behaviour, didn't
    get what you expected (indicating that something's wrong) and
    nothing really serious happened.

    HTH

    Regards
    --
    Irrwahn Grausewitz ()
    welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
    clc faq-list : http://www.eskimo.com/~scs/C-faq/top.html
    acllc-c++ faq : http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Irrwahn Grausewitz, Jan 16, 2004
    #6
  7. Dominique Léger wrote:
    > Hello guys,
    >
    > I'm kinda new to C, and I'm having a hard time with strings. What I'm trying
    > to do is a simple function that trims spaces & tabs at the beginning of a
    > given string. For example, I want this: " Hello World" to become this:
    > "Hello World". At first glance, my function seems to work, but returns some
    > strange values...
    >
    > Here's my code (please pardon the mess):
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int main(void){
    > char *trimbegin(char *text);


    Move the function definition above the main(), and you won't have to
    declare its prototype here.

    > char *str = " Hello World!";
    > char *result = trimbegin(str);
    > printf("What the function returns: \"%s\"\n", result);
    > return 0;
    > }
    >
    > char *trimbegin(char *text){
    > int i = 0, j = 0, ok = 0;
    > int size = strlen(text);

    should be a size_t, not an int.

    > char buffer[size + 1];

    gcc -Wall -ansi -pedantic :
    warning: ISO C89 forbids variable-size array `buffer'


    > char *ptr;
    >
    > printf("Original text is: \"%s\"\n", text);
    > printf("That's %d characters long...\n", size);
    > printf("Now, our text buffer can contain %d characters\n", size +
    > 1);
    > for (i = 0; i <= size; i++){
    > if (ok == 1){
    > buffer[j] = text;
    > j++;
    > }
    > else if (isspace(text) == 0 && ok == 0){

    gcc -Wall -ansi -pedantic :
    warning: implicit declaration of function `isspace'

    > buffer[j] = text;
    > j++;
    > ok = 1;
    > }
    > }


    Are you sure your algorithm is ok and as simple as it could be ?

    > printf("What the result is supposed to be: \"%s\"\n", buffer);
    > ptr = buffer;
    > return ptr;


    Which can be shortened to :
    return &buffer[0];
    and further to :
    return buffer;

    in which case you've got an additionnal, and very annoying warning :

    gcc -Wall -ansi -pedantic :
    warning: function returns address of local variable

    > }


    You understand that, even if the value returned is an effective memory
    address, what becomes of the memory block starting at this address is no
    more under your control as soon as the function returns ? This memory
    may be reclaimed and reused by the system at any time, so trying to read
    at this at address may have any unpredictable result - not talking about
    *writing* at this address.

    > And here's the output:
    >
    > [dom@localhost C]$ ./a.out
    > Original text is: " Hello World!"
    > That's 14 characters long...
    > Now, our text buffer can contain 15 characters
    > What the result is supposed to be: "Hello World!"
    > What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >
    >
    > Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    > World!"?


    First you forgot to copy the terminating '\0' to buffer, so buffer is
    char array, but not a string. In C, a string is a char array *terminated
    by the char '\0'*. Note that this character is *not* counted by
    strlen(), since it's not part of the string, but merely a 'sentinel'
    indicating where the string ends (the 'effective' string may be shorter
    than the memory block it is contained in).

    Then, you return the address of a local automatic variable, which
    invokes UB (Undefined Behavior) as soon as you read or write at this
    address. Anything can happen, even that it *seems* to work correctly.

    Solutions are :
    - either dynamically allocate memory for buffer in trimbegin(), or
    declare buffer outside trimbegin() and pass its address to trimbegin
    (for now you'd better try the second solution)
    - make sure that buffer terminates with a '\0' (the simplest way to do
    it being to copy the terminating '\0' of the source string)
    - eventually rewrite your algorithm to make it simpler

    tip 1 : you dont need any test in the for loop body nor the ok flag
    tip 2 : the for loop syntax is :
    for (<initialisation>;<test>;<on_each_iteration>)
    {
    <body>
    }
    where any of <initialisation>, <test>, <on_each_iteration>, and
    <body> can be empty.


    Feel free to post amended code for review !-)

    HTH
    Bruno
    Bruno Desthuilliers, Jan 16, 2004
    #7
  8. "Régis Troadec" <> spoke thus:

    > int main()
    > {
    > char * str = " \tHello World";
    > char * trimmed;
    > printf("Original :\n%s\n",str);
    > trimmed = trim(str);
    > printf("Trimmed :\n%s\n",trimmed);

    /* What will happen if trim fails (returns NULL)? Of course,
    it never does so at the moment, but if it were coded
    correctly it might... */
    > free(trimmed);
    > }


    > char* trim(char* s)
    > {
    > char * res;
    > int cnt = 0;
    > int cnt2 = 0;
    > while (isspace(s[cnt]) != 0)
    > cnt++;
    > res = (char*)malloc(sizeof(char)*(strlen(s)-cnt+1));

    /* There are numerous reasons why casting the return value of
    malloc() is inadvisable, although I will let others
    enumerate them */
    /* And of course, what if malloc() fails? */
    > while (s[cnt] != '\0')
    > res[cnt2++] = s[cnt++];
    > res[cnt2] = '\0';
    > return &res[0];

    /* res===&res[0], so why obfuscate? */
    > }


    I don't claim that all is well otherwise, but those are what my
    untrained eyes see.

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

    (Ignore blank lines following - need to keep tin happy)
    Christopher Benson-Manica, Jan 16, 2004
    #8
  9. Hi,

    "Dominique Léger" <> a écrit dans le message de news:
    ...
    > Hello guys,
    >
    > I'm kinda new to C, and I'm having a hard time with strings. What I'm

    trying
    > to do is a simple function that trims spaces & tabs at the beginning of a
    > given string. For example, I want this: " Hello World" to become this:
    > "Hello World". At first glance, my function seems to work, but returns

    some
    > strange values...
    >
    > Here's my code (please pardon the mess):
    >
    > #include <stdio.h>
    > #include <string.h>


    #include <ctype.h> /* for isspace()*/

    > int main(void){
    > char *trimbegin(char *text);
    > char *str = " Hello World!";
    > char *result = trimbegin(str);
    > printf("What the function returns: \"%s\"\n", result);
    > return 0;
    > }
    >
    > char *trimbegin(char *text){
    > int i = 0, j = 0, ok = 0;
    > int size = strlen(text);
    > char buffer[size + 1];


    VLA in C99 only

    > char *ptr;
    >
    > printf("Original text is: \"%s\"\n", text);
    > printf("That's %d characters long...\n", size);
    > printf("Now, our text buffer can contain %d characters\n", size +
    > 1);
    > for (i = 0; i <= size; i++){
    > if (ok == 1){
    > buffer[j] = text;
    > j++;
    > }
    > else if (isspace(text) == 0 && ok == 0){
    > buffer[j] = text;
    > j++;
    > ok = 1;
    > }
    > }


    I'm not sure about your algorithm, since ok is initialized to 0 and that
    isspace() returns a non-zero value if it is a white-space character.

    > printf("What the result is supposed to be: \"%s\"\n", buffer);
    > ptr = buffer;
    > return ptr;
    > }
    >
    > And here's the output:
    >
    > [dom@localhost C]$ ./a.out
    > Original text is: " Hello World!"
    > That's 14 characters long...
    > Now, our text buffer can contain 15 characters
    > What the result is supposed to be: "Hello World!"
    > What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >
    >
    > Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    > World!"?
    > Thanks for all your help!
    >
    > -Dom


    I suggest you my example :

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

    char* trim(char* s);

    int main()
    {
    char * str = " \tHello World";
    char * trimmed;
    printf("Original :\n%s\n",str);
    trimmed = trim(str);
    printf("Trimmed :\n%s\n",trimmed);
    free(trimmed);
    }

    char* trim(char* s)
    {
    char * res;
    int cnt = 0;
    int cnt2 = 0;

    while (isspace(s[cnt]) != 0)
    cnt++;

    res = (char*)malloc(sizeof(char)*(strlen(s)-cnt+1));

    while (s[cnt] != '\0')
    res[cnt2++] = s[cnt++];

    res[cnt2] = '\0';

    return &res[0];
    }

    Best regards. régis
    Régis Troadec, Jan 16, 2004
    #9
  10. Régis Troadec wrote:
    > Hi,
    >
    > "Dominique Léger" <> a écrit dans le message de news:
    > ...
    >
    >>Hello guys,
    >>
    >>I'm kinda new to C, and I'm having a hard time with strings. What I'm

    >
    > trying
    >
    >>to do is a simple function that trims spaces & tabs at the beginning of a
    >>given string. For example, I want this: " Hello World" to become this:
    >>"Hello World". At first glance, my function seems to work, but returns

    >
    > some
    >
    >>strange values...
    >>
    >>Here's my code (please pardon the mess):

    (snip OP code)
    >
    > I suggest you my example :


    I suggest the small corrections below...

    > #include <ctype.h>
    > #include <stdio.h>
    > #include <string.h>
    > #include <stdlib.h>
    >
    > char* trim(char* s);
    >
    > int main()

    int main(void) or int main(int argc, char **argv)
    > {
    > char * str = " \tHello World";
    > char * trimmed;
    > printf("Original :\n%s\n",str);
    > trimmed = trim(str);
    > printf("Trimmed :\n%s\n",trimmed);
    > free(trimmed);
    > }
    >
    > char* trim(char* s)
    > {
    > char * res;
    > int cnt = 0;
    > int cnt2 = 0;
    >
    > while (isspace(s[cnt]) != 0)
    > cnt++;
    >
    > res = (char*)malloc(sizeof(char)*(strlen(s)-cnt+1));

    res = malloc(strlen(s) - cnt + 1);
    if (res != NULL) /* malloc may fail */
    {
    > while (s[cnt] != '\0')
    > res[cnt2++] = s[cnt++];
    >
    > res[cnt2] = '\0';

    }
    else {
    /* whatever */
    }
    > return &res[0];

    return res;
    > }


    HTH
    Bruno
    Bruno Desthuilliers, Jan 16, 2004
    #10
  11. "lallous" <> wrote:
    >"Dominique Léger" <> wrote:

    <snip>
    >> Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    >> World!"?

    <snip>
    >Hello, guess you forgot to add a zero terminator to the string.


    This was my first thought too, but the OP apparently /did/ copy
    the terminating null character. *But* the OP invoked UB by
    returning the address to automatic storage, and that's why...

    >[...] buffer[j] = 0 just right before the printf() statement.


    .... won't help.

    >> int size = strlen(text);
    >> char buffer[size + 1];

    >I wonder how is this accepted by a C compiler?


    C99 VLA.

    Regards
    --
    Irrwahn Grausewitz ()
    welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
    clc faq-list : http://www.eskimo.com/~scs/C-faq/top.html
    acllc-c++ faq : http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Irrwahn Grausewitz, Jan 16, 2004
    #11
  12. Bruno Desthuilliers <> wrote:
    >Dominique Léger wrote:

    <snip>
    >> What the result is supposed to be: "Hello World!"
    >> What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"

    <snip>
    >First you forgot to copy the terminating '\0' to buffer, so buffer is
    >char array, but not a string.

    <snip>

    Even if it were the case, it would not explain the differences
    between the two lines of output, re-quoted above.

    Regards
    --
    Irrwahn Grausewitz ()
    welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
    clc faq-list : http://www.eskimo.com/~scs/C-faq/top.html
    acllc-c++ faq : http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Irrwahn Grausewitz, Jan 16, 2004
    #12
  13. in comp.lang.c i read:

    >char buffer[size+1]; /* dynamic size arrays are C99, yes? */


    yes, though it is called a variable length array.

    --
    a signature
    those who know me have no need of my name, Jan 16, 2004
    #13
  14. Dominique Léger <> wrote in message news:<>...
    > Hello guys,
    >
    > I'm kinda new to C, and I'm having a hard time with strings. What I'm trying
    > to do is a simple function that trims spaces & tabs at the beginning of a
    > given string. For example, I want this: " Hello World" to become this:
    > "Hello World". At first glance, my function seems to work, but returns some
    > strange values...


    General comment: Consider turning on some more warnings on your
    compiler. I see the following with
    gcc -pedantic -Wall -W -std=c89 -o foo foo.c
    foo.c:15: warning: ISO C89 forbids variable-size array `buffer'
    foo.c:27: warning: implicit declaration of function `isspace'
    The first may not bother you, the second shows failure to include
    a needed header...

    >
    > Here's my code (please pardon the mess):
    >
    > #include <stdio.h>
    > #include <string.h>


    #include <ctype.h> /* for isspace */

    >
    > int main(void){


    It is more usual to put your function declarations at file scope rather
    than inside a function. And you might consider declaring the function
    to be "static", the proper course to take for functions that are not
    being used outside the current source file.

    > char *trimbegin(char *text);


    You want const char *str here, to indicate this must not
    be modified. This lets the compiler help you out by
    pointing out any attempt to change this.

    > char *str = " Hello World!";
    > char *result = trimbegin(str);
    > printf("What the function returns: \"%s\"\n", result);
    > return 0;
    > }
    >


    You want const char *text as the argument, to indicate it is
    not to be modified.

    > char *trimbegin(char *text){
    > int i = 0, j = 0, ok = 0;
    > int size = strlen(text);


    The array size below is not a constant expression. That is OK in
    C99 and as a compiler extension sometimes (it obviously works on
    your compiler). Just FYI, it doesn't work on strict C89 compilers.

    > char buffer[size + 1];
    > char *ptr;
    >
    > printf("Original text is: \"%s\"\n", text);
    > printf("That's %d characters long...\n", size);
    > printf("Now, our text buffer can contain %d characters\n", size +
    > 1);


    What is below seems to me to work just fine. But if you want to
    write it a different and slightly simpler way, consider using a
    loop to advance a pointer past the whitespace and then use a
    strcpy to copy the rest.

    > for (i = 0; i <= size; i++){
    > if (ok == 1){
    > buffer[j] = text;
    > j++;
    > }
    > else if (isspace(text) == 0 && ok == 0){
    > buffer[j] = text;
    > j++;
    > ok = 1;
    > }
    > }



    > printf("What the result is supposed to be: \"%s\"\n", buffer);
    > ptr = buffer;


    You are returning a pointer to "automatic" storage. This is a big
    no-no. I believe (no standard handy) that this causes "undefined
    behavior". What happens to the memory once you leave the scope at
    which the storage is allocated, you don't know what is going to
    happen to it. Thankfully, in your case, something bad DOES happen
    so you know there is a problem. You either need to declare the
    buffer array "static" (often a bad idea in larger programs, fine
    here), or allocate some memory dynamically using malloc and free
    it later.

    > return ptr;
    > }
    >
    > And here's the output:
    >
    > [dom@localhost C]$ ./a.out
    > Original text is: " Hello World!"
    > That's 14 characters long...
    > Now, our text buffer can contain 15 characters
    > What the result is supposed to be: "Hello World!"
    > What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >
    >
    > Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    > World!"?
    >
    > Thanks for all your help!
    >
    > -Dom
    David Resnick, Jan 16, 2004
    #14
  15. Dominique =?ISO-8859-1?Q?L=E9ger?=

    CBFalconer Guest

    Irrwahn Grausewitz wrote:
    > Bruno Desthuilliers <> wrote:
    > >Dominique Léger wrote:

    >
    > <snip>
    >
    > >> What the result is supposed to be: "Hello World!"
    > >> What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"

    >
    > <snip>
    >
    > >First you forgot to copy the terminating '\0' to buffer, so buffer
    > > is char array, but not a string.

    >
    > <snip>
    >
    > Even if it were the case, it would not explain the differences
    > between the two lines of output, re-quoted above.


    With all this foofaraw, nobody seems to point out that all trim
    requires (for leading blanks) is:

    const char *trim(const char *s)
    {
    while ((' ' == *s) || ('\t' == *s)) s++;
    return s;
    }

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Jan 16, 2004
    #15
  16. in comp.lang.c i read:

    >With all this foofaraw, nobody seems to point out that all trim
    >requires (for leading blanks) is:
    >
    >const char *trim(const char *s)
    >{
    > while ((' ' == *s) || ('\t' == *s)) s++;


    isspace() may be better to use, as it is locale sensitive. then again some
    may dislike that carriage control, line termination, and vertical white-
    space are also included.

    --
    a signature
    those who know me have no need of my name, Jan 16, 2004
    #16
  17. Régis Troadec wrote:

    > Hi,
    >
    > "Dominique Léger" <> a écrit dans le message de news:
    > ...
    >
    >>Hello guys,
    >>
    >>I'm kinda new to C, and I'm having a hard time with strings. What I'm

    >
    > trying
    >
    >>to do is a simple function that trims spaces & tabs at the beginning of a
    >>given string. For example, I want this: " Hello World" to become this:
    >>"Hello World". At first glance, my function seems to work, but returns

    >
    > some
    >
    >>strange values...
    >>
    >>Here's my code (please pardon the mess):
    >>
    >>#include <stdio.h>
    >>#include <string.h>

    >
    >
    > #include <ctype.h> /* for isspace()*/
    >
    >
    >>int main(void){
    >> char *trimbegin(char *text);
    >> char *str = " Hello World!";
    >> char *result = trimbegin(str);
    >> printf("What the function returns: \"%s\"\n", result);
    >> return 0;
    >>}
    >>
    >>char *trimbegin(char *text){
    >> int i = 0, j = 0, ok = 0;
    >> int size = strlen(text);
    >> char buffer[size + 1];

    >
    >
    > VLA in C99 only
    >
    >
    >> char *ptr;
    >>
    >> printf("Original text is: \"%s\"\n", text);
    >> printf("That's %d characters long...\n", size);
    >> printf("Now, our text buffer can contain %d characters\n", size +
    >>1);
    >> for (i = 0; i <= size; i++){
    >> if (ok == 1){
    >> buffer[j] = text;
    >> j++;
    >> }
    >> else if (isspace(text) == 0 && ok == 0){
    >> buffer[j] = text;
    >> j++;
    >> ok = 1;
    >> }
    >> }

    >
    >
    > I'm not sure about your algorithm, since ok is initialized to 0 and that
    > isspace() returns a non-zero value if it is a white-space character.
    >
    >
    >> printf("What the result is supposed to be: \"%s\"\n", buffer);
    >> ptr = buffer;
    >> return ptr;
    >>}
    >>
    >>And here's the output:
    >>
    >>[dom@localhost C]$ ./a.out
    >>Original text is: " Hello World!"
    >>That's 14 characters long...
    >>Now, our text buffer can contain 15 characters
    >>What the result is supposed to be: "Hello World!"
    >>What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"
    >>
    >>
    >>Why does it return "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿" and not "Hello
    >>World!"?
    >>Thanks for all your help!
    >>
    >>-Dom

    >
    >
    > I suggest you my example :
    >
    > #include <ctype.h>
    > #include <stdio.h>
    > #include <string.h>
    > #include <stdlib.h>
    >
    > char* trim(char* s);
    >
    > int main()
    > {
    > char * str = " \tHello World";
    > char * trimmed;
    > printf("Original :\n%s\n",str);
    > trimmed = trim(str);
    > printf("Trimmed :\n%s\n",trimmed);
    > free(trimmed);

    exit(EXIT_SUCCESS); /* 0 is fine, too */
    /* or you could have return 0; just as well */
    > }
    >
    > char* trim(char* s)
    > {
    > char * res;
    > int cnt = 0;
    > int cnt2 = 0;
    >
    > while (isspace(s[cnt]) != 0)
    > cnt++;
    >
    > res = (char*)malloc(sizeof(char)*(strlen(s)-cnt+1));

    Not testing the return value of malloc() is VERY bad, because if
    malloc() returns NULL you will attempt to access memory you don't own.
    Which is a source of undefined behavior. Which means your program, OS,
    and hardware can literally do /anything/ after that point.

    It is important enough that even trivial code should test for a failure,
    and some coders (myself included) have created a version of malloc that
    will quit the program with an error message instead of returning NULL.
    (That can be deeply stupid in some cases, which is why I only use it in
    the cases where it makes sense.)

    Casting the retval of malloc() is bad:
    1. Can hide a failure to #include <stdlib.h> because if a prototype is
    not in scope, malloc() implicitly returns an int. This can be dangerous
    on some machines.
    2. Makes code harder to change later, when you decide to make malloc()
    allocate something besides a buffer of char.
    3. Demonstrates a lack of knowledge about how a pointer to void works.
    4. Introduces unneeded visual clutter.

    sizeof(char) is unneeded, as sizeof(char) == 1 by definition.

    >
    > while (s[cnt] != '\0')
    > res[cnt2++] = s[cnt++];
    >
    > res[cnt2] = '\0';
    >
    > return &res[0];


    Why not just return res; ?

    > }




    --
    My address is yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
    Note: Rot13 and convert spelled-out numbers to numerical equivalents.
    August Derleth, Jan 16, 2004
    #17
  18. Variable-Length Arrays (was Re: Something wrong in my program)

    those who know me have no need of my name wrote:

    > in comp.lang.c i read:
    >
    >
    >>char buffer[size+1]; /* dynamic size arrays are C99, yes? */

    >
    >
    > yes, though it is called a variable length array.
    >


    What happens if you try to use a VLA to allocate more memory than your
    OS will let your program have?

    --
    My address is yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
    Note: Rot13 and convert spelled-out numbers to numerical equivalents.
    August Derleth, Jan 16, 2004
    #18
  19. Irrwahn Grausewitz wrote:
    > Bruno Desthuilliers <> wrote:
    >
    >>Dominique Léger wrote:

    >
    > <snip>
    >
    >>>What the result is supposed to be: "Hello World!"
    >>>What the function returns: "Hello World! @8@$÷ÿ¿¸öÿ¿PS@ý@Èöÿ¿"

    >
    > <snip>
    >
    >>First you forgot to copy the terminating '\0' to buffer, so buffer is
    >>char array, but not a string.

    >
    > <snip>
    >
    > Even if it were the case, it would not explain the differences
    > between the two lines of output, re-quoted above.
    >
    > Regards


    That was the second point, that you may have noticed if you had read
    further !-)

    Regards too
    Bruno Desthuilliers, Jan 16, 2004
    #19
  20. CBFalconer wrote:
    (snip)

    > With all this foofaraw, nobody seems to point out that all trim
    > requires (for leading blanks) is:
    >
    > const char *trim(const char *s)
    > {
    > while ((' ' == *s) || ('\t' == *s)) s++;
    > return s;
    > }


    Some did notice, but tried to lead the OP to discover this by himself
    instead of giving him the solution.
    Bruno Desthuilliers, Jan 16, 2004
    #20
    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. Guest
    Replies:
    4
    Views:
    477
    Guest
    Oct 13, 2004
  2. Flamingo
    Replies:
    2
    Views:
    384
    IchBin
    Jul 11, 2006
  3. Pekka Järvinen
    Replies:
    2
    Views:
    664
    Richard Tobin
    Apr 29, 2008
  4. Replies:
    4
    Views:
    214
    Tad McClellan
    Jun 1, 2007
  5. Replies:
    9
    Views:
    159
Loading...

Share This Page