Create 2D array of dynamic size in C









up vote
-1
down vote

favorite












Let's say we have a string of words that are delimited by a comma.
I want to write a code in C to store these words in a variable.



Example




amazon, google, facebook, twitter, salesforce, sfb



We do not know how many words are present.



If I were to do this in C, I thought I need to do 2 iterations.
First iteration, I count how many words are present.
Then, in the next iteration, I store each words.



Step 1: 1st loop -- count number of words
....
....
//End 1st loop. num_words is set.

Step 2:
// Do malloc using num_words.
char **array = (char**)malloc(num_words* sizeof(char*));

Step 3: 2nd loop -- Store each word.
// First, walk until the delimiter and determine the length of the word
// Once len_word is determined, do malloc
*array= (char*)malloc(len_word * sizeof(char));
// And then store the word to it

// Do this for all words and then the 2nd loop terminates


Can this be done more efficiently?
I do not like having 2 loops. I think there must be a way to do it in 1 loop with just basic pointers.



The only restriction is that this needs to be done in C (due to constraints that are not in my control)










share|improve this question























  • Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
    – John Bollinger
    Nov 10 at 19:22






  • 1




    without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
    – mangusta
    Nov 10 at 19:25















up vote
-1
down vote

favorite












Let's say we have a string of words that are delimited by a comma.
I want to write a code in C to store these words in a variable.



Example




amazon, google, facebook, twitter, salesforce, sfb



We do not know how many words are present.



If I were to do this in C, I thought I need to do 2 iterations.
First iteration, I count how many words are present.
Then, in the next iteration, I store each words.



Step 1: 1st loop -- count number of words
....
....
//End 1st loop. num_words is set.

Step 2:
// Do malloc using num_words.
char **array = (char**)malloc(num_words* sizeof(char*));

Step 3: 2nd loop -- Store each word.
// First, walk until the delimiter and determine the length of the word
// Once len_word is determined, do malloc
*array= (char*)malloc(len_word * sizeof(char));
// And then store the word to it

// Do this for all words and then the 2nd loop terminates


Can this be done more efficiently?
I do not like having 2 loops. I think there must be a way to do it in 1 loop with just basic pointers.



The only restriction is that this needs to be done in C (due to constraints that are not in my control)










share|improve this question























  • Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
    – John Bollinger
    Nov 10 at 19:22






  • 1




    without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
    – mangusta
    Nov 10 at 19:25













up vote
-1
down vote

favorite









up vote
-1
down vote

favorite











Let's say we have a string of words that are delimited by a comma.
I want to write a code in C to store these words in a variable.



Example




amazon, google, facebook, twitter, salesforce, sfb



We do not know how many words are present.



If I were to do this in C, I thought I need to do 2 iterations.
First iteration, I count how many words are present.
Then, in the next iteration, I store each words.



Step 1: 1st loop -- count number of words
....
....
//End 1st loop. num_words is set.

Step 2:
// Do malloc using num_words.
char **array = (char**)malloc(num_words* sizeof(char*));

Step 3: 2nd loop -- Store each word.
// First, walk until the delimiter and determine the length of the word
// Once len_word is determined, do malloc
*array= (char*)malloc(len_word * sizeof(char));
// And then store the word to it

// Do this for all words and then the 2nd loop terminates


Can this be done more efficiently?
I do not like having 2 loops. I think there must be a way to do it in 1 loop with just basic pointers.



The only restriction is that this needs to be done in C (due to constraints that are not in my control)










share|improve this question















Let's say we have a string of words that are delimited by a comma.
I want to write a code in C to store these words in a variable.



Example




amazon, google, facebook, twitter, salesforce, sfb



We do not know how many words are present.



If I were to do this in C, I thought I need to do 2 iterations.
First iteration, I count how many words are present.
Then, in the next iteration, I store each words.



Step 1: 1st loop -- count number of words
....
....
//End 1st loop. num_words is set.

Step 2:
// Do malloc using num_words.
char **array = (char**)malloc(num_words* sizeof(char*));

Step 3: 2nd loop -- Store each word.
// First, walk until the delimiter and determine the length of the word
// Once len_word is determined, do malloc
*array= (char*)malloc(len_word * sizeof(char));
// And then store the word to it

// Do this for all words and then the 2nd loop terminates


Can this be done more efficiently?
I do not like having 2 loops. I think there must be a way to do it in 1 loop with just basic pointers.



The only restriction is that this needs to be done in C (due to constraints that are not in my control)







c pointers






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 17:52

























asked Nov 10 at 19:06









sh0731

391620




391620











  • Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
    – John Bollinger
    Nov 10 at 19:22






  • 1




    without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
    – mangusta
    Nov 10 at 19:25

















  • Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
    – John Bollinger
    Nov 10 at 19:22






  • 1




    without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
    – mangusta
    Nov 10 at 19:25
















Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
– John Bollinger
Nov 10 at 19:22




Note: sizeof(void) is invalid, because void is an incomplete type. Your probably meant sizeof(char *) or sizeof(*array).
– John Bollinger
Nov 10 at 19:22




1




1




without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
– mangusta
Nov 10 at 19:25





without counting words, you may use "malloc" for the first word and then increase the size of double array by using "realloc" for every new word
– mangusta
Nov 10 at 19:25













3 Answers
3






active

oldest

votes

















up vote
1
down vote













You don't need to do a separate pass to count the words. You can use realloc to enlarge the array on the fly as you read in the data on a single pass.



To parse an input line buffer, you can use strtok to tokenize the individual words.



When saving the parsed words into the word list array, you can use strdup to create a copy of the tokenized word. This is necessary for the word to persist. That is, whatever you were pointing to in the line buffer on the first line will get clobbered when you read the second line (and so on ...)



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

char **words;
size_t wordmax;
size_t wordcount;

int
main(int argc,char **argv)

char *cp;
char *bp;
FILE *fi;
char buf[5000];

--argc;
++argv;

// get input file name
cp = *argv;
if (cp == NULL)
printf("no file specifiedn");
exit(1);


// open input file
fi = fopen(cp,"r");
if (fi == NULL)
printf("unable to open file '%s' -- %sn",cp,strerror(errno));
exit(1);


while (1)
// read in next line -- bug out if EOF
cp = fgets(buf,sizeof(buf),fi);
if (cp == NULL)
break;

bp = buf;
while (1)
// tokenize the word
cp = strtok(bp," t,n");
if (cp == NULL)
break;
bp = NULL;

// expand the space allocated for the word list [if necessary]
if (wordcount >= wordmax)
// this is an expensive operation so don't do it too often
wordmax += 100;

words = realloc(words,(wordmax + 1) * sizeof(char *));
if (words == NULL)
printf("out of memoryn");
exit(1);



// get a persistent copy of the word text
cp = strdup(cp);
if (cp == NULL)
printf("out of memoryn");
exit(1);


// save the word into the word array
words[wordcount++] = cp;



// close the input file
fclose(fi);

// add a null terminator
words[wordcount] = NULL;

// trim the array to exactly what we need/used
words = realloc(words,(wordcount + 1) * sizeof(char *));

// NOTE: because we added the terminator, _either_ of these loops will
// print the word list
#if 1
for (size_t idx = 0; idx < wordcount; ++idx)
printf("%sn",words[idx]);
#else
for (char **word = words; *word != NULL; ++word)
printf("%sn",*word);
#endif

return 0;






share|improve this answer





























    up vote
    0
    down vote













    What you're looking for is
    http://manpagesfr.free.fr/man/man3/strtok.3.html



    (From man page)




    The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.




    But this thread look like duplicate of Split string with delimiters in C
    Unless you are forced to produce your own implementation ...






    share|improve this answer




















    • This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
      – John Bollinger
      Nov 10 at 19:28

















    up vote
    0
    down vote














    We do not know how many words are present.




    We know num_words <= strlen(string) + 1. Only 1 "loop" needed. The cheat here is a quick run down s via strlen().



    // *alloc() out-of-memory checking omitted for brevity
    char **parse_csv(const char *s)
    size_t slen = strlen(s);
    size_t num_words = 0;
    char **words = malloc(sizeof *words * (slen + 1));

    // find, allocate, copy the words
    while (*s)
    size_t len = strcspn(s, ",");
    words[num_words] = malloc(len + 1);
    memcpy(words[num_words], s, len);
    words[num_words][len] = '';
    num_words++;
    s += len; // skip word
    if (*s) s++; // skip ,


    // Only 1 realloc() needed.
    realloc(words, sizeof *words *num_words); // right-size words list
    return words;



    It makes send to NULL terminate the list, so



     char **words = malloc(sizeof *words * (slen + 1 + 1));
    ...
    words[num_words++] = NULL;
    realloc(words, sizeof *words *num_words);
    return words;



    In considering the worst case for the initial char **words = malloc(...);, I take a string like ",,," with its 3 ',' would make for 4 words "", "", "", "". Adjust code as needed for such pathological cases.






    share|improve this answer






















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242449%2fcreate-2d-array-of-dynamic-size-in-c%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      1
      down vote













      You don't need to do a separate pass to count the words. You can use realloc to enlarge the array on the fly as you read in the data on a single pass.



      To parse an input line buffer, you can use strtok to tokenize the individual words.



      When saving the parsed words into the word list array, you can use strdup to create a copy of the tokenized word. This is necessary for the word to persist. That is, whatever you were pointing to in the line buffer on the first line will get clobbered when you read the second line (and so on ...)



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

      char **words;
      size_t wordmax;
      size_t wordcount;

      int
      main(int argc,char **argv)

      char *cp;
      char *bp;
      FILE *fi;
      char buf[5000];

      --argc;
      ++argv;

      // get input file name
      cp = *argv;
      if (cp == NULL)
      printf("no file specifiedn");
      exit(1);


      // open input file
      fi = fopen(cp,"r");
      if (fi == NULL)
      printf("unable to open file '%s' -- %sn",cp,strerror(errno));
      exit(1);


      while (1)
      // read in next line -- bug out if EOF
      cp = fgets(buf,sizeof(buf),fi);
      if (cp == NULL)
      break;

      bp = buf;
      while (1)
      // tokenize the word
      cp = strtok(bp," t,n");
      if (cp == NULL)
      break;
      bp = NULL;

      // expand the space allocated for the word list [if necessary]
      if (wordcount >= wordmax)
      // this is an expensive operation so don't do it too often
      wordmax += 100;

      words = realloc(words,(wordmax + 1) * sizeof(char *));
      if (words == NULL)
      printf("out of memoryn");
      exit(1);



      // get a persistent copy of the word text
      cp = strdup(cp);
      if (cp == NULL)
      printf("out of memoryn");
      exit(1);


      // save the word into the word array
      words[wordcount++] = cp;



      // close the input file
      fclose(fi);

      // add a null terminator
      words[wordcount] = NULL;

      // trim the array to exactly what we need/used
      words = realloc(words,(wordcount + 1) * sizeof(char *));

      // NOTE: because we added the terminator, _either_ of these loops will
      // print the word list
      #if 1
      for (size_t idx = 0; idx < wordcount; ++idx)
      printf("%sn",words[idx]);
      #else
      for (char **word = words; *word != NULL; ++word)
      printf("%sn",*word);
      #endif

      return 0;






      share|improve this answer


























        up vote
        1
        down vote













        You don't need to do a separate pass to count the words. You can use realloc to enlarge the array on the fly as you read in the data on a single pass.



        To parse an input line buffer, you can use strtok to tokenize the individual words.



        When saving the parsed words into the word list array, you can use strdup to create a copy of the tokenized word. This is necessary for the word to persist. That is, whatever you were pointing to in the line buffer on the first line will get clobbered when you read the second line (and so on ...)



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

        char **words;
        size_t wordmax;
        size_t wordcount;

        int
        main(int argc,char **argv)

        char *cp;
        char *bp;
        FILE *fi;
        char buf[5000];

        --argc;
        ++argv;

        // get input file name
        cp = *argv;
        if (cp == NULL)
        printf("no file specifiedn");
        exit(1);


        // open input file
        fi = fopen(cp,"r");
        if (fi == NULL)
        printf("unable to open file '%s' -- %sn",cp,strerror(errno));
        exit(1);


        while (1)
        // read in next line -- bug out if EOF
        cp = fgets(buf,sizeof(buf),fi);
        if (cp == NULL)
        break;

        bp = buf;
        while (1)
        // tokenize the word
        cp = strtok(bp," t,n");
        if (cp == NULL)
        break;
        bp = NULL;

        // expand the space allocated for the word list [if necessary]
        if (wordcount >= wordmax)
        // this is an expensive operation so don't do it too often
        wordmax += 100;

        words = realloc(words,(wordmax + 1) * sizeof(char *));
        if (words == NULL)
        printf("out of memoryn");
        exit(1);



        // get a persistent copy of the word text
        cp = strdup(cp);
        if (cp == NULL)
        printf("out of memoryn");
        exit(1);


        // save the word into the word array
        words[wordcount++] = cp;



        // close the input file
        fclose(fi);

        // add a null terminator
        words[wordcount] = NULL;

        // trim the array to exactly what we need/used
        words = realloc(words,(wordcount + 1) * sizeof(char *));

        // NOTE: because we added the terminator, _either_ of these loops will
        // print the word list
        #if 1
        for (size_t idx = 0; idx < wordcount; ++idx)
        printf("%sn",words[idx]);
        #else
        for (char **word = words; *word != NULL; ++word)
        printf("%sn",*word);
        #endif

        return 0;






        share|improve this answer
























          up vote
          1
          down vote










          up vote
          1
          down vote









          You don't need to do a separate pass to count the words. You can use realloc to enlarge the array on the fly as you read in the data on a single pass.



          To parse an input line buffer, you can use strtok to tokenize the individual words.



          When saving the parsed words into the word list array, you can use strdup to create a copy of the tokenized word. This is necessary for the word to persist. That is, whatever you were pointing to in the line buffer on the first line will get clobbered when you read the second line (and so on ...)



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

          char **words;
          size_t wordmax;
          size_t wordcount;

          int
          main(int argc,char **argv)

          char *cp;
          char *bp;
          FILE *fi;
          char buf[5000];

          --argc;
          ++argv;

          // get input file name
          cp = *argv;
          if (cp == NULL)
          printf("no file specifiedn");
          exit(1);


          // open input file
          fi = fopen(cp,"r");
          if (fi == NULL)
          printf("unable to open file '%s' -- %sn",cp,strerror(errno));
          exit(1);


          while (1)
          // read in next line -- bug out if EOF
          cp = fgets(buf,sizeof(buf),fi);
          if (cp == NULL)
          break;

          bp = buf;
          while (1)
          // tokenize the word
          cp = strtok(bp," t,n");
          if (cp == NULL)
          break;
          bp = NULL;

          // expand the space allocated for the word list [if necessary]
          if (wordcount >= wordmax)
          // this is an expensive operation so don't do it too often
          wordmax += 100;

          words = realloc(words,(wordmax + 1) * sizeof(char *));
          if (words == NULL)
          printf("out of memoryn");
          exit(1);



          // get a persistent copy of the word text
          cp = strdup(cp);
          if (cp == NULL)
          printf("out of memoryn");
          exit(1);


          // save the word into the word array
          words[wordcount++] = cp;



          // close the input file
          fclose(fi);

          // add a null terminator
          words[wordcount] = NULL;

          // trim the array to exactly what we need/used
          words = realloc(words,(wordcount + 1) * sizeof(char *));

          // NOTE: because we added the terminator, _either_ of these loops will
          // print the word list
          #if 1
          for (size_t idx = 0; idx < wordcount; ++idx)
          printf("%sn",words[idx]);
          #else
          for (char **word = words; *word != NULL; ++word)
          printf("%sn",*word);
          #endif

          return 0;






          share|improve this answer














          You don't need to do a separate pass to count the words. You can use realloc to enlarge the array on the fly as you read in the data on a single pass.



          To parse an input line buffer, you can use strtok to tokenize the individual words.



          When saving the parsed words into the word list array, you can use strdup to create a copy of the tokenized word. This is necessary for the word to persist. That is, whatever you were pointing to in the line buffer on the first line will get clobbered when you read the second line (and so on ...)



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

          char **words;
          size_t wordmax;
          size_t wordcount;

          int
          main(int argc,char **argv)

          char *cp;
          char *bp;
          FILE *fi;
          char buf[5000];

          --argc;
          ++argv;

          // get input file name
          cp = *argv;
          if (cp == NULL)
          printf("no file specifiedn");
          exit(1);


          // open input file
          fi = fopen(cp,"r");
          if (fi == NULL)
          printf("unable to open file '%s' -- %sn",cp,strerror(errno));
          exit(1);


          while (1)
          // read in next line -- bug out if EOF
          cp = fgets(buf,sizeof(buf),fi);
          if (cp == NULL)
          break;

          bp = buf;
          while (1)
          // tokenize the word
          cp = strtok(bp," t,n");
          if (cp == NULL)
          break;
          bp = NULL;

          // expand the space allocated for the word list [if necessary]
          if (wordcount >= wordmax)
          // this is an expensive operation so don't do it too often
          wordmax += 100;

          words = realloc(words,(wordmax + 1) * sizeof(char *));
          if (words == NULL)
          printf("out of memoryn");
          exit(1);



          // get a persistent copy of the word text
          cp = strdup(cp);
          if (cp == NULL)
          printf("out of memoryn");
          exit(1);


          // save the word into the word array
          words[wordcount++] = cp;



          // close the input file
          fclose(fi);

          // add a null terminator
          words[wordcount] = NULL;

          // trim the array to exactly what we need/used
          words = realloc(words,(wordcount + 1) * sizeof(char *));

          // NOTE: because we added the terminator, _either_ of these loops will
          // print the word list
          #if 1
          for (size_t idx = 0; idx < wordcount; ++idx)
          printf("%sn",words[idx]);
          #else
          for (char **word = words; *word != NULL; ++word)
          printf("%sn",*word);
          #endif

          return 0;







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 10 at 20:34

























          answered Nov 10 at 19:30









          Craig Estey

          13.5k21029




          13.5k21029






















              up vote
              0
              down vote













              What you're looking for is
              http://manpagesfr.free.fr/man/man3/strtok.3.html



              (From man page)




              The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.




              But this thread look like duplicate of Split string with delimiters in C
              Unless you are forced to produce your own implementation ...






              share|improve this answer




















              • This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
                – John Bollinger
                Nov 10 at 19:28














              up vote
              0
              down vote













              What you're looking for is
              http://manpagesfr.free.fr/man/man3/strtok.3.html



              (From man page)




              The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.




              But this thread look like duplicate of Split string with delimiters in C
              Unless you are forced to produce your own implementation ...






              share|improve this answer




















              • This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
                – John Bollinger
                Nov 10 at 19:28












              up vote
              0
              down vote










              up vote
              0
              down vote









              What you're looking for is
              http://manpagesfr.free.fr/man/man3/strtok.3.html



              (From man page)




              The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.




              But this thread look like duplicate of Split string with delimiters in C
              Unless you are forced to produce your own implementation ...






              share|improve this answer












              What you're looking for is
              http://manpagesfr.free.fr/man/man3/strtok.3.html



              (From man page)




              The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL.




              But this thread look like duplicate of Split string with delimiters in C
              Unless you are forced to produce your own implementation ...







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 10 at 19:21









              Asya Corbeau

              111




              111











              • This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
                – John Bollinger
                Nov 10 at 19:28
















              • This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
                – John Bollinger
                Nov 10 at 19:28















              This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
              – John Bollinger
              Nov 10 at 19:28




              This does not seem responsive to the question, which is about an approach that avoids separate loops for counting strings and recording the split results. Yes, strtok could be used in such a pursuit, but it is not the key here.
              – John Bollinger
              Nov 10 at 19:28










              up vote
              0
              down vote














              We do not know how many words are present.




              We know num_words <= strlen(string) + 1. Only 1 "loop" needed. The cheat here is a quick run down s via strlen().



              // *alloc() out-of-memory checking omitted for brevity
              char **parse_csv(const char *s)
              size_t slen = strlen(s);
              size_t num_words = 0;
              char **words = malloc(sizeof *words * (slen + 1));

              // find, allocate, copy the words
              while (*s)
              size_t len = strcspn(s, ",");
              words[num_words] = malloc(len + 1);
              memcpy(words[num_words], s, len);
              words[num_words][len] = '';
              num_words++;
              s += len; // skip word
              if (*s) s++; // skip ,


              // Only 1 realloc() needed.
              realloc(words, sizeof *words *num_words); // right-size words list
              return words;



              It makes send to NULL terminate the list, so



               char **words = malloc(sizeof *words * (slen + 1 + 1));
              ...
              words[num_words++] = NULL;
              realloc(words, sizeof *words *num_words);
              return words;



              In considering the worst case for the initial char **words = malloc(...);, I take a string like ",,," with its 3 ',' would make for 4 words "", "", "", "". Adjust code as needed for such pathological cases.






              share|improve this answer


























                up vote
                0
                down vote














                We do not know how many words are present.




                We know num_words <= strlen(string) + 1. Only 1 "loop" needed. The cheat here is a quick run down s via strlen().



                // *alloc() out-of-memory checking omitted for brevity
                char **parse_csv(const char *s)
                size_t slen = strlen(s);
                size_t num_words = 0;
                char **words = malloc(sizeof *words * (slen + 1));

                // find, allocate, copy the words
                while (*s)
                size_t len = strcspn(s, ",");
                words[num_words] = malloc(len + 1);
                memcpy(words[num_words], s, len);
                words[num_words][len] = '';
                num_words++;
                s += len; // skip word
                if (*s) s++; // skip ,


                // Only 1 realloc() needed.
                realloc(words, sizeof *words *num_words); // right-size words list
                return words;



                It makes send to NULL terminate the list, so



                 char **words = malloc(sizeof *words * (slen + 1 + 1));
                ...
                words[num_words++] = NULL;
                realloc(words, sizeof *words *num_words);
                return words;



                In considering the worst case for the initial char **words = malloc(...);, I take a string like ",,," with its 3 ',' would make for 4 words "", "", "", "". Adjust code as needed for such pathological cases.






                share|improve this answer
























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote










                  We do not know how many words are present.




                  We know num_words <= strlen(string) + 1. Only 1 "loop" needed. The cheat here is a quick run down s via strlen().



                  // *alloc() out-of-memory checking omitted for brevity
                  char **parse_csv(const char *s)
                  size_t slen = strlen(s);
                  size_t num_words = 0;
                  char **words = malloc(sizeof *words * (slen + 1));

                  // find, allocate, copy the words
                  while (*s)
                  size_t len = strcspn(s, ",");
                  words[num_words] = malloc(len + 1);
                  memcpy(words[num_words], s, len);
                  words[num_words][len] = '';
                  num_words++;
                  s += len; // skip word
                  if (*s) s++; // skip ,


                  // Only 1 realloc() needed.
                  realloc(words, sizeof *words *num_words); // right-size words list
                  return words;



                  It makes send to NULL terminate the list, so



                   char **words = malloc(sizeof *words * (slen + 1 + 1));
                  ...
                  words[num_words++] = NULL;
                  realloc(words, sizeof *words *num_words);
                  return words;



                  In considering the worst case for the initial char **words = malloc(...);, I take a string like ",,," with its 3 ',' would make for 4 words "", "", "", "". Adjust code as needed for such pathological cases.






                  share|improve this answer















                  We do not know how many words are present.




                  We know num_words <= strlen(string) + 1. Only 1 "loop" needed. The cheat here is a quick run down s via strlen().



                  // *alloc() out-of-memory checking omitted for brevity
                  char **parse_csv(const char *s)
                  size_t slen = strlen(s);
                  size_t num_words = 0;
                  char **words = malloc(sizeof *words * (slen + 1));

                  // find, allocate, copy the words
                  while (*s)
                  size_t len = strcspn(s, ",");
                  words[num_words] = malloc(len + 1);
                  memcpy(words[num_words], s, len);
                  words[num_words][len] = '';
                  num_words++;
                  s += len; // skip word
                  if (*s) s++; // skip ,


                  // Only 1 realloc() needed.
                  realloc(words, sizeof *words *num_words); // right-size words list
                  return words;



                  It makes send to NULL terminate the list, so



                   char **words = malloc(sizeof *words * (slen + 1 + 1));
                  ...
                  words[num_words++] = NULL;
                  realloc(words, sizeof *words *num_words);
                  return words;



                  In considering the worst case for the initial char **words = malloc(...);, I take a string like ",,," with its 3 ',' would make for 4 words "", "", "", "". Adjust code as needed for such pathological cases.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 10 at 20:08

























                  answered Nov 10 at 19:50









                  chux

                  78.4k869143




                  78.4k869143



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242449%2fcreate-2d-array-of-dynamic-size-in-c%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      How to read a connectionString WITH PROVIDER in .NET Core?

                      Node.js Script on GitHub Pages or Amazon S3

                      Museum of Modern and Contemporary Art of Trento and Rovereto