1

I have used a section of code found on here to read in a .txt file line by line, and I think this should add all of the lines into an array named words. Whenever I try and return a value from the array, for example printf(words[7]); all of the lines from the text document are returned, not just the 7th value in the array. Have all of the lines not been split into an array properly, or are all of the values of the array being returned?

void readFile() {
    FILE* fp; // Declare the file pointer

    int lines_allocated = 128;
    int max_line_len = 100;

    /* Allocate lines of text */
    char** words = (char**)malloc(sizeof(char*) * lines_allocated);
    if (words == NULL) {
        fprintf(stderr, "Out of memory (1).\n");
        exit(1);
    }

    switch (difficulty) // Open the file for read
    {
        case 'e':
            fp = fopen("words_easy.txt", "r");
            break;
        case 'm':
            fp = fopen("words_medium.txt", "r");
            break;
        case 'h':
            fp = fopen("words_hard.txt", "r");
            break;
        default:
            printf("Cannot open file");
    }
    if (fp == NULL) {
        fprintf(stderr, "Error opening file.\n");
        exit(2);
    }

    int i;
    for (i = 0; 1; i++) {
        int j;

        /* Have we gone over our line allocation? */
        if (i >= lines_allocated) {
            int new_size;

            /* Double our allocation and re-allocate */
            new_size = lines_allocated * 2;
            words = (char**)realloc(words, sizeof(char*) * new_size);
            if (words == NULL) {
                fprintf(stderr, "Out of memory.\n");
                exit(3);
            }
            lines_allocated = new_size;
        }
        /* Allocate space for the next line */
        words[i] = malloc(max_line_len);
        if (words[i] == NULL) {
            fprintf(stderr, "Out of memory (3).\n");
            exit(4);
        }
        if (fgets(words[i], max_line_len - 1, fp) == NULL)
            break;

        /* Get rid of CR or LF at end of line */
        for (j = strlen(words[i]) - 1;
             j >= 0 && (words[i][j] == '\n' || words[i][j] == '\r'); j--)
            ;
        words[i][j + 1] = '\0';
    }

    /* Close file */
    fclose(fp);

    int j;
    for (j = 0; j < i; j++)
        printf("%s\n", words[j]);

    /* Good practice to free memory */
    for (; i >= 0; i--)
        free(words[i]);
    free(words);
    printf(words[7]);
    return 0;
}

The document is one word per line, and I am only trying to print one word as a test, however I am getting all of the lines outputted to the console when I try and call one value from the array.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Toby Cannon
  • 725
  • 6
  • 16
  • 3
    `/* Good practice to free memory */`..no, it's _almost_ mandatory. :-) – Sourav Ghosh Apr 14 '15 at 12:27
  • 2
    Standard Warning : Please [do not cast](http://stackoverflow.com/q/605845/2173917) the return value of `malloc()` and family in `C`. – Sourav Ghosh Apr 14 '15 at 12:28
  • `words = (char **)realloc(words,sizeof(char*)*new_size);`...think of the ___horror___ if `realloc()` fails. – Sourav Ghosh Apr 14 '15 at 12:29
  • 2
    If you don't want to print all the words, any particular reason for your final `j` loop? Further, you just free'd all the allocations you made, so the final `printf(words[7]);` seems like wishful thinking at-best, and certainly undefined-behavior. – WhozCraig Apr 14 '15 at 12:31
  • @WhozCraig Well done that man, left this loop in from the testing stage, tiredness and distractions produces sloppy code, thanks for pointing that stupid error out! – Toby Cannon Apr 14 '15 at 12:34
  • Also, you can't print what you have just `free`d. – M Oehm Apr 14 '15 at 12:34

2 Answers2

2

why this for loop is required in your progm...???

int j;
for(j = 0; j < i; j++)
    printf("%s\n", words[j]);
Pankaj Andhale
  • 401
  • 9
  • 24
1

Point 1: In your code, you've written

free(words);
printf(words[7]);

Accessing a pointer after it has been free()d will lead to undefined behaviour.

Point 2:

for (j = 0; j < i; j++)
        printf("%s\n", words[j]);

This for loop prints all the lines, anyways.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261