Question

I'm a novice with C and am still weak when it comes to using and understanding pointers - especially void pointers. I'm attempting to write a function that loads data from a file and stores those data in a void pointer array, such that each element of the array has (in this example) the string from that line of the file. I suspect that there are several problems with the code:

  1. I'm not sure if I'm properly using *voidArray[] as one of the function's arguments.
  2. I'm not sure if strcpy() is a good approach for copying the line buffer's contents into the pertinent array element.
  3. I don't know what the proper syntax is for strcpy()'s destination (i.e. the pertinent element in the void pointer array).

There could be other errors as well, but those are the three issues I feel very unsure about.

Here's my function:

void *readData(void *voidArray[], const char *filename, int lines) {
    FILE *stream = fopen(filename, "r");
    if (stream == NULL) {
        perror("Error loading file");
    return 1;
    }
    char lineBuffer[BUFFER_SIZE];

int i = 0;
    while(!feof(stream)) {
        while(fgets(lineBuffer, sizeof(lineBuffer), stream)) {
            // *voidArray[i] = malloc(strlen(lineBuffer) + 1);     // probably not what I want
            strcpy(*voidArray[i], lineBuffer);
            i++;
        }
    }

    fclose(stream);
}

...and here's the beginning of main(), where (again) I'm not sure what the proper syntax is for declaring (and initializing?) the array:

int main(void)
{
    int lines = 20;
    void *varray[lines];
    // varray = malloc(sizeof(char *) * lines);     // probably not what I want
    readData(varray[lines], FILENAME, lines);       // FILENAME declared earlier

Some suggested code fixes would be sorely appreciated (especially if I'm completely missing the boat on a more appropriate approach), but what I feel like I need even more is a good explanation for why the suggestions are correct. If I can wrap my head around this problem I think - at worst - I'll have a good sense of what I still need to teach myself re: pointers. Thank you in advance for any help or commentary, and for your patience in reading this far.


Edit: Joachim Pileborg's answer has helped, but I'm still missing something fundamental (and probably obvious). Here is my revised function:

void *loadData(void *voidArray, const char *filename, int lines) {
    FILE *stream = fopen(filename, "r");
    if (stream == NULL) {
        perror("Error loading file");
    }
    char lineBuffer[BUFFER_SIZE];

    int i = 0;
    while(fgets(lineBuffer, sizeof(lineBuffer), stream)) {
        strcpy((voidArray+i), lineBuffer);
        printf("voidArray: %s\n", (char *)(voidArray+i));
        i++;
    }

    for (i = 0; i < lines; i++) {
        printf("array element %d: %s\n", i, (char *)(voidArray+i));
    }

    fclose(stream);
}

And here are the results from my two tests:

voidArray: Good
voidArray: morning
voidArray: everyone
array element 0: Gmeveryone
array element 1: meveryone
array element 2: everyone

Again, I'm probably missing something trivial. What I want to do is have varray comprised of void pointers, each of which points to an object (for this example, a string) read from an external file. I have a sense of what I'm doing wrong with "varray+i", but I don't know what I should actually be doing instead.

Was it helpful?

Solution

There are four problems (besides the one I mentioned in the comment) that I see at a quick glance:

  • The first is that you commented out the allocation, so if the the pointers aren't allocated when you call the function you will write to what will seem random locations in memory.

  • The second is that you use the dereference operator in your call to strcpy. If you had for example an array of char pointers, this would be a single char and not a pointer. And that's besides the fact that you can't actually dereference a void pointer.

  • The third problem is that you never check the number of entries in the array, you just keep on looping and reading and copying into the array without regards for its size.

  • The fourth problem is in the way you call this function, where you actually aren't passing an array of pointers, but a single pointer at the index lines, which will be one beyond the limits of the array.


As an unrelated side-note: Remember that if fgets reads a newline, then that newline will be in the buffer.

OTHER TIPS

You can't store stuff in void pointers, nor can you index into them. You cannot dereference void pointers unless you cast them first. You can't do pointer arithmetic with them. They are syntactic sugar for generics which was added later because people were using char* for that purpose.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top