C 为什么函数中的Printf可以防止结构数组中的变量在另一个函数中损坏?

C 为什么函数中的Printf可以防止结构数组中的变量在另一个函数中损坏?,c,string,file,printf,corruption,C,String,File,Printf,Corruption,我有一个函数可以读取一个文件和一个结构数组的属性多个整数和字符串,我的fscanf格式字符串如下所示:%d.%d.%d.%d%60c%60c%d%8c“ 当我扫描它时,如果我使用printf,那么一切都是好的,但是如果我不使用printf,那么最后的两个字符串在最后会被破坏 由于文件很大,而这不是函数的目的,所以我想将printf取出 typedef struct { int nacional; int regional; int distrital; int

我有一个函数可以读取一个文件和一个结构数组的属性多个整数和字符串,我的
fscanf
格式字符串如下所示:
%d.%d.%d.%d%60c%60c%d%8c“

当我扫描它时,如果我使用printf,那么一切都是好的,但是如果我不使用printf,那么最后的两个字符串在最后会被破坏

由于文件很大,而这不是函数的目的,所以我想将printf取出

 typedef struct
 {
    int nacional;
    int regional;
    int distrital;
    int municipal;
  }id_geo;

  typedef struct
  {
    id_geo id_geo;
    long int cartao_cid;
    char nome_dono[61];
    char morada[61];
    int num_porta;
    char codigo_postal[9];
   }prop_id_dono;
prop_id_dono *ler_ficheiro(char *file_name, int num_linha) {
    prop_id_dono *info_geral;
    long int cartao_cid;
    char nome_ficheiro;
    char nome_dono[60];
    char morada[60];
    int num_porta;
    char codigo_postal[8]; 
    int nacional;
    int regional;
    int distrital;
    int municipal; 
    int i = 0;
    FILE *fp; 

    fp = fopen(file_name, "r");
    if (fp == NULL)
        printf("Peço desculpa, mas não foi possível abrir o ficheiro.");

    info_geral = (prop_id_dono *)malloc(sizeof(prop_id_dono) * num_linhas); 

    while (fscanf(fp, "%d.%d.%d.%d %ld %60c%60c%d %8c\n",
           &nacional, &regional, &distrital, &municipal,
           &cartao_cid, nome_dono, morada, &num_porta, codigo_postal) != EOF) {

        // Faz o scan ao ficheiro através de variáveis temporais, sendo que só 
        // depois é que atribui valores ao vetor que contém a informação geral
        info_geral[i].id_geo.nacional = nacional;
        info_geral[i].id_geo.regional = regional;
        info_geral[i].id_geo.distrital = distrital;
        info_geral[i].id_geo.municipal = municipal;
        info_geral[i].cartao_cid = cartao_cid;
        strcpy(info_geral[i].nome_dono, nome_dono + '\0');
        strcpy(info_geral[i].morada, morada + '\0');
        info_geral[i].num_porta = num_porta;
        strcpy(info_geral[i].codigo_postal, codigo_postal + '\0');

        //This is the magical printf
        printf("%d.%d.%d.%d %ld %s%s%d %s \n",
               info_geral[i].id_geo.nacional, info_geral[i].id_geo.regional,
               info_geral[i].id_geo.distrital, info_geral[i].id_geo.municipal,
               info_geral[i].cartao_cid, info_geral[i].nome_dono,
               info_geral[i].morada, info_geral[i].num_porta, 
               info_geral[i].codigo_postal);
        i++;    
    }
    fclose(fp);
    return info_geral;
}
输入是这样的,但它在文件中重复了20000次
1.1.1.1 1234568姓名,总共60个字符(包括空格)地址(与此处空格相同)门牌号邮政编码

您使用%60c将输入片段解析为大小为60的字符数组

假设转换成功,这些数组将不包含正确的C字符串,并且您连接
'\0'
的尝试在C中不起作用

以下是改进您的计划的方法:

  • 您应该将行读入本地数组,以便在转换失败时更容易地报告错误,并使用
    sscanf()
    fo解析
  • 您应该使目标数组长一个字节,并在末尾设置空终止符。
    prop\u id\u dono
    结构中的数组也应足够大
  • 您应该检查
    sscanf
    的返回值,并报告转换失败
  • 您应该在
    num\u linhas
    行之后停止扫描
  • 您应该检查内存分配失败
以下是更正的版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int nacional;
    int regional;
    int distrital;
    int municipal;
} id_geo;

typedef struct {
    id_geo id_geo;
    long int cartao_cid;
    char nome_dono[61];
    char morada[61];
    int num_porta;
    char codigo_postal[9];
} prop_id_dono;

prop_id_dono *ler_ficheiro(const char *file_name, int num_linha) {
    char buf[256];
    prop_id_dono *info_geral;
    long int cartao_cid;
    char nome_ficheiro;
    char nome_dono[61];
    char morada[61];
    int num_porta;
    char codigo_postal[9]; 
    int nacional;
    int regional;
    int distrital;
    int municipal; 
    int i = 0;
    FILE *fp; 

    fp = fopen(file_name, "r");
    if (fp == NULL) {
        printf("Peço desculpa, mas não foi possível abrir o ficheiro.");
        return NULL;
    }
    // use calloc to allocate an array initialized to all bits zero
    info_geral = (prop_id_dono *)calloc(num_linhas, sizeof(prop_id_dono));
    if (info_geral == NULL) {
        fclose(fp);
        return NULL;
    }

    while (i < num_linhas && fgets(buf, sizeof buf, fp) != NULL) {
        // Faz o scan ao ficheiro através de variáveis temporais, sendo que só 
        // depois é que atribui valores ao vetor que contém a informação geral
        if (sscanf(buf, "%d.%d.%d.%d %ld %60c%60c%d %8c",
                   &nacional, &regional, &distrital, &municipal,
                   &cartao_cid, nome_dono, morada, &num_porta, codigo_postal) != 9) {
            printf("parsing error: %s", buf);
            continue;
        }
        info_geral[i].id_geo.nacional = nacional;
        info_geral[i].id_geo.regional = regional;
        info_geral[i].id_geo.distrital = distrital;
        info_geral[i].id_geo.municipal = municipal;
        info_geral[i].cartao_cid = cartao_cid;
        nome_dono[60] = '\0';
        strcpy(info_geral[i].nome_dono, nome_dono);
        morada[60] = '\0';
        strcpy(info_geral[i].morada, morada);
        info_geral[i].num_porta = num_porta;
        codigo_postal[8] = '\0';
        strcpy(info_geral[i].codigo_postal, codigo_postal);
        i++;    
    }
    fclose(fp);
    // note that the caller does not receive the number of lines parsed.
    // passing the address of a int for this purpose if a good solution.
    return info_geral;
}
#包括
#包括
#包括
类型定义结构{
国际民族;
国际区域组织;
国际区;
国际市政;
}id_geo;
类型定义结构{
id_geo id_geo;
长内卡塔奥西德;
char nome_dono[61];
char morada[61];
国际门户;
char codigo_邮政[9];
}道具;
prop_id_dono*ler_ficheiro(常量字符*文件名,int num\u linha){
char-buf[256];
道具识别号*信息栏;
长内卡塔奥西德;
char nome_ficheiro;
char nome_dono[61];
char morada[61];
国际门户;
char codigo_邮政[9];
国际民族;
国际区域组织;
国际区;
国际市政;
int i=0;
文件*fp;
fp=fopen(文件名,“r”);
如果(fp==NULL){
printf(“Peço desculpa,mas não foi possível abrir o ficheiro”);
返回NULL;
}
//使用calloc分配一个初始化为所有零位的数组
info_geral=(prop_id_dono*)calloc(num_linhas,sizeof(prop_id_dono));
if(info_geral==NULL){
fclose(fp);
返回NULL;
}
而(i
几乎可以肯定,这意味着您有导致未定义行为的代码。例如,缓冲区溢出。首先请注意,
+
在C语言中不进行字符串连接,因此strcpy调用可能会导致缓冲区溢出。但是不能确定,因为您没有提供输入数据,也没有提供
属性id\u dono的定义。我已经添加了结构和输入,抱歉,第一次在这里发布海报。但这解决了它!非常感谢你!