我试图从文本文件读取到具有指向另一个结构的指针的结构。
文本文件格式如下:
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;
}
在if成功后(当访问我日期的struct的指针时)尝试运行fscanf时,它给出了一个bad_access错误。如果有人能帮助我,我会非常感激。
答案 0 :(得分:1)
现在你在循环中为aux
分配内存,然后尝试使用不起作用的索引来访问元素。相反,您需要为所有Cliente
条记录分配内存。如果您知道文件中的记录数,则可以执行aux = (Cliente*)malloc(size * sizeof(Cliente));
。您还可以检查如何在实际循环中使用realloc()
。
答案 1 :(得分:1)
在
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()
的错误检查。
答案 2 :(得分:0)
您正在使用 <{strong> 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);