【问题标题】:Segmentation error in the C programming languageC 编程语言中的分段错误
【发布时间】:2021-05-11 23:06:51
【问题描述】:

这是我的 C 代码。首先,我创建了结构数据,然后读取了一个二进制文件,但是我的 fscanf 函数无法正常工作。我遇到了分段错误。

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

#define DATA_FILE "records.dat"

struct record
{
    char name[64];
    char surname[64];
    char gender;
    char email[32];
    char phone_number[16];
    char address[32];
    char level_of_education[8];
    unsigned int income_level;
    unsigned int expenditure;
    char currency_unit[16];
    char currentModd[32];
    float height;
    unsigned int weight;
};
typedef struct record myrecord;

int main()
{
    myrecord rItem;
    FILE *fp;
    struct record Myrecord;
    if ((fp = fopen(DATA_FILE, "r")) != NULL)
    {
        fscanf(fp, "%s %s %s %s %s %s %s %d %d %s %s %f %d\n", &rItem.name, &rItem.surname, &rItem.gender, &rItem.email,
               &rItem.phone_number, &rItem.address, &rItem.level_of_education, &rItem.income_level, &rItem.expenditure,
               &rItem.currency_unit, &rItem.currentModd, &rItem.height, &rItem.weight
        );
        printf("doneeee");
    }
    else
    {
        printf("errorrrr ");
    }
}

我的输出是这样的:

分段错误

[Done] 在 0.17 秒内以 code=139 退出

【问题讨论】:

  • 您不能使用 %s 格式说明符来读取 single char 变量,就像您尝试使用 &amp;rItem.gender 参数一样。不过,不确定这是否是唯一的问题,因为您谈到读取“二进制文件”,但 fscanf 用于 text 模式输入。修复取决于您希望gender 字段是什么:单个字符(然后使用%c)或以null 结尾的字符串(然后它需要是char 的数组,与其他字段一样)。
  • 从数组分配中删除 &amp;。您不需要为已经是指针的内容传递指针。
  • 另外,将%u 用于无符号 整数-%d 用于有符号 参数。
  • 永远不要使用%s。始终添加最大字段宽度,该宽度最多比将写入的缓冲区大小小 1。例如fscanf(fp,"%63s %63s ... 当您认为gender 的大小为1 时,您可能会想使用格式字符串%0s,这应该表明有问题。
  • 您还应该检查 f/s scanf 系列函数的返回值。

标签: c


【解决方案1】:

到目前为止的建议已经说:

  1. 在 fscanf() 调用中删除“字符串”变量前面的“&”。
  2. 将“%d”更改为“%u”作为 fscanf() 调用中“unsigned int”变量的说明符
  3. 将“%s”更改为“%c”作为 fscanf() 调用中“char”(不是 char [])变量的说明符
  4. 在 fscanf() 调用中将长度说明符添加到“%s”

注意:您没有显示“records.dat”文件的内容,与规格不符。

然而你说你已经做出了改变,但仍然出现分段错误。

假设这是您的“records.dat”文件(只有一行):

<-my_name-> <-sir_name-> M <-email-> <-phone-> <-address-> <-levl-> 50000 5000 <-mon-unit-> <-currMODD-> 14.5 250

这是对您的代码进行上述所有修改(除了#4)的示例,它还打印出 fscanf() 的结果。它还包含您的原始代码,已注释掉。 在针对我的“records.dat”进行测试时,这不会 segv。我把它留给你来整合 #4 建议,并在你的 records.dat 版本上进行测试。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DATA_FILE "records.dat"
 struct record {
    char name[64];
    char surname[64];
    char gender;
    char email[32];
    char phone_number[16];
    char address[32];
    char level_of_education[8];
    unsigned int income_level;
    unsigned int expenditure;
    char currency_unit[16];
    char currentModd[32];
    float height;
    unsigned int weight;
 };
typedef struct record myrecord;
int main()
{
    myrecord rItem;
    FILE *fp;
    struct record Myrecord;
    if ((fp = fopen(DATA_FILE,"r")) !=NULL)
    {
        /* ORIG:  fscanf(fp,"%s %s %s %s %s %s %s %d %d %s %s %f %u\n",
          &rItem.name,               // 1
          &rItem.surname,            // 2
          &rItem.gender,             // 3  - char
          &rItem.email,              // 4
          &rItem.phone_number,       // 5
          &rItem.address,            // 6
          &rItem.level_of_education, // 7
          &rItem.income_level,       // 8  - unsigned int
          &rItem.expenditure,        // 9  - unsigned int
          &rItem.currency_unit,      // 10
          &rItem.currentModd,        // 11
          &rItem.height,             // 12 - float
          &rItem.weight);            // 13 - unsigned int
     */
              //   1  2  3  4  5  6  7  8  9  10 11 12 13
        fscanf(fp,"%s %s %c %s %s %s %s %u %u %s %s %f %u\n",
           rItem.name,               // 1
           rItem.surname,            // 2
          &rItem.gender,             // 3  - char
           rItem.email,              // 4
           rItem.phone_number,       // 5
           rItem.address,            // 6
           rItem.level_of_education, // 7
          &rItem.income_level,       // 8  - unsigned int
          &rItem.expenditure,        // 9  - unsigned int
           rItem.currency_unit,      // 10
           rItem.currentModd,        // 11
          &rItem.height,             // 12 - float
          &rItem.weight);            // 13 - unsigned int
        printf("doneeee\n");
    printf("name:     %s\n"
           "surname:  %s\n"
           "gender:   %c\n"
           "email:    %s\n"
           "phone:    %s\n"
           "address:  %s\n"
           "ed_level: %s\n"
           "incm_lvl: %u\n"
           "expend:   %u\n"
           "CurrUnit: %s\n"
           "CurrModd: %s\n"
           "height:   %f\n"
           "weight:   %u\n",
           rItem.name,               // 1
           rItem.surname,            // 2
           rItem.gender,             // 3  - char
           rItem.email,              // 4
           rItem.phone_number,       // 5
           rItem.address,            // 6
           rItem.level_of_education, // 7
           rItem.income_level,       // 8  - unsigned int
           rItem.expenditure,        // 9  - unsigned int
           rItem.currency_unit,      // 10
           rItem.currentModd,        // 11
           rItem.height,             // 12 - float
           rItem.weight);            // 13 - unsigned int

    }
    else{
        printf("errorrrr ");
    }
    
    
}

【讨论】:

    【解决方案2】:

    尝试在您的 scanf 中的字符串值中不使用 &。例如,您的变量“名称”。不使用 [] 编写它已经意味着它是指向数组第一个字符的指针。通过写 &name 你将指向指针。

    【讨论】:

      猜你喜欢
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多