Чтение текстового файла с fscanf не работает, как задумано - PullRequest
0 голосов
/ 17 октября 2019

Я хочу прочитать файл с числами и сом-текстом, но когда я пытаюсь прочитать каждую строку файла, он пропускает \ n после первой строки чисел и читает две строки как одну вместо двух отдельныхиз них.

Я хочу строго использовать fgets и fscanf для этого.

struct lakemedel
{
    char namn[MAXORD];
    int forpackningar[PAKETSTORLEKAR];
    int antalForpackningar;
    int saldo[PAKETSTORLEKAR];
    int antalSaldo;
};
typedef struct lakemedel Lakemedel;

Lakemedel lakemedelRegister[MAXANTAL];

    printf("Skriv in fil du vill anvanda: ");
    scanf(" %s", lasFilnamn);
    int i = 0;
    int f = 0;
    int s = 0;
    int nl = 0;
    FILE *fp;
    fp = fopen(lasFilnamn, "r");
    if(fp!=NULL)
    {        
        while(fscanf(fp,"%s", lasLakemedelRegister[i].namn)==1)
        {
            lasLakemedelRegister[i].antalForpackningar = 0;
            lasLakemedelRegister[i].antalSaldo = 0;
            printf("fff");
            while (fscanf(fp, "%d", &lasLakemedelRegister[i].forpackningar[lasLakemedelRegister[i].antalForpackningar]) == 1)
            {
                printf("aaa");
                lasLakemedelRegister[i].antalForpackningar++;                
            }
            while (fscanf(fp, "%d", &lasLakemedelRegister[i].saldo[lasLakemedelRegister[i].antalSaldo])==1)
            {
                lasLakemedelRegister[i].antalSaldo++;
            }
            /*for (lasLakemedelRegister[i].antalForpackningar = 0; lasLakemedelRegister[i].antalForpackningar == 1; lasLakemedelRegister[i].antalForpackningar++)
            {            
                fscanf(fp, "%d", &lasLakemedelRegister[i].forpackningar[lasLakemedelRegister[i].antalForpackningar]);
            }
            for (lasLakemedelRegister[i].antalSaldo = 0; lasLakemedelRegister[i].antalSaldo < PAKETSTORLEKAR; lasLakemedelRegister[i].antalSaldo++)
            {            
                fscanf(fp, "%d", &lasLakemedelRegister[i].saldo[lasLakemedelRegister[i].antalSaldo]);
            }*/
            (*pAntalLakemedel)++;
            i++;
        }

Вот и пример файла, который я хочу прочитать:

Hello
25 40
2 5
Hi
85 41
2 3

Я ожидаю, что каждая строка, если числа будут считаны в массив, но причина, почему это не сделано, потому что он как-то перебрасывает символ новой строки и читает до следующей текстовой строки.

Вот полный код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXANTAL 10000
#define MAXORD 20
#define PAKETSTORLEKAR 10
#define FILNAMNSTORLEK 20

struct lakemedel
{
    char namn[MAXORD];
    char forpackningar[PAKETSTORLEKAR];
    int antalForpackningar;
    char saldo[PAKETSTORLEKAR];
    int antalSaldo;
};
typedef struct lakemedel Lakemedel;

void lasFil(Lakemedel lasLakemedelRegister[], int *pAntalLakemedel, char lasFilnamn[]);
void skrivUt(Lakemedel skrivLakemedelRegister[], int pAntalLakemedel);

int main()
{
    Lakemedel lakemedelRegister[MAXANTAL];
    char filnamn[FILNAMNSTORLEK];
    int antalLakemedel = 0;
    int val;
    lasFil(lakemedelRegister, &antalLakemedel, filnamn);
    //printf("%d", lakemedelRegister[0].forpackningar[0]);
    while (1 && val != 8)
    {   
        printf("\n\n2-Skriva\n8-Avsluta\n\n");
        scanf(" %d", &val);
        switch (val)
        {
        case 1: //Registrera
            break;     
        case 2: //Skriva ut
            skrivUt(lakemedelRegister, antalLakemedel);
            break;
        case 3: //Söka
            break;
        case 4: //Lägga till storlek
            printf("hello");
            break;
        case 5: //Ändra saldo för läkemedel
            printf("hello");
            break;
        case 6: //Avregistrera läkemedel
            break;
        case 7: //Varningar
            printf("hello");
            break;
        case 8: //Avslutar programmet
            printf("Avslutar Programmet...");
            break;
        default:
            break;
        } 
    }

    return 0;
}

void lasFil(Lakemedel lasLakemedelRegister[], int *pAntalLakemedel, char lasFilnamn[])
{
    printf("Skriv in fil du vill anvanda: ");
    scanf(" %s", lasFilnamn);
    int i = 0;
    FILE *fp;
    fp = fopen(lasFilnamn, "r");
    if(fp!=NULL)
    {   
        while(fscanf(fp,"%s", lasLakemedelRegister[i].namn)==1)
        {
            lasLakemedelRegister[i].antalForpackningar = 0;
            lasLakemedelRegister[i].antalSaldo = 0;
            printf("ff");
            while (fscanf(fp, "%d", &lasLakemedelRegister[i].forpackningar[lasLakemedelRegister[i].antalForpackningar]) == 1)
            {
                printf("aa ");
                lasLakemedelRegister[i].antalForpackningar++;                
            }
            while (fscanf(fp, "%d", &lasLakemedelRegister[i].saldo[lasLakemedelRegister[i].antalSaldo])==1)
            {
                printf("gg ");
                lasLakemedelRegister[i].antalSaldo++;
            }
            /*for (lasLakemedelRegister[i].antalForpackningar = 0; lasLakemedelRegister[i].antalForpackningar == 1; lasLakemedelRegister[i].antalForpackningar++)
            {            
                fscanf(fp, "%d", &lasLakemedelRegister[i].forpackningar[lasLakemedelRegister[i].antalForpackningar]);
            }
            for (lasLakemedelRegister[i].antalSaldo = 0; lasLakemedelRegister[i].antalSaldo < PAKETSTORLEKAR; lasLakemedelRegister[i].antalSaldo++)
            {            
                fscanf(fp, "%d", &lasLakemedelRegister[i].saldo[lasLakemedelRegister[i].antalSaldo]);
            }*/
            (*pAntalLakemedel)++;
            i++;
        }
    fclose(fp);
    }
        printf("\n\n%d\n", *pAntalLakemedel);
        printf("%s\n",lasLakemedelRegister[0].namn);
        printf("%d\n",lasLakemedelRegister[0].antalForpackningar);
        printf("%d\n", lasLakemedelRegister[0].antalSaldo);
}

1 Ответ

0 голосов
/ 17 октября 2019

В соответствии со стандартом C, fscanf при успешном завершении возвращает количество элементов, прочитанных из входного потока (которое может быть меньше, чем запрошенное число, если произошла ошибка чтения или достигнут конец файла). Если происходит ошибка чтения или достигнут конец файла до того, как будут прочитаны какие-либо данные, возвращается EOF.

Итак, как уже говорили другие, следующий цикл while не остановится на символе новой строки. Он будет остановлен только тогда, когда во входном потоке встретится нецелочисленный символ или достигнут EOF.

while (fscanf(fp, "%d", &lasLakemedelRegister[i].forpackningar[lasLakemedelRegister[i].antalForpackningar]) == 1)
{
   printf("aa ");
   lasLakemedelRegister[i].antalForpackningar++;                
}

Правильный способ чтения двух чисел из входного потока с помощью fscanf заключается в следующем:

numIntsRead = fscanf(fp, " %d %d", &intVar1, &intVar2);
// Use numIntsRead to ensure both numbers were actually read

Вы хотели бы отбросить два цикла while и просто вызвать приведенный выше код дважды для каждого читаемого набора 2x.

PS Обратите внимание на начальный пробел в спецификаторе формата. Согласно стандарту, пробел в спецификаторе формата может соответствовать ноль или больше символов пробела во входных данных. Это обеспечит правильный синтаксический анализ, если в файле есть начальные пробелы.

...