简体   繁体   中英

(C) Using while(fscanf(fptr,"%[^\n] %d %f",nome,&regAlmoxarifado,&preco) != EOF) locks the program into a loop

I have a file with the following contents:

lucas lucas lucas
24121 23.00
popotao popotao
2525252 23.52
yee yee
2442421 12.00

I have to read all the words and store them all in a single string, then the number into a int and the last number into a float. It works just fine if I just use " %s %d %f ", except the %s only pulls the word until it finds a space, meaning it prints in the console like this:

lucas 0 0.00
lucas 0 0.00
lucas 24121 23.00
popotao 24121 23.00
popotao 2525252 23.52
yee 2525252 23.52
yee 2442421 12.00

So I tried using %[^\\n] (and a few variations such as [^\\t\\n] and [^\\t\\n]s , \\t isn't making a difference and putting an s at the end just breaks the program further), and it kind of worked for the first 3 values (lucas lucas lucas into the string, 24121 into the int and 23.00 into the float), but then it just keeps printing those same 3 values over and over forever, like this:

lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00
lucas lucas lucas 24121 23.00

It doesn't read the following contents nor does the program end, I honestly have no clue what is the problem, using the debug tool the variables "nome,regAlmoxarifado,preco" just stay with the same value while going through fscanf. Here's the actual code, any help is welcome:

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

int main(void){
    FILE *fptr;
    char nome[20];
    int regAlmoxarifado;
    float preco;
    fptr = fopen("Estoque.txt","r");
    
    while(fscanf(fptr,"%[^\n] %d %f",nome,&regAlmoxarifado,&preco) != EOF)
        printf("%s %d %.2f\n",nome,regAlmoxarifado,preco);
        
    fclose(fptr);
    return 0;
}

Put a space at the beginning of the format string so it will skip over whitespace before it starts looking for the words. Otherwise it fails because the next character after the two numbers is a newline, and %[^\\n] fails.

And instead of comparing to EOF , compare to 3, which is the number of elements you expect it to scan. That way you won't get into an infinite loop when parsing fails.

    while(fscanf(fptr," %[^\n] %d %f",nome,&regAlmoxarifado,&preco) == 3)

Try changing

while(fscanf(fptr,"%[^\n] %d %f",nome,&regAlmoxarifado,&preco) != EOF)

with

while(fscanf(fptr," %19[^0-9] %d %f",nome,&regAlmoxarifado,&preco) == 3)

The space before the %19[ to consume the trailing new line lefted by the previous scan.

19 to be protected from buffer overflows (the length of the string is 20 including the final '\\0' ).

^0-9 reads until a digit is found.

Compare with == 3 instead of != EOF in order to skip malformed lines.

Or better yet, use fgets and the functions provided in string.h . scanf is always a bad option:

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

int main(void)
{
    FILE *file;
    char str[128];
    long reg;
    double pre;

    file = fopen("Estoque.txt","r");
    while (fgets(str, sizeof str, file))
    {
        size_t pos;

        if ((pos = strcspn(str, "0123456789")) > 0) // Position of the first digit
        {
            str[pos - 1] = '\0'; // Cut the string
        }

        char *ptr;

        reg = strtol(str + pos, &ptr, 10); // 10 means base 10
        pre = strtod(ptr, NULL);
        printf("%s %ld %.2f\n", str, reg, pre);
    }
    fclose(file);
    return 0;
}

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