C - 从文本文件读取输入 (int,string,int,int)

C - Read input from text file (int,string,int,int)

首先,对于任何英文错误,我们深表歉意。 所以,我在 .txt 文件中有这些数据

Codigo,Produto,StockMinimo,StockAtual
1,Couro,300,1000
2,Tecido,250,2000
...

我想跳过第一行,只将整数读入结构

我正在使用波纹管函数来计算文件的行数:

int nrLinhasFicheiro(char *filename){
    char ch;
    FILE *file;
    file = fopen(filename, "r");
    int linhas = 0;
    if (file != NULL) {
         for (ch = getc(file); ch != EOF; ch = getc(file)) 
        if (ch == '\n')  
            linhas = linhas + 1; 
    }
    fclose(file);
    return linhas - 1;
}

而这个将文件读取到结构“Stock”:

void carregarStock(Stock *stock, char *nomeFicheiro){
    int i = 0;
    int codigo; //stores "codigo" values
    char stringFake[40], *storeProduto; //variables to store first line and "Produto" string
    int minimo, quantidade;
    
    FILE *fp = fopen(nomeFicheiro, "r");
    
    int numeroLinhas = nrLinhasFicheiro(nomeFicheiro);
    
    if (fp != NULL){
       
        if(numeroLinhas >0){
            fscanf(fp, "%s",stringFake);//skip first line
            
            while(i< numeroLinhas){
                fscanf(fp, "%d,%s ,%d,%d", &codigo, storeProduto, &minimo, &quantidade);
                //fscanf(fp, "%d,%s %d,%d", &codigo, storeProduto, &minimo, &quantidade);  also tried this and don't work
                
                if(codigo==1){
                    stock->minStockCouro = minimo;
                    stock->couroStock = quantidade;
                }else if(codigo==2){
                    stock->minStockTecido = minimo;
                    stock->tecidoStock = quantidade;
                }else if(codigo==3){
                    stock->minStockBorracha = minimo;
                    stock->borrachaStock = quantidade;
                }else if(codigo==4){
                    stock->minStockCordoes = minimo;
                    stock->cordoesStock = quantidade;
                }else if(codigo==5){
                    stock->minStockPalmilhas = minimo;
                    stock->palmilhasStock = quantidade;
                }   
                i++;
            }
            
        }else{
            puts("Error");          
        }      
    }else{
        puts(MSG_ERRO_LER_FICHEIRO);
    }
    fclose(fp);
}

打印结构的函数:

void mostrarStock(Stock stock){
    puts("==============  Stock : =============\n");
    puts("Codigo | Produto | Stock Minimo | Stock Atual\n");
    printf("1\tCouro\t\t%d\t\t%d\n", stock.minStockCouro, stock.couroStock);
    printf("2\tTecido\t\t%d\t\t%d\n", stock.minStockTecido, stock.tecidoStock);
    printf("3\tBorracha\t%d\t\t%d\n", stock.minStockBorracha, stock.borrachaStock);
    printf("4\tCordões\t\t%d\t\t%d\n", stock.minStockCordoes, stock.cordoesStock);
    printf("5\tPalmilhas\t%d\t\t%d\n", stock.minStockPalmilhas, stock.palmilhasStock);

}   

这就是我在 main 中调用函数的方式:

int main(int argc, char** argv) {
    
    char *nomeFicheiro1 = "tabela_stocks.txt";
    Stock stock;
    carregarStock(&stock, nomeFicheiro1);
    mostrarStock(stock);
    
    return (EXIT_SUCCESS);
}

打印结构的函数不打印。 我猜错误在

fscanf(fp, "%d,%s ,%d,%d", &codigo, storeProduto, &minimo, &quantidade);

我做错了什么?

您可以创建一个辅助函数来从一行中读出两个整数。

bool get_two(FILE *stream, int* a, int* b) {
    return fscanf(stream, " %*[^,],%*[^,],%d,%d", a, b) == 2;
}

然后你只需要调用它 5 次。

示例:

#include <stdbool.h>
#include <stdio.h>

typedef struct {
    int couroStock;
    int minStockCouro;
    int tecidoStock;
    int minStockTecido;
    int borrachaStock;
    int minStockBorracha;
    int cordoesStock;
    int minStockCordoes;
    int palmilhasStock;
    int minStockPalmilhas;
} Stock;

bool get_two(FILE *stream, int* a, int* b) {
    return fscanf(stream, " %*[^,],%*[^,],%d,%d", a, b) == 2;
}

int main() {
    FILE *fp = fopen("tabela_stocks.txt", "r");
    if(fp) {
        Stock s;
        fscanf(fp, "%*[^\n]"); // skip first line

        if(get_two(fp, &s.couroStock, &s.minStockCouro) &&
           get_two(fp, &s.tecidoStock, &s.minStockTecido) &&
           get_two(fp, &s.borrachaStock, &s.minStockBorracha) &&
           get_two(fp, &s.cordoesStock, &s.minStockCordoes) &&
           get_two(fp, &s.palmilhasStock, &s.minStockPalmilhas))
        {
            printf("%d %d\n", s.couroStock, s.minStockCouro);
            printf("%d %d\n", s.tecidoStock, s.minStockTecido);
            printf("%d %d\n", s.borrachaStock, s.minStockBorracha);
            printf("%d %d\n", s.cordoesStock, s.minStockCordoes);
            printf("%d %d\n", s.couroStock, s.minStockCouro);
        }
        fclose(fp);
    }
}

如果tabela_stocks.txt包含

Codigo,Produto,StockMinimo,StockAtual
1,Couro,300,1000
2,Tecido,250,2000
3,Borracha,200,500
4,Cordões,500,2000
5,Palmilhas,500,1000

那么输出将是

300 1000
250 2000
200 500
500 2000
300 1000

由于您的 Stock struct 中的不同股票之间有很多相似之处,您可以将其分解成更小的部分并制作一个 struct 仅包含有关 一个 存货:

#include <stdbool.h>
#include <stdio.h>

typedef struct {
    int stock;
    int min_stock;
} Stock;

bool Stock_read(FILE *stream, Stock *s) {
    return fscanf(stream, " %*[^,],%*[^,],%d,%d", &s->stock, &s->min_stock) == 2;
}

void Stock_print(const Stock *s) {
    printf("%d %d\n", s->stock, s->min_stock);
}

这样你就可以创建一个 Stocks 类型:

typedef struct {
    Stock Couro;
    Stock Tecido;
    Stock Borracha;
    Stock Cordoes;
    Stock Palmilhas;
} Stocks;

bool Stocks_read(FILE *stream, Stocks *s) {
    return
        Stock_read(stream, &s->Couro) &&
        Stock_read(stream, &s->Tecido) &&
        Stock_read(stream, &s->Borracha) &&
        Stock_read(stream, &s->Cordoes) &&
        Stock_read(stream, &s->Palmilhas);
}

void Stocks_print(const Stocks *s) {
    Stock_print(&s->Couro);
    Stock_print(&s->Tecido);
    Stock_print(&s->Borracha);
    Stock_print(&s->Cordoes);
    Stock_print(&s->Palmilhas);
}

阅读和打印会变得更简单:

int main() {
    FILE *fp = fopen("tabela_stocks.txt", "r");
    if(fp) {
        Stocks s;
        fscanf(fp, "%*[^\n]"); // skip first line

        if(Stocks_read(fp, &s)) {
            Stocks_print(&s);
        }
        fclose(fp);
    }
}

仔细观察 Stocks struct 您可能需要考虑改用数组:

typedef struct {
    Stock stocks[5];
} Stocks;

这也将简化其余代码,因为您可以遍历该数组以读取和打印每个 Stock.