1

Im trying to write a function that, given a filename will read strings from the file to an array of strings. This array (list) will then be returned by the function.

I've tried list being of type char * as well as an array of [50][100] where 50 is the maximum number of words in a list and 100 is the maximum length of a word. I've also tried both copying the word to an index in the array using strcpy and setting an index in the list to word (list[i] = word).

char list[100][100];
char word[100];
int i = 0;
FILE * fp = fopen(filename, "r+");

while (!feof(fp)) {
    fscanf(fp, "%s", word);
    strcpy(list[i], word);
    i++;
}

When i run code that calls this function (and no other function) I get a segmentation fault 11.


EDIT: I have changed the code to run as below:

char arr[100][100];

    int i = 0;

    FILE * fp = fopen("collection.txt", "r+");
    while (fscanf(fp, "%s", arr[i]) == 1 && i < 100) {
        i++;
    }

It works when i test it in a main function however I can't get it to work when calling it as a function. I had defined the function as:

char get_list (char * filename);

and called this function from a main function using

char list = get_list ("testfile.txt");

and the compiler is giving warning:

warning: incompatible pointer to integer conversion returning 'char [100][100]' from a function with result type 'char' [-Wint-conversion]

How should this function be defined and called?

ascii7
  • 11
  • 3
  • 2
    You're loop is bounded only by an erroneous `while (!feof(fp))`, which in itself is wrong.Read this: [Why is “while (!feof(file))” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong). Second, don't let more than 100 strings come through or you're going to breach your array and invoke undefined behavior. Third, make sure any string you're reading fits in `word` (a 100 character string or larger will *not*, accounting for the terminator). And after all of that, `word` is useless; you can read directly into `list[i]` and avoid the `strcpy` entirely. – WhozCraig Jul 31 '19 at 06:48

3 Answers3

0

Try changing the name of your array (list) to something else. And tell us what happens

Note: Add an extra condition in the while loop && i < 100

This works for me

char arr[100][100];
char word[100];
int i = 0;

FILE * fp = fopen(filename, "r+");
while (!feof(fp) && i < 100)
    fscanf(fp, "%s", arr[i++]);
Issam Rafihi
  • 432
  • 3
  • 10
0

The error is your array defined 'list' is out of bound. Because the text file may contain Char(in this code,word) more than 100. Try to add another condition to avoid that, just like

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char list[100][100];
    char word[100];
    int i = 0;
    char filename[]="mytxt.txt";
    FILE * fp = fopen(filename, "r+");



    while (!feof(fp) && i<100 )
    {
        fscanf(fp, "%s", word);
        strcpy(list[i], word);
        i++;
    }

    printf(list[2]);
    return 0;
}

or you can modify that code to get the char length of the text file and looping that.

nipun-kavishka
  • 842
  • 12
  • 21
  • check this code if you want to modify yours https://stackoverflow.com/questions/7374062/how-do-i-count-the-number-of-words-in-a-text-file-using-c – nipun-kavishka Jul 31 '19 at 07:32
0

You will want to look at Why is while ( !feof (file) ) always wrong?

Whenever you are reading data in a loop, you control the loop with the read function, e.g.

#define ROWS 100    /* if you need a constant, #define one (or more) */
#define COLS ROWS
...
    /* you control the read loop with the read function itself
     * you must protect your ROW bounds with the counter and 
     * protect your COL bounds with the field-width modifier.
     */
    while (i < ROWS && fscanf (fp, "%99s", list[i]) == 1)
        i++;                        /* increment counter */

Above you protect your ROWS (rows) array bound by only adding a new word while your counter is less than the number of rows available. You protect your COLS bound by using the field-width modifier to the "%s" conversion specifier to ensure no more than 99 characters are read into your array (saving room for +1 -- the nul-terminating character).

(note: your words array was superfluous. You can read directly into list)

You now have all words read from the file stored in list. It doesn't matter whether there are one or more words on each line, you read a word-at-a-time and the "%s" conversion specifier ignores leading whitespace (including '\n').

A short example that reads words from the file provided as the first argument to your program (or reads from stdin by default if no argument was given) could be:

#include <stdio.h>

#define ROWS 100    /* if you need a constant, #define one (or more) */
#define COLS ROWS

int main (int argc, char **argv) {

    char list[ROWS][COLS];  /* 2D array to hold strings (words) */
    int i = 0;              /* counter for strings */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    /* you control the read loop with the read function itself
     * you must protect your ROW bounds with the counter and 
     * protect your COL bounds with the field-width modifier.
     */
    while (i < ROWS && fscanf (fp, "%99s", list[i]) == 1)
        i++;                        /* increment counter */

    for (int j = 0; j < i; j++)     /* output stored words */
        printf ("list[%2d] : %s\n", j, list[j]);

    if (fp != stdin)                /* close file if not stdin */
        fclose (fp);
}

Example Input File

Taking a file with multiple words on some lines and a single word on others:

$ cat dat/dictwrds20.txt
a
AAA
AAAS
aardvark Aarhus Aaron ABA
Ababa
aback
abacus abalone abandon abase
abash
abate abbas abbe
abbey
abbot
Abbott

Example Use/Output

The code above reads each word into your list array without any problems:

$ ./bin/readlist dat/dictwrds20.txt
list[ 0] : a
list[ 1] : AAA
list[ 2] : AAAS
list[ 3] : aardvark
list[ 4] : Aarhus
list[ 5] : Aaron
list[ 6] : ABA
list[ 7] : Ababa
list[ 8] : aback
list[ 9] : abacus
list[10] : abalone
list[11] : abandon
list[12] : abase
list[13] : abash
list[14] : abate
list[15] : abbas
list[16] : abbe
list[17] : abbey
list[18] : abbot
list[19] : Abbott

Look things over and let me know if you have questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85