Help me with Concatenating strings

Discussion in 'C Programming' started by c, Sep 24, 2006.

  1. c

    c Guest

    Hi everybody.

    I'm working on converting a program wriiten on perl to C, and facing a
    problem with concatenate strings.
    Now here is a small program that descripe the problem, if you help me
    to solve in this small code, I can solve it on my own program...you
    don't want to have head-ache :)

    So, the problem excatly is, I built an array..just like this one.

    char *my_array [10];
    my_array[0] = "Sally\n";
    my_array[1] = "Ndiya\n";
    my_array[2] = "Samantha\n";
    my_array[3] = "Sara\n";
    my_array[4] = "Cadillac\n";
    my_array[5] = "GM For Ever\n";
    my_array[6] = "SlacWare\n";
    my_array[7] = "Google\n";
    my_array[8] = "Google more and more\n";
    my_array[9] = "You\n";
    my_array[10] = "Computers\n";

    my program will recieve an argument -char *argv[]- from the user.

    int main(int argc,char *argv[])


    I want to concatenate the given argument to at the first of each line
    of my array.
    so, if we imagine the array after the concatenating, it would look like
    this (suppose the given argument is "ILove").

    my_array[0] = "ILoveSally\n";
    my_array[1] = "ILoveNdiya\n";
    my_array[2] = "ILovesamantha\n";
    my_array[3] = "ILoveSara\n";
    my_array[4] = "ILoveCadillac\n";
    my_array[5] = "ILoveGM For Ever\n";
    my_array[6] = "ILoveSlacWare\n";
    my_array[7] = "ILoveGoogle\n";
    my_array[8] = "ILoveGoogle again\n";
    my_array[9] = "ILoveSAMI\n";
    my_array[10] = "ILoveComputers\n";*/

    I tried strcat() -strings.h- but the result wasn't what I'm looking
    for.

    read the code..and the comments will help to understand the
    problem..here is the whole code of my problem example.

    #include <stdio.h>

    int main(int argc,char *argv[])
    {int i=-1;
    char *my_array [10];

    my_array[0] = "Sally\n";
    my_array[1] = "Ndiya\n";
    my_array[2] = "Samantha\n";
    my_array[3] = "Sara\n";
    my_array[4] = "Cadillac\n";
    my_array[5] = "GM For Ever\n";
    my_array[6] = "SlacWare\n";
    my_array[7] = "Google\n";
    my_array[8] = "Google more and more\n";
    my_array[9] = "You\n";
    my_array[10] = "Computers\n";

    while(i++ < 10)
    {
    printf(argv[1]); //Don't do it like this..read my comments please.
    printf(my_array);
    }

    // I need your help to fix below loop, I want to cancatenate the given
    data -*argv[]- to each line of my array.
    // For Example, if the user enetered
    // root@localhost# test ILove
    // the result would be:
    // ILoveSally
    // ILoveNdiya
    // ..etc
    //
    //But don't do it by printting the given data followed by my_array
    lines(I mean by printting it twoice), because I need the given data to
    be concatenated at the first of each line of my array.
    //So, my_array would look like this
    // my_array[0] = "ILoveSally\n";
    // my_array[1] = "ILoveNdiya\n";
    // my_array[2] = "ILovesamantha\n";
    // my_array[3] = "ILoveSara\n";
    // my_array[4] = "ILoveCadillac\n";
    // my_array[5] = "ILoveGM For Ever\n";
    // my_array[6] = "ILoveSlacWare\n";
    // my_array[7] = "ILoveGoogle\n";
    // my_array[8] = "ILoveGoogle again\n";
    // my_array[9] = "ILoveSAMI\n";
    // my_array[10] = "ILoveComputers\n";*/

    while (i++ < 10)
    {
    // type your code here..Thanks
    }


    return 0;
    }


    thank you for your time.
    c, Sep 24, 2006
    #1
    1. Advertising

  2. you can't change anything in that array, as those are all read-only
    constants.

    So you either need another array, either fixed size strings, or get the
    memory dynamically, either thru malloc() or out of your own array. I
    recommend something aloong the lines of the latter for simplicity. Not
    tested, but generally on track below code is. Add some obvious error
    checks for extra credit. Use snprintf for extra safety.


    char BigPool[ 1000000 ]; // or whatever size you expect;

    char Strs[ STRINGS_IN_LIST ] = { "foo", "bar", ........ };
    int Free = 0;

    int i, Len;

    for( i = 0; i < STRINGS_IN_LIST; i++ )
    Free += sprintf( BigPool[ Free ], "%s%s", argv[ whatever ], Strs[
    i ] ) + 1;



    .
    Ancient_Hacker, Sep 24, 2006
    #2
    1. Advertising

  3. oops, I forgot to log the address of each created string, try this:


    char BigPool[ 1000000 ]; // or whatever size you expect;

    char Strs[ STRINGS_IN_LIST ] = { "foo", "bar", ........ };

    char * OutStrs[ STRINGS_IN_LIST ];


    int Free = 0;

    int i, Len;

    for( i = 0; i < STRINGS_IN_LIST; i++ )
    Free += sprintf( OutStrs[ i ] = BigPool[ Free ], "%s%s", argv[
    whatever ], Strs[ i ] ) + 1;



    .
    Ancient_Hacker, Sep 24, 2006
    #3
  4. c posted:

    > char *my_array [10];



    This array contains ten elements.


    > my_array[0] = "Sally\n";
    > my_array[1] = "Ndiya\n";
    > my_array[2] = "Samantha\n";
    > my_array[3] = "Sara\n";
    > my_array[4] = "Cadillac\n";
    > my_array[5] = "GM For Ever\n";
    > my_array[6] = "SlacWare\n";
    > my_array[7] = "Google\n";
    > my_array[8] = "Google more and more\n";
    > my_array[9] = "You\n";
    > my_array[10] = "Computers\n";



    Here, you assign to eleven separate elements.


    > #include <stdio.h>
    >
    > int main(int argc,char *argv[])
    > {int i=-1;
    > char *my_array [10];
    >
    > my_array[0] = "Sally\n";
    > my_array[1] = "Ndiya\n";
    > my_array[2] = "Samantha\n";
    > my_array[3] = "Sara\n";
    > my_array[4] = "Cadillac\n";
    > my_array[5] = "GM For Ever\n";
    > my_array[6] = "SlacWare\n";
    > my_array[7] = "Google\n";
    > my_array[8] = "Google more and more\n";
    > my_array[9] = "You\n";
    > my_array[10] = "Computers\n";



    Again here, you assign to eleven elements.


    > while(i++ < 10)
    > {
    > printf(argv[1]); //Don't do it like this..read my comments please.
    > printf(my_array);
    > }



    Why resort to that? Looping 0 through 10 can be much simpler:

    unsigned i = 0;

    do {

    }while(++i != 11);

    Or, if you'd prefer the less efficient simplicity of:

    for(unsigned i = 0; i != 11; ++i)
    {

    }

    You're still pretending that you're array has eleven elements though...

    --

    Frederick Gotham
    Frederick Gotham, Sep 24, 2006
    #4
  5. c

    c Guest

    Thank you, but this is just a peace of code i don't care about it that
    much.

    Frederick Gotham wrote:
    > c posted:
    >
    > > char *my_array [10];

    >
    >
    > This array contains ten elements.
    >
    >
    > > my_array[0] = "Sally\n";
    > > my_array[1] = "Ndiya\n";
    > > my_array[2] = "Samantha\n";
    > > my_array[3] = "Sara\n";
    > > my_array[4] = "Cadillac\n";
    > > my_array[5] = "GM For Ever\n";
    > > my_array[6] = "SlacWare\n";
    > > my_array[7] = "Google\n";
    > > my_array[8] = "Google more and more\n";
    > > my_array[9] = "You\n";
    > > my_array[10] = "Computers\n";

    >
    >
    > Here, you assign to eleven separate elements.
    >
    >
    > > #include <stdio.h>
    > >
    > > int main(int argc,char *argv[])
    > > {int i=-1;
    > > char *my_array [10];
    > >
    > > my_array[0] = "Sally\n";
    > > my_array[1] = "Ndiya\n";
    > > my_array[2] = "Samantha\n";
    > > my_array[3] = "Sara\n";
    > > my_array[4] = "Cadillac\n";
    > > my_array[5] = "GM For Ever\n";
    > > my_array[6] = "SlacWare\n";
    > > my_array[7] = "Google\n";
    > > my_array[8] = "Google more and more\n";
    > > my_array[9] = "You\n";
    > > my_array[10] = "Computers\n";

    >
    >
    > Again here, you assign to eleven elements.
    >
    >
    > > while(i++ < 10)
    > > {
    > > printf(argv[1]); //Don't do it like this..read my comments please.
    > > printf(my_array);
    > > }

    >
    >
    > Why resort to that? Looping 0 through 10 can be much simpler:
    >
    > unsigned i = 0;
    >
    > do {
    >
    > }while(++i != 11);
    >
    > Or, if you'd prefer the less efficient simplicity of:
    >
    > for(unsigned i = 0; i != 11; ++i)
    > {
    >
    > }
    >
    > You're still pretending that you're array has eleven elements though...
    >
    > --
    >
    > Frederick Gotham
    c, Sep 24, 2006
    #5
  6. c

    c Guest

    Thank you for helping me, I'm going to try and reply again if I have
    some Questions.

    Ancient_Hacker wrote:
    > oops, I forgot to log the address of each created string, try this:
    >
    >
    > char BigPool[ 1000000 ]; // or whatever size you expect;
    >
    > char Strs[ STRINGS_IN_LIST ] = { "foo", "bar", ........ };
    >
    > char * OutStrs[ STRINGS_IN_LIST ];
    >
    >
    > int Free = 0;
    >
    > int i, Len;
    >
    > for( i = 0; i < STRINGS_IN_LIST; i++ )
    > Free += sprintf( OutStrs[ i ] = BigPool[ Free ], "%s%s", argv[
    > whatever ], Strs[ i ] ) + 1;
    >
    >
    >
    > .
    c, Sep 24, 2006
    #6
  7. c

    Eric Sosman Guest

    c wrote:
    > Hi everybody.
    >
    > I'm working on converting a program wriiten on perl to C, and facing a
    > problem with concatenate strings.
    > Now here is a small program that descripe the problem, if you help me
    > to solve in this small code, I can solve it on my own program...you
    > don't want to have head-ache :)
    >
    > So, the problem excatly is, I built an array..just like this one.
    >
    > char *my_array [10];
    > my_array[0] = "Sally\n";
    > my_array[1] = "Ndiya\n";
    > my_array[2] = "Samantha\n";
    > my_array[3] = "Sara\n";
    > my_array[4] = "Cadillac\n";
    > my_array[5] = "GM For Ever\n";
    > my_array[6] = "SlacWare\n";
    > my_array[7] = "Google\n";
    > my_array[8] = "Google more and more\n";
    > my_array[9] = "You\n";
    > my_array[10] = "Computers\n";


    "Just like" this one? Including the attempt to store a
    value in the non-existent eleventh element of a ten-element
    array? In C an array of N elements has indices that run from
    [0] through [N-1], inclusive, but does not have an [N] element.

    By the way, C offers a more convenient syntax for array
    initialization:

    char *my_array[10] = { "Sally\n", "Ndiya\n", "Samantha\n",
    "Sara\n", "Cadillac\n", "GM For Ever\n", "SlacWare\n",
    "Google\n", "Google more and more\n", "You\n",
    "Computers\n", };

    A few points about this: First, since you've declared the array
    to have ten elements but actually provided eleven initializers,
    the compiler will complain and point out your mistake. Second,
    you could replace [10] with [] and let the compiler figure out
    the array size by counting the initializers itself instead of
    making you do it (sizeof my_array / sizeof my_array[0] will then
    tell you how big the compiler decided the array should be). And
    last, the comma after the final initializer is optional -- it's
    sometimes convenient if the code is being generated by a program
    or if you anticipate adding more initializers later, but you can
    use it or omit it according to your own taste.

    > my program will recieve an argument -char *argv[]- from the user.
    >
    > int main(int argc,char *argv[])
    >
    > I want to concatenate the given argument to at the first of each line
    > of my array. [...]


    You need to confront the simplicity of C's memory management.
    I mean "simplicity" in the sense that C doesn't do very much about
    memory management on its own; you must attend to it for yourself.
    This is both a weakness and a strength of C: It's a weakness because
    it forces you to fret about the details, and a strength because it
    doesn't burden you with the machinery of automatic managers whose
    style may not suit your needs.

    In this case, C has already done some minimal memory management
    for you: It has set aside space for the array my_array and filled
    its elements with pointers to strings, and it has set aside space
    for those strings and filled them with their intended contents. But
    now you need something different: You need to create new strings in
    memory someplace, and change the array elements to point to those
    new strings instead of the old ones.

    Here's a quickie solution, with explanation to follow:

    for (i = 0; i < sizeof my_array / sizeof my_array[0]; ++i) {
    char *new;
    new = malloc(strlen(argv[1]) + strlen(my_array) + 1);
    if (new == NULL)
    exit (EXIT_FAILURE);
    strcpy (new, argv[1]);
    strcat (new, my_array);
    my_array = new;
    }

    The first line steps the variable i through all the valid index
    values of the array my_array, executing the body of the loop once
    for each i value. The second line declares a temporary variable called
    new that will point to the memory for one of the new strings you're
    about to create -- you can't just obliterate my_array yet, because
    you still need to work with the original string it's still pointing to.

    The third line requests some memory to be allocated. How much?
    You'll need enough for all the characters of the argv[1] string, plus
    enough for all the characters of the my_array string, plus one more
    for the '\0' that must be present at the end of any string. (It is
    astonishing how frequently people forget about that "plus one;" be
    on guard against making that all-too-commmon mistake.)

    The fourth and fifth lines are important: You call malloc to
    *request* a certain amount of memory, but the request might not be
    granted. Perhaps the system is running low on memory, perhaps it
    has plenty available but it's all scattered around in dribs and
    drabs none of which are big enough, perhaps the phase of the Moon
    is wrong. *Always* check for a NULL return from malloc, and take
    corrective action if you get one -- in this case, the "corrective
    action" is simply to terminate the program unsuccessfully, but in
    other programs you might do something more elaborate.

    The sixth and seventh lines build the new string from the two
    pieces. Line six copies the argv[1] string into the new memory area,
    and line seven appends the my_array string to it. Note carefully
    that line six uses strcpy and seven uses strcat; it would be wrong
    to interchange them or to use the same function (either one) in both
    places. You need to copy the first string into the uninitialized
    brand-new memory area, and then append the second.

    Finally, line eight changes my_array so it now points to the
    newly-built string.

    At the beginning of the program, you'll need to #include the
    <string.h> header (to declare the strlen, strcpy, and strcat functions)
    and the <stdlib.h> header (for malloc, exit, and EXIT_FAILURE). You
    may need other headers like <stdio.h> if you intend to display any
    results. Also, it would be a good idea for your program to check
    that it actually received an argument string (check for argc>1)
    before running blindly ahead and trying to do things with a string
    that doesn't even exist.

    --
    Eric Sosman
    lid
    Eric Sosman, Sep 24, 2006
    #7
  8. c

    CBFalconer Guest

    c wrote:
    >
    > I'm working on converting a program wriiten on perl to C, and
    > facing a problem with concatenate strings.


    Try strlcat and strlcpy. You can get source and documentation for
    these from:

    <http://cbfalconer.home.att.net/download/>

    --
    Some informative links:
    <news:news.announce.newusers
    <http://www.geocities.com/nnqweb/>
    <http://www.catb.org/~esr/faqs/smart-questions.html>
    <http://www.caliburn.nl/topposting.html>
    <http://www.netmeister.org/news/learn2quote.html>
    <http://cfaj.freeshell.org/google/>
    CBFalconer, Sep 24, 2006
    #8
  9. c

    c Guest

    THANK YOU VERY VERY MUCH, I'm going to try it and reply if I have
    another questions..you just wrote an article for me, it must be printed
    :)

    Eric Sosman wrote:
    > c wrote:
    > > Hi everybody.
    > >
    > > I'm working on converting a program wriiten on perl to C, and facing a
    > > problem with concatenate strings.
    > > Now here is a small program that descripe the problem, if you help me
    > > to solve in this small code, I can solve it on my own program...you
    > > don't want to have head-ache :)
    > >
    > > So, the problem excatly is, I built an array..just like this one.
    > >
    > > char *my_array [10];
    > > my_array[0] = "Sally\n";
    > > my_array[1] = "Ndiya\n";
    > > my_array[2] = "Samantha\n";
    > > my_array[3] = "Sara\n";
    > > my_array[4] = "Cadillac\n";
    > > my_array[5] = "GM For Ever\n";
    > > my_array[6] = "SlacWare\n";
    > > my_array[7] = "Google\n";
    > > my_array[8] = "Google more and more\n";
    > > my_array[9] = "You\n";
    > > my_array[10] = "Computers\n";

    >
    > "Just like" this one? Including the attempt to store a
    > value in the non-existent eleventh element of a ten-element
    > array? In C an array of N elements has indices that run from
    > [0] through [N-1], inclusive, but does not have an [N] element.
    >
    > By the way, C offers a more convenient syntax for array
    > initialization:
    >
    > char *my_array[10] = { "Sally\n", "Ndiya\n", "Samantha\n",
    > "Sara\n", "Cadillac\n", "GM For Ever\n", "SlacWare\n",
    > "Google\n", "Google more and more\n", "You\n",
    > "Computers\n", };
    >
    > A few points about this: First, since you've declared the array
    > to have ten elements but actually provided eleven initializers,
    > the compiler will complain and point out your mistake. Second,
    > you could replace [10] with [] and let the compiler figure out
    > the array size by counting the initializers itself instead of
    > making you do it (sizeof my_array / sizeof my_array[0] will then
    > tell you how big the compiler decided the array should be). And
    > last, the comma after the final initializer is optional -- it's
    > sometimes convenient if the code is being generated by a program
    > or if you anticipate adding more initializers later, but you can
    > use it or omit it according to your own taste.
    >
    > > my program will recieve an argument -char *argv[]- from the user.
    > >
    > > int main(int argc,char *argv[])
    > >
    > > I want to concatenate the given argument to at the first of each line
    > > of my array. [...]

    >
    > You need to confront the simplicity of C's memory management.
    > I mean "simplicity" in the sense that C doesn't do very much about
    > memory management on its own; you must attend to it for yourself.
    > This is both a weakness and a strength of C: It's a weakness because
    > it forces you to fret about the details, and a strength because it
    > doesn't burden you with the machinery of automatic managers whose
    > style may not suit your needs.
    >
    > In this case, C has already done some minimal memory management
    > for you: It has set aside space for the array my_array and filled
    > its elements with pointers to strings, and it has set aside space
    > for those strings and filled them with their intended contents. But
    > now you need something different: You need to create new strings in
    > memory someplace, and change the array elements to point to those
    > new strings instead of the old ones.
    >
    > Here's a quickie solution, with explanation to follow:
    >
    > for (i = 0; i < sizeof my_array / sizeof my_array[0]; ++i) {
    > char *new;
    > new = malloc(strlen(argv[1]) + strlen(my_array) + 1);
    > if (new == NULL)
    > exit (EXIT_FAILURE);
    > strcpy (new, argv[1]);
    > strcat (new, my_array);
    > my_array = new;
    > }
    >
    > The first line steps the variable i through all the valid index
    > values of the array my_array, executing the body of the loop once
    > for each i value. The second line declares a temporary variable called
    > new that will point to the memory for one of the new strings you're
    > about to create -- you can't just obliterate my_array yet, because
    > you still need to work with the original string it's still pointing to.
    >
    > The third line requests some memory to be allocated. How much?
    > You'll need enough for all the characters of the argv[1] string, plus
    > enough for all the characters of the my_array string, plus one more
    > for the '\0' that must be present at the end of any string. (It is
    > astonishing how frequently people forget about that "plus one;" be
    > on guard against making that all-too-commmon mistake.)
    >
    > The fourth and fifth lines are important: You call malloc to
    > *request* a certain amount of memory, but the request might not be
    > granted. Perhaps the system is running low on memory, perhaps it
    > has plenty available but it's all scattered around in dribs and
    > drabs none of which are big enough, perhaps the phase of the Moon
    > is wrong. *Always* check for a NULL return from malloc, and take
    > corrective action if you get one -- in this case, the "corrective
    > action" is simply to terminate the program unsuccessfully, but in
    > other programs you might do something more elaborate.
    >
    > The sixth and seventh lines build the new string from the two
    > pieces. Line six copies the argv[1] string into the new memory area,
    > and line seven appends the my_array string to it. Note carefully
    > that line six uses strcpy and seven uses strcat; it would be wrong
    > to interchange them or to use the same function (either one) in both
    > places. You need to copy the first string into the uninitialized
    > brand-new memory area, and then append the second.
    >
    > Finally, line eight changes my_array so it now points to the
    > newly-built string.
    >
    > At the beginning of the program, you'll need to #include the
    > <string.h> header (to declare the strlen, strcpy, and strcat functions)
    > and the <stdlib.h> header (for malloc, exit, and EXIT_FAILURE). You
    > may need other headers like <stdio.h> if you intend to display any
    > results. Also, it would be a good idea for your program to check
    > that it actually received an argument string (check for argc>1)
    > before running blindly ahead and trying to do things with a string
    > that doesn't even exist.
    >
    > --
    > Eric Sosman
    > lid
    c, Sep 24, 2006
    #9
  10. c

    Joe Estock Guest

    Frederick Gotham wrote:
    > c posted:
    >
    >> char *my_array [10];

    >
    >
    > This array contains ten elements.
    >
    >
    >> my_array[0] = "Sally\n";
    >> my_array[1] = "Ndiya\n";
    >> my_array[2] = "Samantha\n";
    >> my_array[3] = "Sara\n";
    >> my_array[4] = "Cadillac\n";
    >> my_array[5] = "GM For Ever\n";
    >> my_array[6] = "SlacWare\n";
    >> my_array[7] = "Google\n";
    >> my_array[8] = "Google more and more\n";
    >> my_array[9] = "You\n";
    >> my_array[10] = "Computers\n";

    >
    >
    > Here, you assign to eleven separate elements.


    To someone who is new at C, the above code would not be as easy to
    notice something wrong in.

    In c array indexing starts at 0. When you declare char *my_array[10];
    you are saying the following: "Give me an array of 10 pointers to type
    char". You can now safely assign to 0 - 9 of those without worrying.
    Assigning to anything beyond index 9 would invoke UB (Undefined Behaviour).

    It is also important for you to note that in your declaration you are
    (in laymen terms) saying: "Give me an array of 10 pointers to type char
    that I may not modify after initialization".

    For example:

    char *foo;

    /* this is fine. you are initializing foo */
    foo = "some string";

    /* this is fine too. you are declaring and initializing foo */
    char *foo = "some string";

    /* this is *not* fine. you are writing to memory that you shouldn't */
    foo[3] = '\0';

    char foo[100];

    /* the below is fine. we are allowed to write to foo provided that we do
    not go beyond element 99. */
    strcpy(foo, "testing");

    foo[4] = '\0';

    >
    >
    >> #include <stdio.h>
    >>
    >> int main(int argc,char *argv[])
    >> {int i=-1;
    >> char *my_array [10];
    >>
    >> my_array[0] = "Sally\n";
    >> my_array[1] = "Ndiya\n";
    >> my_array[2] = "Samantha\n";
    >> my_array[3] = "Sara\n";
    >> my_array[4] = "Cadillac\n";
    >> my_array[5] = "GM For Ever\n";
    >> my_array[6] = "SlacWare\n";
    >> my_array[7] = "Google\n";
    >> my_array[8] = "Google more and more\n";
    >> my_array[9] = "You\n";
    >> my_array[10] = "Computers\n";

    >
    >
    > Again here, you assign to eleven elements.
    >
    >
    >> while(i++ < 10)
    >> {
    >> printf(argv[1]); //Don't do it like this..read my comments please.
    >> printf(my_array);
    >> }

    >
    >
    > Why resort to that? Looping 0 through 10 can be much simpler:
    >
    > unsigned i = 0;
    >
    > do {
    >
    > }while(++i != 11);


    This isn't safe, especially if you're suggesting that someone who is
    obviously new to C to use it. What happens if OP increments i within the
    while loop? Consider the following:

    i = 0;

    do
    {
    i += 20;
    } while(++i != 11);

    There you have an infinite loop and the OP may not know what is wrong.
    The code below would give clearer meaning of your intent.

    i = 0;

    do
    {
    /* code */
    } while (++i < 11);

    >
    > Or, if you'd prefer the less efficient simplicity of:
    >
    > for(unsigned i = 0; i != 11; ++i)


    Not valid C89 or C90 syntax. Variable declarations must be at the
    beginning of a block. Again you insist on checking i to see if it is
    *exactly* 11.

    > {
    >
    > }
    >
    > You're still pretending that you're array has eleven elements though...
    >


    It would be more helpful if you could point out to the OP *why* (see my
    reply towards the top).
    Joe Estock, Sep 24, 2006
    #10
  11. c

    Guest

    Frederick Gotham wrote:
    > c posted:
    > > while(i++ < 10)
    > > {
    > > printf(argv[1]); //Don't do it like this..read my comments please.
    > > printf(my_array);
    > > }

    >
    >
    > Why resort to that? Looping 0 through 10 can be much simpler:
    >
    > unsigned i = 0;
    >
    > do {
    >
    > }while(++i != 11);


    These aren't equivalent. His has _2_ off-by-one errors; it loops from
    1 to 10. Yours goes from 0 to 10; you've inadvertantly fixed one
    problem.

    To the OP: You want to loop from 0 to 9. One very common way to do
    that is:

    for(i=0; i<10; i++) {
    /* Do stuff */
    }
    , Sep 24, 2006
    #11
  12. posted:

    > Yours goes from 0 to 10; you've inadvertantly fixed one
    > problem.



    Which is why I mentioned that he was pretending the array had eleven
    elements.

    --

    Frederick Gotham
    Frederick Gotham, Sep 24, 2006
    #12
  13. c

    Jack Klein Guest

    On 24 Sep 2006 06:20:12 -0700, "Ancient_Hacker" <>
    wrote in comp.lang.c:

    Kindly quote at least some context.

    > you can't change anything in that array, as those are all read-only
    > constants.


    In what array? In the OP's code, which you failed to quote:

    > > char *my_array [10];
    > > my_array[0] = "Sally\n";
    > > my_array[1] = "Ndiya\n";
    > > my_array[2] = "Samantha\n";
    > > my_array[3] = "Sara\n";
    > > my_array[4] = "Cadillac\n";
    > > my_array[5] = "GM For Ever\n";
    > > my_array[6] = "SlacWare\n";
    > > my_array[7] = "Google\n";
    > > my_array[8] = "Google more and more\n";
    > > my_array[9] = "You\n";
    > > my_array[10] = "Computers\n";


    The array contains pointers to char. The pointers are not constant at
    all. Nor are the character arrays they point to constant. They are
    string literals, and the type of string literals is "array of char",
    most specifically not "array of const char".

    Attempting to modify a string literal produces undefined behavior in C
    because the C standard specifically states that it does, not because
    the string literal itself has the type "array of const char".

    And there is neither requirement nor guarantee in the C standard that
    string literals are "read-only". The point of having an undefined
    behavior category is that there are no requirements or guarantees on
    the result. On some platforms, writing to string literals changes
    them.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Sep 25, 2006
    #13
  14. Frederick Gotham wrote:
    > c posted:


    <snip>

    > > while(i++ < 10)
    > > {
    > > printf(argv[1]); //Don't do it like this..read my comments please.
    > > printf(my_array);
    > > }

    >
    >
    > Why resort to that? Looping 0 through 10 can be much simpler:
    >
    > unsigned i = 0;
    >
    > do {
    >
    > }while(++i != 11);


    I don't see why your version is simpler than the original. In fact I'd
    say
    while is safer than do just in case the length of the array is
    specified as
    zero.

    > Or, if you'd prefer the less efficient simplicity of:
    >
    > for(unsigned i = 0; i != 11; ++i)
    > {
    >
    > }


    why is this less effiecient? Do you have benchmarks?

    <snip>

    --
    Nick Keighley
    Nick Keighley, Sep 25, 2006
    #14
  15. Nick Keighley posted:

    > Frederick Gotham wrote:
    >> c posted:

    >
    ><snip>
    >
    >> > while(i++ < 10)
    >> > {
    >> > printf(argv[1]); //Don't do it like this..read my comments

    please.
    >> > printf(my_array);
    >> > }

    >>
    >>
    >> Why resort to that? Looping 0 through 10 can be much simpler:
    >>
    >> unsigned i = 0;
    >>
    >> do {
    >>
    >> }while(++i != 11);

    >
    > I don't see why your version is simpler than the original. In fact I'd
    > say
    > while is safer than do just in case the length of the array is
    > specified as
    > zero.
    >
    >> Or, if you'd prefer the less efficient simplicity of:
    >>
    >> for(unsigned i = 0; i != 11; ++i)
    >> {
    >>
    >> }

    >
    > why is this less effiecient? Do you have benchmarks?



    It is less efficient (conceptually) because it performs a redundant
    equality operation. I don't have benchmarks at the moment, but I would
    hazard a guess that the following statement:

    i != 11;

    takes longer to execute than the following statement:

    ;

    --

    Frederick Gotham
    Frederick Gotham, Sep 25, 2006
    #15
  16. c

    Guest

    Frederick Gotham wrote:
    > posted:
    >
    > > Yours goes from 0 to 10; you've inadvertantly fixed one
    > > problem.

    >
    >
    > Which is why I mentioned that he was pretending the array had eleven
    > elements.


    Please disregard my earlier message, I missed his initialization to -1.
    Sorry for the confusion.
    , Sep 25, 2006
    #16
  17. Frederick Gotham wrote:
    > Nick Keighley posted:
    > > Frederick Gotham wrote:
    > >> c posted:


    > >> > while(i++ < 10)
    > >> > {
    > >> > printf(argv[1]); //Don't do it like this..read my comments please.
    > >> > printf(my_array);
    > >> > }
    > >>
    > >>
    > >> Why resort to that? Looping 0 through 10 can be much simpler:
    > >>
    > >> unsigned i = 0;
    > >>
    > >> do {
    > >>
    > >> }while(++i != 11);

    > >
    > > I don't see why your version is simpler than the original. In fact I'd
    > > say while is safer than do just in case the length of the array is
    > > specified as zero.
    > >
    > >> Or, if you'd prefer the less efficient simplicity of:
    > >>
    > >> for(unsigned i = 0; i != 11; ++i)
    > >> {
    > >>
    > >> }

    > >
    > > why is this less effiecient? Do you have benchmarks?

    >
    > It is less efficient (conceptually) because it performs a redundant
    > equality operation. I don't have benchmarks at the moment, but I would
    > hazard a guess that the following statement:
    >
    > i != 11;
    >
    > takes longer to execute than the following statement:
    >
    > ;


    both versions have to perform the test. I wouldn't be surprised if they

    generate identical code. Don't micro-optimse.


    --
    Nick Keighley
    Nick Keighley, Sep 26, 2006
    #17
  18. Nick Keighley posted:

    > both versions have to perform the test. I wouldn't be surprised if they
    >
    > generate identical code. Don't micro-optimse.



    Don't rely on an optimiser.

    If you tell John to drive your car past the neighbouring town to drop it
    into the mechanic, don't just sit back and expect him to take the shorter
    route up past the old cemetary -- explicitly instruct him to do so.

    When you write:

    for(size_t i = 0; max != i; ++i) /* Body */

    you're *explicitly* telling the compiler that the conditional must be
    evaluated before the first iteration. Of course, in accordance with the "as
    if" principle, the compiler may elide the first evaluation if it realises
    that it's utterly redundant (just like John _might_ take the quicker
    route).

    If you _don't_ want the conditional to be evaluated for the first
    iteration, then simply TELL the compiler:

    size_t i = p;

    do /* Body */
    while(max != ++i);

    There's micro-optimisation, and then there's wanton sabotage of the
    efficiency of one's code by being lax and saying "Hey compiler, just get
    the job done however you like, I'm not too pushed whether it's efficient or
    not."

    --

    Frederick Gotham
    Frederick Gotham, Sep 26, 2006
    #18
  19. Frederick Gotham wrote:
    > Nick Keighley posted:


    my reply isn't really addressed to Frederick Gotham as he has
    demonstrated before that once he has an idea fixed in his head it's
    hard to shift. I'm more expressing what I believe to be the balance
    of opinion amongst experienced programmers for the benefit of the
    lurkers.


    > > both versions have to perform the test. I wouldn't be surprised if they
    > > generate identical code.


    to be honest, I'd be astonished if they generated different code.

    > > Don't micro-optimse.


    "premature optimistation is the root of all evil"


    > Don't rely on an optimiser.


    ***DO*** rely on the optimser. Changing your optimisation level might
    take
    a few minutes to recompile. Analysing and optimising an application may

    take days, or weeks.


    > If you tell John to drive your car past the neighbouring town to drop it
    > into the mechanic, don't just sit back and expect him to take the shorter
    > route up past the old cemetary -- explicitly instruct him to do so.


    bad analogy. John is not an optimising compiler.


    > When you write:
    >
    > for(size_t i = 0; max != i; ++i) /* Body */
    >
    > you're *explicitly* telling the compiler that the conditional must be
    > evaluated before the first iteration.


    which, of course is what I want... You snipped the bit where I said I
    wouldn't normally replace while-loop with a do-loop. It's not 1957
    anymore and we don't program in FORTRAN.


    > Of course, in accordance with the "as
    > if" principle, the compiler may elide the first evaluation if it realises
    > that it's utterly redundant (just like John _might_ take the quicker
    > route).
    >
    > If you _don't_ want the conditional to be evaluated for the first
    > iteration, then simply TELL the compiler:
    >
    > size_t i = p;
    >
    > do /* Body */
    > while(max != ++i);
    >
    > There's micro-optimisation, and then there's wanton sabotage of the
    > efficiency of one's code by being lax and saying "Hey compiler, just get
    > the job done however you like, I'm not too pushed whether it's efficient or
    > not."


    yes, and this is *not* an example. If I use bubble sort instead of
    quicksort I can hardly expect the compiler to fix my error.

    Choose good algorithms, write clear simple code. If it is too slow
    then use a profiler and find out where it is slow. Only then start
    applying optimsation tricks.

    Your pessimisation saves one test at loop setup and is slightly more
    insecure.


    --
    Nick Keighley

    "There are two ways of constructing a software design: One way is to
    make it so simple that there are obviously no deficiencies, and the
    other way is to make it so complicated that there are no obvious
    deficiencies. The first method is far more difficult."
    -- C.A.R. Hoare
    Nick Keighley, Sep 27, 2006
    #19
  20. Frederick Gotham schrieb:
    > Nick Keighley posted:
    >
    >> both versions have to perform the test. I wouldn't be surprised if they
    >> generate identical code. Don't micro-optimse.

    >
    > Don't rely on an optimiser.


    Do you know this - not directly C or C++ related - article?
    http://www.flounder.com/optimization.htm

    > When you write:
    >
    > for(size_t i = 0; max != i; ++i) /* Body */
    >
    > you're *explicitly* telling the compiler that the conditional must be
    > evaluated before the first iteration. Of course, in accordance with the "as
    > if" principle, the compiler may elide the first evaluation if it realises
    > that it's utterly redundant (just like John _might_ take the quicker
    > route).
    >
    > If you _don't_ want the conditional to be evaluated for the first
    > iteration, then simply TELL the compiler:
    >
    > size_t i = p;
    >
    > do /* Body */
    > while(max != ++i);


    If you _know_, that max never ever may fall to zero, you can do it.
    However, a simple compare of two variables that are already stored in
    registers won't do any damage. A buffer overflow caused by a superfluous
    and redundant check, sacrificed for a few microseconds, will do damage.

    --
    Thomas
    http://www.netmeister.org/news/learn2quote.html
    Thomas J. Gritzan, Sep 28, 2006
    #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. Stan Horwitz
    Replies:
    2
    Views:
    2,731
    Stan Horwitz
    Feb 15, 2006
  2. Replies:
    11
    Views:
    615
    Karl Heinz Buchegger
    Apr 8, 2005
  3. John Henry

    Concatenating strings

    John Henry, Jul 1, 2006, in forum: Python
    Replies:
    1
    Views:
    301
    Steven Bethard
    Jul 1, 2006
  4. John Henry

    Concatenating strings

    John Henry, Jul 1, 2006, in forum: Python
    Replies:
    1
    Views:
    325
    Robert Kern
    Jul 1, 2006
  5. EHC

    concatenating strings

    EHC, Dec 15, 2006, in forum: Python
    Replies:
    3
    Views:
    317
    Caleb Hattingh
    Dec 16, 2006
Loading...

Share This Page