2

I want to read a text file that contains id numbers and names and print those informations line by line. I wrote codes below but output is empty. I cannot find out why it didn't work.

Text file (firms.txt):

101 eti300 superfresh502 pinar91 banvit

Code:

#include <stdio.h>

//prototypes
void readFirms(char *filename);

int main(void) {

    readFirms("C:\\Users\\hakan\\Desktop\\firms.txt");

}

void readFirms(char *filename) {
    FILE *firmFilePtr;

    if ((firmFilePtr = fopen(filename, "r")) == NULL) {
        puts("File could not be opened.");
    } else {
        unsigned int firmId;
        char *firmName;

        fscanf(firmFilePtr, "%d%s", &firmId, firmName);

        while (!feof(firmFilePtr)) {
            printf("%d %s\n", firmId, *firmName);
            fscanf(firmFilePtr, "%d %s", &firmId, firmName);
        }
        fclose(firmFilePtr);
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
H.Ozer
  • 115
  • 6
  • 6
    Read also [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – pzaenger May 26 '18 at 15:59
  • In the file shown in the question, there's no whitespace between `eti` and `300`, is that an accurate representation of the file you're actually using? – Angew is no longer proud of SO May 26 '18 at 15:59
  • I tried with space and without space for both of fscanf but result is same. – H.Ozer May 26 '18 at 15:59
  • @Angew Yes in text file there is no space – H.Ozer May 26 '18 at 16:01
  • Read carefully the documentation of every used function, such as [fscanf](http://en.cppreference.com/w/c/io/fscanf) & [feof](http://en.cppreference.com/w/c/io/feof). Compile with all warnings and debug info (`gcc -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/)...). Improve your code to get no warnings. Then [use the `gdb` debugger](https://sourceware.org/gdb/current/onlinedocs/gdb/) to understand the behavior of your program – Basile Starynkevitch May 26 '18 at 16:05
  • @DevSolar Page not found. – H.Ozer May 26 '18 at 16:23
  • Related: [How to read / parse input in C. The FAQ.](https://stackoverflow.com/questions/35178520/) – DevSolar May 26 '18 at 16:24
  • @user3121023 No, changed it with char name[50] but output is still empty. – H.Ozer May 26 '18 at 16:35
  • @user3121023 sorry, still firmName – H.Ozer May 26 '18 at 16:37
  • 1
    @user3121023 Thank you very much. It worked when i removed asterisk. – H.Ozer May 26 '18 at 16:40

2 Answers2

2

Your code has multiple problems:

  • the loop test is incorrect: Why is “while ( !feof (file) )” always wrong? You should instead call fscanf() in the while test expression and compare the return value with 2.

  • the file contents does not match the format you are trying to parse: the first 101 will match %d, then eti300 matches %s, but the next call to fscanf() fails because superfresh502 does not match %d and any subsequent calls fail because the offending input is still pending in the input stream.

  • firmName is an uninitialized pointer, passing it as the destination to fscanf for the %s conversion specifier has undefined behavior.

Here is a modified version:

#include <stdio.h>

//prototypes
void readFirms(char *filename);

int main(void) {
    readFirms("C:\\Users\\hakan\\Desktop\\firms.txt");
    return 0;
}

void readFirms(char *filename) {
    FILE *firmFilePtr;

    if ((firmFilePtr = fopen(filename, "r")) == NULL) {
        puts("File could not be opened.");
    } else {
        unsigned int firmId;
        char firmName[100];

        while (fscanf(firmFilePtr, "%d%99s", &firmId, firmName) == 2) {
            printf("%d %s\n", firmId, firmName);
        }
        fclose(firmFilePtr);
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Tried both but didn' work. Output is still empty. Interestingly when i change text file like "101 eti 300 superfresh 502 pinar 91 banvit" and fscanf(firmFilePtr, "%d%s", &firmId, firmName it didn't work too. – H.Ozer May 26 '18 at 16:22
  • @H.Ozer: of course the input file must be reformatted with numbers and words separated by whitespace for the `fscanf()` code to parse it. – chqrlie May 26 '18 at 18:01
0

fscanf("%s", ...) reads a string: all characters valid for a string are read into it, until whitespace is encountered (or the file ends). Note that eti300 is a perfectly valid string, and as such, all of it is consumed by the first fscanf. This leaves no number for the second fscanf to start with, so it errors.

If you can, change the format of your data to introduce whitespace (such as a newline) between a name and the next ID number following it.

If that is not an option, you will have to parse the numbers out of the strings manually (such as finding the first digit and splitting the string there). This could be done via character-by-character reads from the file, or by reading the data into memory as strings and processing it there.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455