简体   繁体   中英

Am I using fscanf incorrectly?

I am having a small problem with fscanf reading from a text file.

I have this small piece of code (C++):

struct tooted
{
    char nimi[50];
    int kogus;
    float hind;
}toode[20];

int main()
{
    FILE *kala;
    kala = fopen("kala.txt", "r");
    int i=0, n=0;
    char buffer[200];

    while(!feof(kala))
    {
        if(n<1)
        {
            fgets(buffer, 200, kala);
        }
        if(n>0)
        {
            fscanf(kala, "%s[^\t]%i[^\t]%f", toode[i].nimi, toode[i].kogus, toode[i].hind);
            i++;
        }
        n++;
    }

    for(i=0; i<n-1; i++)
    {
        printf("Toode: %s\nKogus: %i\n Hind: %f\n\n", toode[i].nimi, toode[i].kogus, toode[i].hind);
    }

    return 0;
}

The fgets(buffer, 200, kala); is just to start the fscanf from the second row. In the file kala.txt I have 3 rows separated with [tab]. The first word is a string, the second an integer, and the third a float, like this:

product1 (tab) 4 (tab) 1.4
product2 (tab) 3 (tab) 2.3

It reads the words (and numbers) one by one using only the toode[i].nimi so the outcome is:

Toode: product1
Kogus: 0
Hind: 0.0000

Toode: 4
Kogus: 0
Hind: 0.0000

etc.

Note also that product1 can be two words, but they are separated with a space not tab. I want it to read product1 as one string.

(I tried looking it up before asking, but I couldn't find the solution. Sorry if it's a repost.)

Thank you :)

Yes. You are using it wrongly.

All arguments must be pointers, you gave a pointer for the char[] but not to the int and float.

pointer are the only way to create out (not return) parameters in C. and all the arguments after the format are out parameters.

It should be:(note to the '&' additions)

EDIT I fix also the format ...

fscanf(kala, "%[^\t] %i %f", toode[i].nimi, &toode[i].kogus, &toode[i].hind);

The "[^" in the format string will try to match a literal [^ in the input (and probably fail), as there's not a % before it, so it's not a scanf pattern. You probably just want:

fscanf(kala, " %[^\t]%i%f", toode[i].nimi, &toode[i].kogus, &toode[i].hind);

You have many other problems, such as using feof , and not doing any error checking, but this should at least get you started.

Okay so I tinkered on it a little and found out (still learning) that I shouldn't have had comas in the text file I was getting the info from. Or at least I should have made the fscanf ignore the comas.

I also removed the [^\\t] as the fscanf ignores them just like it does with spaces.

My code now:

struct tooted
{
    char nimi[50];
    int kogus;
    float hind;
}toode[20];

int main()
{
    FILE *kala;
    kala = fopen("kala.txt", "r");
    int i=0, n=0;
    char buffer[200], *token;

    fgets(buffer, 200, kala);
    while(!feof(kala))
    {
            fscanf(kala, "%s %i %f", toode[i].nimi, &toode[i].kogus, &toode[i].hind);
            printf("Toode: %s\nKogus: %i\n Hind: %2.2f\n\n", toode[i].nimi, toode[i].kogus, toode[i].hind);
            i++;
    }
    return 0;
}

My output now:

Toode: product1
Kogus: 1
Hind: 1.5

Toode: product2
Kogus: 2
Hind: 2.6

etc

Just as I wanted it to be.

I know I still have no error checking, but that was not the bug that I tryed to fix, at least not yet. Sorry for not specifying my text file as it would have helped you discover the problem. I didn't know to look for the problem there :)

I looked into using the feof correctly, you were right, I could do it much better to eliminate future bugs. Thanks for the heads up (not sure if using this expression correctly :P). Right now I just didn't have the time to fix it.

Thank you all for helping :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM