First of all sorry for any english error. So, I have this data in a .txt file
Codigo,Produto,StockMinimo,StockAtual
1,Couro,300,1000
2,Tecido,250,2000
...
I want to skip the first line and read only the integers to a struct
I'm using the bellow function to count the line of the file:
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;
}
and this one to read the file to the struct "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);
}
Function to print the struct:
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);
}
This is how i call the function in main:
int main(int argc, char** argv) {
char *nomeFicheiro1 = "tabela_stocks.txt";
Stock stock;
carregarStock(&stock, nomeFicheiro1);
mostrarStock(stock);
return (EXIT_SUCCESS);
}
The function to print the struct doesn't print. I guess the error is in
fscanf(fp, "%d,%s ,%d,%d", &codigo, storeProduto, &minimo, &quantidade);
What am I doing wrong?
You could create a helper function to read out the two integers from one line.
bool get_two(FILE *stream, int* a, int* b) {
return fscanf(stream, " %*[^,],%*[^,],%d,%d", a, b) == 2;
}
You then just need to call that 5 times.
Example:
#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);
}
}
If tabela_stocks.txt
contains
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
Then the output will be
300 1000
250 2000
200 500
500 2000
300 1000
Since there are so many similarities between the different stocks in your Stock
struct
, you could break it down into smaller pieces and make a struct
only holding information about one stock:
#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);
}
With that you could create a Stocks
type like this:
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);
}
and reading and printing would become simpler:
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);
}
}
Looking closer at the Stocks
struct
you may want to consider using an array instead:
typedef struct {
Stock stocks[5];
} Stocks;
which would also simplify the rest of the code since you could loop over that array to read and print each Stock
.