Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
quick C programming question
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
methodtwo
Apprentice
Apprentice


Joined: 01 Feb 2008
Posts: 231

PostPosted: Sat Nov 02, 2013 6:15 pm    Post subject: quick C programming question Reply with quote

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
View user's profile Send private message
methodtwo
Apprentice
Apprentice


Joined: 01 Feb 2008
Posts: 231

PostPosted: Sat Nov 02, 2013 6:45 pm    Post subject: Reply with quote

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
View user's profile Send private message
creaker
l33t
l33t


Joined: 14 Jul 2012
Posts: 651

PostPosted: Sat Nov 02, 2013 6:46 pm    Post subject: Reply with quote

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
View user's profile Send private message
creaker
l33t
l33t


Joined: 14 Jul 2012
Posts: 651

PostPosted: Sat Nov 02, 2013 6:55 pm    Post subject: Reply with quote

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
View user's profile Send private message
methodtwo
Apprentice
Apprentice


Joined: 01 Feb 2008
Posts: 231

PostPosted: Sat Nov 02, 2013 6:57 pm    Post subject: Reply with quote

Thanks for the reply. I thought strdup did allocate memory on the heap for you?
Back to top
View user's profile Send private message
Atom2
Apprentice
Apprentice


Joined: 01 Aug 2011
Posts: 185

PostPosted: Sat Nov 02, 2013 7:15 pm    Post subject: Reply with quote

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
View user's profile Send private message
Atom2
Apprentice
Apprentice


Joined: 01 Aug 2011
Posts: 185

PostPosted: Sat Nov 02, 2013 7:19 pm    Post subject: Reply with quote

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
View user's profile Send private message
creaker
l33t
l33t


Joined: 14 Jul 2012
Posts: 651

PostPosted: Sat Nov 02, 2013 7:23 pm    Post subject: Reply with quote

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
View user's profile Send private message
methodtwo
Apprentice
Apprentice


Joined: 01 Feb 2008
Posts: 231

PostPosted: Sat Nov 02, 2013 7:30 pm    Post subject: Reply with quote

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
View user's profile Send private message
Hu
Moderator
Moderator


Joined: 06 Mar 2007
Posts: 21431

PostPosted: Sat Nov 02, 2013 8:14 pm    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum