繁体   English   中英

fscanf从文本文件到结构指针

[英]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成功后尝试运行fscanfif会给我bad_access错误

2个问题:

  1. 正如@Rishikesh Raje@Cyclonecode指出的那样,该分配仅对aux = aux[0]以及其他缺少的分配有效。

  2. 通常扫描问题的怀疑者是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()错误检查。

同时使用getcfscanf访问文件。

如果要使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM