943,929 Members | Top Members by Rank

Ad:
  • C Discussion Thread
  • Marked Solved
  • Views: 2252
  • C RSS
Nov 20th, 2008
0

Dynamically allocating 2d arrays

Expand Post »
Basically I'm reading from a file and populating a dynamically allocated array with the words that are in the file. I've already read through the file to figure out what numArts is, so I know how many words there are in the array.

This works up until the:

  1. arts[index] = (char*)malloc(strlen(word) * sizeof(char));
  2. strcpy(*(arts + index), word);

if I remove those lines, the printf statment prints what I expect it to. I've tried doing this with pointer arithmetic as well. I just keep getting bus error over and over. From what I can tell and what I've been able to read about dynamically allocating arrays and such I'm doing this correctly. Does anyone see anything wrong with this?

  1. void populateArts(char **arts, FILE *fin, int *numArts)
  2. {
  3. int index;
  4. char* word; /* Temporary holding for each word */
  5.  
  6. arts = malloc(*numArts * sizeof(char*));
  7.  
  8. fscanf(fin, "%s", word); /* Skip over category */
  9. /* Fill articles array */
  10. for(index = 0; index < *numArts; index++)
  11. {
  12. fscanf(fin, "%s", word);
  13. printf("word is %s\n", word);
  14.  
  15. arts[index] = (char*)malloc(strlen(word) * sizeof(char));
  16. strcpy(*(arts + index), word);
  17. }
  18. }
Similar Threads
Reputation Points: 11
Solved Threads: 0
Light Poster
bondo is offline Offline
43 posts
since Apr 2007
Nov 20th, 2008
2

Re: Dynamically allocating 2d arrays

>char* word; /* Temporary holding for each word */
>fscanf(fin, "%s", word);
Pointers aren't magic containers for infinite data. You need to allocate space to word before you can write to it. In this case, there's little point in using a pointer unless you want to get fancy with single character reads.

>arts[index] = (char*)malloc(strlen(word) * sizeof(char));
You cast the result of malloc in one call but not another. Consistency is more important than perfect style, but I'd still recommend removing the cast. Also, instead of sizeof(char) , you can get the same effect without specifying the type directly using sizeof *arts[index] . Also note that sizeof(char) is guaranteed to be 1.

Finally, when allocating memory for a string, you need to add an extra slot for the null character. If you don't do that, you'll end up with problems later when overflowing the buffer.

Try this:
  1. void populateArts(char **arts, FILE *fin, int *numArts)
  2. {
  3. int index;
  4. char word[BUFSIZ]; /* Temporary holding for each word */
  5.  
  6. arts = malloc(*numArts * sizeof *arts);
  7.  
  8. fscanf(fin, "%s", word); /* Skip over category */
  9.  
  10. /* Fill articles array */
  11. for(index = 0; index < *numArts; index++)
  12. {
  13. fscanf(fin, "%s", word);
  14. printf("word is %s\n", word);
  15.  
  16. arts[index] = malloc(strlen(word) + 1);
  17. strcpy(arts[index], word);
  18. }
  19. }
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
Nov 20th, 2008
0

Re: Dynamically allocating 2d arrays

Ah! I see. Fantastic. Thanks so much. I know pointers aren't "magic containers", but the only reason I was trying

  1. char* word;
  2. fscanf(fin, "%s", word)

is that earlier on while reading through the file I am doing this:

  1. int countWords(FILE* fin)
  2. {
  3. int count = 0;
  4. char* temp; /* Temporary holding for each line */
  5. fscanf(fin, "%s", temp); /* Read the category name, but don't count it */
  6.  
  7. while(*temp != '#' && !feof(fin))
  8. {
  9. fscanf(fin, "%s", temp);
  10. printf("temp is %s\n", temp);
  11. if(*temp != '#')
  12. count++;
  13. }
  14.  
  15. return count;
  16. }

Which, to me, looked exactly the same as what I was doing in the other function, except for the allocating memory part, so I was getting confused as to why in countWords() I am able to read into a pointer that didn't have memory allocated to it and print out the correct results, but in populateArts() it wasn't working. Do you have some insight as to why it was working in one place, but not in another? I just would like to have the concept clarified, if you don't mind.

Thanks again!

Oh also, how do you specify what kind of syntax you are using with the CODE tags?
Reputation Points: 11
Solved Threads: 0
Light Poster
bondo is offline Offline
43 posts
since Apr 2007
Nov 20th, 2008
0

Re: Dynamically allocating 2d arrays

Quote ...
Oh also, how do you specify what kind of syntax you are using with the CODE tags?
for c:

[CODE=C]
/*code goes here */
[/CODE]


also explained here
Last edited by Nick Evan; Nov 20th, 2008 at 11:39 am.
Moderator
Featured Poster
Reputation Points: 4142
Solved Threads: 394
Industrious Poster
Nick Evan is offline Offline
4,132 posts
since Oct 2006
Nov 20th, 2008
1

Re: Dynamically allocating 2d arrays

>Do you have some insight as to why it was working in one place, but not in another?
You got unlucky where it worked and lucky in another because bugs are more obvious when they break immediately. As for the detailed why, the random address as temp's value in countWords happened to be in your address space and writing to it happened not to cross any boundaries that would cause a segmentation fault. In populateArts, the random address wasn't nearly as benign.

>while(*temp != '#' && !feof(fin))
For future reference, feof isn't designed to be used as a loop condition like that. Because the end-of-file indicator for a stream is only set after you've tried and failed to read from the stream, loops constructed like this have an off-by-one error where the last record in the stream will be processed twice. This is easily tested and proven with a simple program:
  1. #include <stdio.h>
  2.  
  3. int main ( void )
  4. {
  5. char buf[BUFSIZ] = "I'm a monkey! Ook ook!\n";
  6.  
  7. while ( !feof ( stdin ) ) {
  8. fgets( buf, sizeof buf, stdin );
  9. printf ( "Processing a line: %s", buf );
  10. }
  11.  
  12. return 0;
  13. }
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
Nov 20th, 2008
0

Re: Dynamically allocating 2d arrays

Oh, I see. So really it was wrong in BOTH places, it just happened to be work in one place and not in the other, but really I should have done the both how you said. Awesome.

Thanks again!
Reputation Points: 11
Solved Threads: 0
Light Poster
bondo is offline Offline
43 posts
since Apr 2007

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C Forum Timeline: corruption of the heap
Next Thread in C Forum Timeline: External Delaration for An Array?





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC