View previous topic :: View next topic |
Author |
Message |
methodtwo Apprentice
Joined: 01 Feb 2008 Posts: 231
|
Posted: Sat Nov 02, 2013 6:15 pm Post subject: quick C programming question |
|
|
I have a really basic C question and my friend has my K&R!:
If you have some code like:
Code: | while (fgets(buf, sizeof(buf), fp) != NULL)
|
then how do you build an array of pointers with each pointer pointing to a line returned by fgets()?. Bearing in mind that in this while loop buf is overwritten each time through.
I've tried:
Code: | char *ptr_buf[BUFSIZ];
memcpy(ptr_buf[i++], buf, sizeof(buf)); |
And with an & before ptr_buf too. I've also tried:
Code: | strncpy(ptr_buf[i++], buf, sizeof(buf)); |
And just:
Code: | ptr_buf[i++] = buf; |
But the program segfaults with all these ways. I need a way of having an array of pointers to strings even though the source of the strings(but) is overwritten each time through the while loop.
Any help would be great. I can post the whole program if you want. It's only a short bit of code.
Thank you for any help |
|
Back to top |
|
|
methodtwo Apprentice
Joined: 01 Feb 2008 Posts: 231
|
Posted: Sat Nov 02, 2013 6:45 pm Post subject: |
|
|
I have just done this:
Code: | ptr_buf[i++] = strdup(buf); |
instead of this previous attempts to fill the array of pointers to strings that i called ptr_buf. The program still segfaulted! |
|
Back to top |
|
|
creaker l33t
Joined: 14 Jul 2012 Posts: 651
|
Posted: Sat Nov 02, 2013 6:46 pm Post subject: |
|
|
You have to allocate memory for each index/string. Your pointers ( char *ptr_buf[BUFSIZ] ) points to nowhere instead of pointing to allocated memory chunks. It leads to segfault, when you copying data to the place that pointed by invalid pointers.
Allocate memory chunk for each string before copying. |
|
Back to top |
|
|
creaker l33t
Joined: 14 Jul 2012 Posts: 651
|
Posted: Sat Nov 02, 2013 6:55 pm Post subject: |
|
|
In other words it should be like this:
1. Read data from file to buf
2. Calculate data size
3. Allocate enough memory to fit your data
4. Copy data from buf to allocated chunk
5. Add pointer to this memory chunk to your pointers array |
|
Back to top |
|
|
methodtwo Apprentice
Joined: 01 Feb 2008 Posts: 231
|
Posted: Sat Nov 02, 2013 6:57 pm Post subject: |
|
|
Thanks for the reply. I thought strdup did allocate memory on the heap for you? |
|
Back to top |
|
|
Atom2 Apprentice
Joined: 01 Aug 2011 Posts: 185
|
Posted: Sat Nov 02, 2013 7:15 pm Post subject: |
|
|
Something around the following should work:
Code: | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 100 /* maximum number of characters per line */
#define ARRAYSIZE 10 /* maximum number of lines to read */
int main(int argc, char *argv[])
{
char *array[ARRAYSIZE];
char buf[BUFSIZE];
unsigned int i = 0;
FILE *fp;
if ((fp = fdopen(1, "r")) == NULL) {
fprintf(stderr, "Unable to open stdin\n");
exit(1);
}
while ((i < ARRAYSIZE) && (fgets(buf, BUFSIZE, fp) != NULL))
array[i++] = strcpy(malloc(strlen(buf) + 1), buf);
while (i)
fprintf(stdout, "%s", array[--i]);
exit(0);
}
|
The main thing is that you need the memory to store the read lines. I have sorted this by using malloc. Alternatively you could also create a tow dimensional array of appropriate size with one dimension being the maximum number of lines and the other dimension being the maximum length of a single line. |
|
Back to top |
|
|
Atom2 Apprentice
Joined: 01 Aug 2011 Posts: 185
|
Posted: Sat Nov 02, 2013 7:19 pm Post subject: |
|
|
methodtwo wrote: | Thanks for the reply. I thought strdup did allocate memory on the heap for you? |
You are right, strdup does actually allocate memory - so you could also change my suggestion slightly to read as follows:
Code: | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 100 /* maximum number of characters per line */
#define ARRAYSIZE 10 /* maximum number of lines to read */
int main(int argc, char *argv[])
{
char *array[ARRAYSIZE];
char buf[BUFSIZE];
unsigned int i = 0;
FILE *fp;
if ((fp = fdopen(1, "r")) == NULL) {
fprintf(stderr, "Unable to open stdin\n");
exit(1);
}
while ((i < ARRAYSIZE) && (fgets(buf, BUFSIZE, fp) != NULL))
array[i++] = strdup(buf);
while (i)
fprintf(stdout, "%s", array[--i]);
exit(0);
}
|
|
|
Back to top |
|
|
creaker l33t
Joined: 14 Jul 2012 Posts: 651
|
Posted: Sat Nov 02, 2013 7:23 pm Post subject: |
|
|
In the case of strdup :
Code: | #include <string.h>
#include <stdio.h>
#include <malloc.h>
char buf[1024];
char *arr[300];
int main()
{
int i,k;
scanf("%d\n",&k);
if(k>300) k=300;
/* read k lines and collect data */
for(i=0;i<k;i++) {
gets(buf);
arr[i]=strdup(buf);
}
/* print string */
for(i=0;i<k;i++) printf("line %3d -> %s\n",i+1,arr[i]);
/* free memory */
for(i=0;i<k;i++) free(arr[i]);
return 0;
} |
|
|
Back to top |
|
|
methodtwo Apprentice
Joined: 01 Feb 2008 Posts: 231
|
Posted: Sat Nov 02, 2013 7:30 pm Post subject: |
|
|
Thank you very much for such an illustrative reply. I think i'll be able to get it working bearing your replies in mind. Yet again this forum is the coolest(most helpful & friendly) that i've used! Thanks guys/girls |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21644
|
Posted: Sat Nov 02, 2013 8:14 pm Post subject: |
|
|
creaker wrote: | In the case of strdup : | That works fine, until he gets a line longer than the input buffer was prepared to handle. man gets: | BUGS
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead. |
|
|
Back to top |
|
|
|