Adding element to an array of strings










0














I've got an array of strings



char **tab;


and I want it to be able to increase as user types in new strings. I've created this code:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv)

char **tab=malloc(sizeof(char*));
tab[0]=malloc(41*sizeof(char));
int i=0;
int d=0;
while(strcmp(tab[i],"END"))

if(d==0)

i--;
d++;

i++;
scanf("%s",tab[i]);
**tab=realloc(tab,(i+2)*sizeof(char*));
tab[i+1]=malloc(41*sizeof(char));

return 0;



its purpose is to read new strings to tab untill user writes keyword "END". Since it's not known how many words will be inputted I tried to reallocate the size of array after each iteration. Unfortunately it prints Segmentation fault after getting 3 words.
What did i do wrong? Is there any better way to do this task?



Maximum length of any word is 40










share|improve this question

















  • 1




    tab=realloc(tab, ...
    – Stephan Lechner
    Nov 12 '18 at 19:18






  • 2




    in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
    – WhozCraig
    Nov 12 '18 at 19:19











  • It worked! Thank You. I can't even tell how dumb I feel right now
    – Igor
    Nov 12 '18 at 19:21






  • 1




    Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
    – 4386427
    Nov 12 '18 at 19:21











  • You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
    – 4386427
    Nov 12 '18 at 19:25















0














I've got an array of strings



char **tab;


and I want it to be able to increase as user types in new strings. I've created this code:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv)

char **tab=malloc(sizeof(char*));
tab[0]=malloc(41*sizeof(char));
int i=0;
int d=0;
while(strcmp(tab[i],"END"))

if(d==0)

i--;
d++;

i++;
scanf("%s",tab[i]);
**tab=realloc(tab,(i+2)*sizeof(char*));
tab[i+1]=malloc(41*sizeof(char));

return 0;



its purpose is to read new strings to tab untill user writes keyword "END". Since it's not known how many words will be inputted I tried to reallocate the size of array after each iteration. Unfortunately it prints Segmentation fault after getting 3 words.
What did i do wrong? Is there any better way to do this task?



Maximum length of any word is 40










share|improve this question

















  • 1




    tab=realloc(tab, ...
    – Stephan Lechner
    Nov 12 '18 at 19:18






  • 2




    in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
    – WhozCraig
    Nov 12 '18 at 19:19











  • It worked! Thank You. I can't even tell how dumb I feel right now
    – Igor
    Nov 12 '18 at 19:21






  • 1




    Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
    – 4386427
    Nov 12 '18 at 19:21











  • You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
    – 4386427
    Nov 12 '18 at 19:25













0












0








0







I've got an array of strings



char **tab;


and I want it to be able to increase as user types in new strings. I've created this code:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv)

char **tab=malloc(sizeof(char*));
tab[0]=malloc(41*sizeof(char));
int i=0;
int d=0;
while(strcmp(tab[i],"END"))

if(d==0)

i--;
d++;

i++;
scanf("%s",tab[i]);
**tab=realloc(tab,(i+2)*sizeof(char*));
tab[i+1]=malloc(41*sizeof(char));

return 0;



its purpose is to read new strings to tab untill user writes keyword "END". Since it's not known how many words will be inputted I tried to reallocate the size of array after each iteration. Unfortunately it prints Segmentation fault after getting 3 words.
What did i do wrong? Is there any better way to do this task?



Maximum length of any word is 40










share|improve this question













I've got an array of strings



char **tab;


and I want it to be able to increase as user types in new strings. I've created this code:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv)

char **tab=malloc(sizeof(char*));
tab[0]=malloc(41*sizeof(char));
int i=0;
int d=0;
while(strcmp(tab[i],"END"))

if(d==0)

i--;
d++;

i++;
scanf("%s",tab[i]);
**tab=realloc(tab,(i+2)*sizeof(char*));
tab[i+1]=malloc(41*sizeof(char));

return 0;



its purpose is to read new strings to tab untill user writes keyword "END". Since it's not known how many words will be inputted I tried to reallocate the size of array after each iteration. Unfortunately it prints Segmentation fault after getting 3 words.
What did i do wrong? Is there any better way to do this task?



Maximum length of any word is 40







c arrays string malloc






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 '18 at 19:16









Igor

193




193







  • 1




    tab=realloc(tab, ...
    – Stephan Lechner
    Nov 12 '18 at 19:18






  • 2




    in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
    – WhozCraig
    Nov 12 '18 at 19:19











  • It worked! Thank You. I can't even tell how dumb I feel right now
    – Igor
    Nov 12 '18 at 19:21






  • 1




    Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
    – 4386427
    Nov 12 '18 at 19:21











  • You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
    – 4386427
    Nov 12 '18 at 19:25












  • 1




    tab=realloc(tab, ...
    – Stephan Lechner
    Nov 12 '18 at 19:18






  • 2




    in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
    – WhozCraig
    Nov 12 '18 at 19:19











  • It worked! Thank You. I can't even tell how dumb I feel right now
    – Igor
    Nov 12 '18 at 19:21






  • 1




    Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
    – 4386427
    Nov 12 '18 at 19:21











  • You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
    – 4386427
    Nov 12 '18 at 19:25







1




1




tab=realloc(tab, ...
– Stephan Lechner
Nov 12 '18 at 19:18




tab=realloc(tab, ...
– Stephan Lechner
Nov 12 '18 at 19:18




2




2




in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
– WhozCraig
Nov 12 '18 at 19:19





in the loop body, **tab=... ===> tab = .... Unrelated, this algorithm is inefficient, and more important, broken if you expect no allocations in the event the first string entered is "END". Just saying.
– WhozCraig
Nov 12 '18 at 19:19













It worked! Thank You. I can't even tell how dumb I feel right now
– Igor
Nov 12 '18 at 19:21




It worked! Thank You. I can't even tell how dumb I feel right now
– Igor
Nov 12 '18 at 19:21




1




1




Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
– 4386427
Nov 12 '18 at 19:21





Here while(strcmp(tab[i],"END")) the string variable pointed to by tab[i] is uninitialized. You could consider calloc instead of malloc
– 4386427
Nov 12 '18 at 19:21













You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
– 4386427
Nov 12 '18 at 19:25




You don't need the if(d==0) … part. Just move the i++ just below scanf("%s",tab[i]);
– 4386427
Nov 12 '18 at 19:25












2 Answers
2






active

oldest

votes


















1














Your algorithm is broken in two significant places




  • **tab = ... in the loop body is wrong. If tab is char**, then *tab would be char*, and **tab would be char. Assigning a memory address to char should flag huge warnings from your toolchain, and if it doesn't either turn up your warning levels or get a new toolchain.

  • Initial entry to your while condition evaluates indeterminate data. At that time you have allocated raw memory for tab[0], but nothing has populated it yet. Therefore, your program invokes undefined behavior.

Besides the above, expansion algorithms aren't complex, and explaining yours to your rubber-duck will help significantly before writing any code. In doing so, you'll see reallocating a pointer array with each new read is both costly and inefficient. A geometric expansion algorithms makes this much better. As a bonus, it fixes both of the problems above.



Code



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

#define MAX_BUFLEN 41
#define MAX_STR_FMT "%40s"

int main()

char **tab = NULL;
size_t size = 0, capacity = 0;

char str[MAX_BUFLEN];

while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

// check for expansion
if (size == capacity)

size_t new_capacity = 2 * capacity + 1;
void *tmp = realloc(tab, new_capacity * sizeof *tab);
if (tmp == NULL)

perror("Failed to expand dynamic table");
break;


// save expanded table, and update capacity
tab = tmp;
capacity = new_capacity;


size_t slen = strlen(str)+1;
if ((tab[size] = malloc(slen)) == NULL)

perror("Failed to allocate buffer for new string");
break;


// copy incoming string; update 'size' to reflect new count
memcpy(tab[size++], str, slen);


//
// TODO: use 'tab' holding 'size' pointers.
//

// then free the table
while (size-- > 0)
free(tab[size]);
free(tab);

return 0;




Alternative: No pointers to pointers



If your need truly requires fixed length allocations (as your code demonstrates), you don't need pointers to pointers at all (unless there is some hidden agenda for something like sorting where swapping pointers is much more efficient than swapping full string buffers).



Code



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

#define MAX_BUFLEN 41
#define MAX_STR_FMT "%40s"

int main()

char (*tab)[MAX_BUFLEN] = NULL; // see difference here
size_t size = 0, capacity = 0;

char str[MAX_BUFLEN];

while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

// check for expansion
if (size == capacity)

size_t new_capacity = 2 * capacity + 1;
void *tmp = realloc(tab, new_capacity * sizeof *tab);
if (tmp == NULL)

perror("Failed to expand dynamic table");
break;


// save expanded table, and update capacity
tab = tmp;
capacity = new_capacity;


// notice no additional allocations here
strcpy(tab[size++], str);


//
// TODO: use 'tab' holding 'size' strings.
//

// then free the table
free(tab);

return 0;



Summary



Fixing your code was fairly simple, but making it better is too. Never stop thinking about why you're doing what your doing when crafting your algorithms, and spend plenty of time talk with your rubber-duck.






share|improve this answer




























    0














    The problem lies in this line:



    **tab=realloc(tab,(i+2)*sizeof(char*));


    Here **tab dereferences tab to the first character in the first string stored in tab, which isn't what you want. Try this instead:



    tab=realloc(tab,(i+2)*sizeof(char*));


    If you turn on compiler warnings, they should catch this type of mistake.






    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',
      autoActivateHeartbeat: false,
      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%2f53268686%2fadding-element-to-an-array-of-strings%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Your algorithm is broken in two significant places




      • **tab = ... in the loop body is wrong. If tab is char**, then *tab would be char*, and **tab would be char. Assigning a memory address to char should flag huge warnings from your toolchain, and if it doesn't either turn up your warning levels or get a new toolchain.

      • Initial entry to your while condition evaluates indeterminate data. At that time you have allocated raw memory for tab[0], but nothing has populated it yet. Therefore, your program invokes undefined behavior.

      Besides the above, expansion algorithms aren't complex, and explaining yours to your rubber-duck will help significantly before writing any code. In doing so, you'll see reallocating a pointer array with each new read is both costly and inefficient. A geometric expansion algorithms makes this much better. As a bonus, it fixes both of the problems above.



      Code



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

      #define MAX_BUFLEN 41
      #define MAX_STR_FMT "%40s"

      int main()

      char **tab = NULL;
      size_t size = 0, capacity = 0;

      char str[MAX_BUFLEN];

      while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

      // check for expansion
      if (size == capacity)

      size_t new_capacity = 2 * capacity + 1;
      void *tmp = realloc(tab, new_capacity * sizeof *tab);
      if (tmp == NULL)

      perror("Failed to expand dynamic table");
      break;


      // save expanded table, and update capacity
      tab = tmp;
      capacity = new_capacity;


      size_t slen = strlen(str)+1;
      if ((tab[size] = malloc(slen)) == NULL)

      perror("Failed to allocate buffer for new string");
      break;


      // copy incoming string; update 'size' to reflect new count
      memcpy(tab[size++], str, slen);


      //
      // TODO: use 'tab' holding 'size' pointers.
      //

      // then free the table
      while (size-- > 0)
      free(tab[size]);
      free(tab);

      return 0;




      Alternative: No pointers to pointers



      If your need truly requires fixed length allocations (as your code demonstrates), you don't need pointers to pointers at all (unless there is some hidden agenda for something like sorting where swapping pointers is much more efficient than swapping full string buffers).



      Code



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

      #define MAX_BUFLEN 41
      #define MAX_STR_FMT "%40s"

      int main()

      char (*tab)[MAX_BUFLEN] = NULL; // see difference here
      size_t size = 0, capacity = 0;

      char str[MAX_BUFLEN];

      while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

      // check for expansion
      if (size == capacity)

      size_t new_capacity = 2 * capacity + 1;
      void *tmp = realloc(tab, new_capacity * sizeof *tab);
      if (tmp == NULL)

      perror("Failed to expand dynamic table");
      break;


      // save expanded table, and update capacity
      tab = tmp;
      capacity = new_capacity;


      // notice no additional allocations here
      strcpy(tab[size++], str);


      //
      // TODO: use 'tab' holding 'size' strings.
      //

      // then free the table
      free(tab);

      return 0;



      Summary



      Fixing your code was fairly simple, but making it better is too. Never stop thinking about why you're doing what your doing when crafting your algorithms, and spend plenty of time talk with your rubber-duck.






      share|improve this answer

























        1














        Your algorithm is broken in two significant places




        • **tab = ... in the loop body is wrong. If tab is char**, then *tab would be char*, and **tab would be char. Assigning a memory address to char should flag huge warnings from your toolchain, and if it doesn't either turn up your warning levels or get a new toolchain.

        • Initial entry to your while condition evaluates indeterminate data. At that time you have allocated raw memory for tab[0], but nothing has populated it yet. Therefore, your program invokes undefined behavior.

        Besides the above, expansion algorithms aren't complex, and explaining yours to your rubber-duck will help significantly before writing any code. In doing so, you'll see reallocating a pointer array with each new read is both costly and inefficient. A geometric expansion algorithms makes this much better. As a bonus, it fixes both of the problems above.



        Code



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

        #define MAX_BUFLEN 41
        #define MAX_STR_FMT "%40s"

        int main()

        char **tab = NULL;
        size_t size = 0, capacity = 0;

        char str[MAX_BUFLEN];

        while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

        // check for expansion
        if (size == capacity)

        size_t new_capacity = 2 * capacity + 1;
        void *tmp = realloc(tab, new_capacity * sizeof *tab);
        if (tmp == NULL)

        perror("Failed to expand dynamic table");
        break;


        // save expanded table, and update capacity
        tab = tmp;
        capacity = new_capacity;


        size_t slen = strlen(str)+1;
        if ((tab[size] = malloc(slen)) == NULL)

        perror("Failed to allocate buffer for new string");
        break;


        // copy incoming string; update 'size' to reflect new count
        memcpy(tab[size++], str, slen);


        //
        // TODO: use 'tab' holding 'size' pointers.
        //

        // then free the table
        while (size-- > 0)
        free(tab[size]);
        free(tab);

        return 0;




        Alternative: No pointers to pointers



        If your need truly requires fixed length allocations (as your code demonstrates), you don't need pointers to pointers at all (unless there is some hidden agenda for something like sorting where swapping pointers is much more efficient than swapping full string buffers).



        Code



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

        #define MAX_BUFLEN 41
        #define MAX_STR_FMT "%40s"

        int main()

        char (*tab)[MAX_BUFLEN] = NULL; // see difference here
        size_t size = 0, capacity = 0;

        char str[MAX_BUFLEN];

        while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

        // check for expansion
        if (size == capacity)

        size_t new_capacity = 2 * capacity + 1;
        void *tmp = realloc(tab, new_capacity * sizeof *tab);
        if (tmp == NULL)

        perror("Failed to expand dynamic table");
        break;


        // save expanded table, and update capacity
        tab = tmp;
        capacity = new_capacity;


        // notice no additional allocations here
        strcpy(tab[size++], str);


        //
        // TODO: use 'tab' holding 'size' strings.
        //

        // then free the table
        free(tab);

        return 0;



        Summary



        Fixing your code was fairly simple, but making it better is too. Never stop thinking about why you're doing what your doing when crafting your algorithms, and spend plenty of time talk with your rubber-duck.






        share|improve this answer























          1












          1








          1






          Your algorithm is broken in two significant places




          • **tab = ... in the loop body is wrong. If tab is char**, then *tab would be char*, and **tab would be char. Assigning a memory address to char should flag huge warnings from your toolchain, and if it doesn't either turn up your warning levels or get a new toolchain.

          • Initial entry to your while condition evaluates indeterminate data. At that time you have allocated raw memory for tab[0], but nothing has populated it yet. Therefore, your program invokes undefined behavior.

          Besides the above, expansion algorithms aren't complex, and explaining yours to your rubber-duck will help significantly before writing any code. In doing so, you'll see reallocating a pointer array with each new read is both costly and inefficient. A geometric expansion algorithms makes this much better. As a bonus, it fixes both of the problems above.



          Code



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

          #define MAX_BUFLEN 41
          #define MAX_STR_FMT "%40s"

          int main()

          char **tab = NULL;
          size_t size = 0, capacity = 0;

          char str[MAX_BUFLEN];

          while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

          // check for expansion
          if (size == capacity)

          size_t new_capacity = 2 * capacity + 1;
          void *tmp = realloc(tab, new_capacity * sizeof *tab);
          if (tmp == NULL)

          perror("Failed to expand dynamic table");
          break;


          // save expanded table, and update capacity
          tab = tmp;
          capacity = new_capacity;


          size_t slen = strlen(str)+1;
          if ((tab[size] = malloc(slen)) == NULL)

          perror("Failed to allocate buffer for new string");
          break;


          // copy incoming string; update 'size' to reflect new count
          memcpy(tab[size++], str, slen);


          //
          // TODO: use 'tab' holding 'size' pointers.
          //

          // then free the table
          while (size-- > 0)
          free(tab[size]);
          free(tab);

          return 0;




          Alternative: No pointers to pointers



          If your need truly requires fixed length allocations (as your code demonstrates), you don't need pointers to pointers at all (unless there is some hidden agenda for something like sorting where swapping pointers is much more efficient than swapping full string buffers).



          Code



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

          #define MAX_BUFLEN 41
          #define MAX_STR_FMT "%40s"

          int main()

          char (*tab)[MAX_BUFLEN] = NULL; // see difference here
          size_t size = 0, capacity = 0;

          char str[MAX_BUFLEN];

          while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

          // check for expansion
          if (size == capacity)

          size_t new_capacity = 2 * capacity + 1;
          void *tmp = realloc(tab, new_capacity * sizeof *tab);
          if (tmp == NULL)

          perror("Failed to expand dynamic table");
          break;


          // save expanded table, and update capacity
          tab = tmp;
          capacity = new_capacity;


          // notice no additional allocations here
          strcpy(tab[size++], str);


          //
          // TODO: use 'tab' holding 'size' strings.
          //

          // then free the table
          free(tab);

          return 0;



          Summary



          Fixing your code was fairly simple, but making it better is too. Never stop thinking about why you're doing what your doing when crafting your algorithms, and spend plenty of time talk with your rubber-duck.






          share|improve this answer












          Your algorithm is broken in two significant places




          • **tab = ... in the loop body is wrong. If tab is char**, then *tab would be char*, and **tab would be char. Assigning a memory address to char should flag huge warnings from your toolchain, and if it doesn't either turn up your warning levels or get a new toolchain.

          • Initial entry to your while condition evaluates indeterminate data. At that time you have allocated raw memory for tab[0], but nothing has populated it yet. Therefore, your program invokes undefined behavior.

          Besides the above, expansion algorithms aren't complex, and explaining yours to your rubber-duck will help significantly before writing any code. In doing so, you'll see reallocating a pointer array with each new read is both costly and inefficient. A geometric expansion algorithms makes this much better. As a bonus, it fixes both of the problems above.



          Code



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

          #define MAX_BUFLEN 41
          #define MAX_STR_FMT "%40s"

          int main()

          char **tab = NULL;
          size_t size = 0, capacity = 0;

          char str[MAX_BUFLEN];

          while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

          // check for expansion
          if (size == capacity)

          size_t new_capacity = 2 * capacity + 1;
          void *tmp = realloc(tab, new_capacity * sizeof *tab);
          if (tmp == NULL)

          perror("Failed to expand dynamic table");
          break;


          // save expanded table, and update capacity
          tab = tmp;
          capacity = new_capacity;


          size_t slen = strlen(str)+1;
          if ((tab[size] = malloc(slen)) == NULL)

          perror("Failed to allocate buffer for new string");
          break;


          // copy incoming string; update 'size' to reflect new count
          memcpy(tab[size++], str, slen);


          //
          // TODO: use 'tab' holding 'size' pointers.
          //

          // then free the table
          while (size-- > 0)
          free(tab[size]);
          free(tab);

          return 0;




          Alternative: No pointers to pointers



          If your need truly requires fixed length allocations (as your code demonstrates), you don't need pointers to pointers at all (unless there is some hidden agenda for something like sorting where swapping pointers is much more efficient than swapping full string buffers).



          Code



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

          #define MAX_BUFLEN 41
          #define MAX_STR_FMT "%40s"

          int main()

          char (*tab)[MAX_BUFLEN] = NULL; // see difference here
          size_t size = 0, capacity = 0;

          char str[MAX_BUFLEN];

          while (scanf(MAX_STR_FMT, str) == 1 && strcmp(str, "END"))

          // check for expansion
          if (size == capacity)

          size_t new_capacity = 2 * capacity + 1;
          void *tmp = realloc(tab, new_capacity * sizeof *tab);
          if (tmp == NULL)

          perror("Failed to expand dynamic table");
          break;


          // save expanded table, and update capacity
          tab = tmp;
          capacity = new_capacity;


          // notice no additional allocations here
          strcpy(tab[size++], str);


          //
          // TODO: use 'tab' holding 'size' strings.
          //

          // then free the table
          free(tab);

          return 0;



          Summary



          Fixing your code was fairly simple, but making it better is too. Never stop thinking about why you're doing what your doing when crafting your algorithms, and spend plenty of time talk with your rubber-duck.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 12 '18 at 19:53









          WhozCraig

          51.1k958107




          51.1k958107























              0














              The problem lies in this line:



              **tab=realloc(tab,(i+2)*sizeof(char*));


              Here **tab dereferences tab to the first character in the first string stored in tab, which isn't what you want. Try this instead:



              tab=realloc(tab,(i+2)*sizeof(char*));


              If you turn on compiler warnings, they should catch this type of mistake.






              share|improve this answer

























                0














                The problem lies in this line:



                **tab=realloc(tab,(i+2)*sizeof(char*));


                Here **tab dereferences tab to the first character in the first string stored in tab, which isn't what you want. Try this instead:



                tab=realloc(tab,(i+2)*sizeof(char*));


                If you turn on compiler warnings, they should catch this type of mistake.






                share|improve this answer























                  0












                  0








                  0






                  The problem lies in this line:



                  **tab=realloc(tab,(i+2)*sizeof(char*));


                  Here **tab dereferences tab to the first character in the first string stored in tab, which isn't what you want. Try this instead:



                  tab=realloc(tab,(i+2)*sizeof(char*));


                  If you turn on compiler warnings, they should catch this type of mistake.






                  share|improve this answer












                  The problem lies in this line:



                  **tab=realloc(tab,(i+2)*sizeof(char*));


                  Here **tab dereferences tab to the first character in the first string stored in tab, which isn't what you want. Try this instead:



                  tab=realloc(tab,(i+2)*sizeof(char*));


                  If you turn on compiler warnings, they should catch this type of mistake.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 12 '18 at 19:46









                  Henning Koehler

                  1,129610




                  1,129610



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268686%2fadding-element-to-an-array-of-strings%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?

                      In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

                      Museum of Modern and Contemporary Art of Trento and Rovereto