[英]fscanf from text file to struct pointer
我正在尝试从文本文件读取具有指向另一个结构的指针的结构。
文本文件具有以下格式:
279288151 1 John Doe
002 1 30 04 2018
23189842 0 Jane Doe
0
282676381 1 Mark Examp
001 0 28 03 2018 03 04 2018
243897574 1 Joe Soap
003 2 14 04 2018 21 04 2018
这是我的.h文件:
#ifndef Clientes_h
#define Clientes_h
#include <stdio.h>
#include <stdlib.h>
#include "Alugueres.h"
#define ST_TAM 50
typedef struct info_cliente Cliente;
struct info_cliente{
char nome[ST_TAM];
long nif;
int n_alugueres;
int n_hist;
pAluga aluguer;
};
typedef struct aluga Aluguer, *pAluga;
typedef struct data DataIn, *pDataIn;
typedef struct data DaraEn, *pDataEn;
struct aluga{
int id_unico;
int estado;
pDataIn dataIn;
pDataEn dataEn;
pAluga prox;
};
struct data{
int dia;
int mes;
int ano;
};
Cliente* le_fich(char *nome, int *n);
#endif /* Clientes_h */
我的read_file函数如下:
#include "Clientes.h"
Cliente* le_fich(char *nome, int *n){
FILE *f = fopen(nome, "r");
Cliente *aux;
int conta = 0;
if(!f){
printf("Error\n");
return NULL;
}
while(getc(f) != EOF){
aux = (Cliente*)malloc(sizeof(Cliente));
fscanf(f, "%ld %d %49[^\n]", &aux[conta].nif, &aux[conta].n_alugueres, aux[conta].nome);
if(aux[conta].n_alugueres != 0){
fscanf(f, "%d %d %d %d %d", &aux[conta].aluguer->id_unico,
&aux[conta].aluguer->estado, &aux[conta].aluguer->dataIn->dia,
&aux[conta].aluguer->dataIn->mes, &aux[conta].aluguer->dataIn->ano);
}
conta++;
}
return aux;
}
如果在成功后尝试运行fscanf(在为我的日期访问结构的指针时),它给我bad_access错误。 如果有人可以帮助我,将不胜感激。
现在,您在循环中为aux
分配了内存,然后尝试使用无法使用的索引访问元素。 相反,您需要为所有Cliente
记录分配内存。 如果您知道文件中的记录数,则只需执行aux = (Cliente*)malloc(size * sizeof(Cliente));
。 您可能还会检查如何在实际循环中使用realloc()
。
if
成功后尝试运行fscanf
,if
会给我bad_access错误
2个问题:
正如@Rishikesh Raje , @Cyclonecode指出的那样,该分配仅对aux = aux[0]
以及其他缺少的分配有效。
通常扫描问题的怀疑者是fscanf()
没有扫描预期的结果,并且代码缺少对返回值的检查。 (提示:当行仅是"0\\n"
,第二个fscanf()
读取的内容超出了OP的预期值。)
ret = fscanf(f, "%ld %d %49[^\\n]", ...); if((ret ==3) && (aux[conta].n_alugueres != 0)){ fscanf(f, "%d %d %d %d %d", ... // code errantly does not check the return value of `fscanf()`. } else { break; // This code missing, what to do when `ret != 3` }
这两个问题的简单解决方案是根据需要分配(重新)并检查读取2行并对其进行扫描是否成功。
我建议在验证输入之前,不要为新的线对分配数据。
Cliente *aux = NULL; // Initialize to NULL
size_t n = 0; // Keep count of record count
char buf1[150]; // Use generous buffers. Suggest 2x maximum expected need
char buf2[100];
// while 2 lines successfully read
while (fgets(buf1, sizeof buf1, f) && fgets(buf2, sizeof buf2, f)) {
// Form objects to be scanned into with default values.
struct info_cliente cli = { 0 };
struct aluga alu = { 0 };
struct data dat = { 0 };
if (sscanf(buf1, "%ld %d %49[^\n]", &cli.nif, &cli.n_alugueres, cli.nome) != 3) {
perror("Unexpected 1st line");
break;
}
if (cli.n_alugueres == 0) {
if (sscanf(buf2, "%d", &alu.id_unico) != 1 || alu.id_unico != 0)) {
perror("Unexpected 2nd line 0");
break;
}
}
else if (cli.n_alugueres == 1) {
if (sscanf(buf2, "%d %d %d %d %d", &alu.id_unico, &alu.estado, &dat.dia,
&dat.mes, &dat.ano) != 5) {
perror("Unexpected 2nd line");
break;
}
alu.dataIn = malloc(sizeof *alu.dataIn);
*alu.dataIn = dat;
cli.aluguer = malloc(sizeof *cli.aluguer);
*cli.aluguer = alu;
} else {
perror("Unexpected 2nd line n_alugueres");
break;
}
Cliente *tmp = realloc(aux, sizeof *aux * (n+1));
aux = tmp;
aux[n] = cli;
n++;
}
Cliente *tmp = realloc(aux, sizeof *aux * (n+1));
aux = tmp;
aux[n] = NULL; // NULL terminate the list
注意为简洁起见,在上面的示例代码中省略了对malloc()
/ realloc()
错误检查。
您同时使用getc
和fscanf
访问文件。
如果要使用fscanf
,则不应使用getc
。
使用fscanf
的返回值可让您知道文件何时结束。 fscanf
将返回匹配的项目数。 如果您成功,则应返回3
。
int ret;
do{
aux = (Cliente*)malloc(sizeof(Cliente));
ret = fscanf(f, "%ld %d %49[^\n]", &aux[conta].nif, &aux[conta].n_alugueres, aux[conta].nome);
if((ret ==3) && (aux[conta].n_alugueres != 0)){
fscanf(f, "%d %d %d %d %d", &aux[conta].aluguer->id_unico,
&aux[conta].aluguer->estado, &aux[conta].aluguer->dataIn->dia,
&aux[conta].aluguer->dataIn->mes, &aux[conta].aluguer->dataIn->ano);
}
conta++;
}while (ret == 3);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.