【问题标题】:Array of pointers and Segmentation Fault (Core Dumped) in CC中的指针数组和分段错误(核心转储)
【发布时间】:2023-03-09 07:42:01
【问题描述】:

我正在尝试用 C 语言编写一个从输入文件(“input0”)读取的程序,该文件遵循以下格式: 约翰·多伊 1230 4.0

我正在尝试使用 fscanf 从文档中读取并将这些值输入到结构中。但目前,在编译并运行代码后,我遇到了神秘的“分段错误(核心转储)”。

我的代码中当前发出此错误的行是带有 fscanf 语句的行。我找不到解决办法。

此外,strcpy 在取消注释后会报错。我在运行代码时收到警告,我认为这与什么是指针和什么是字符串存在差异,这是我无法解决的另一个问题。任何帮助将不胜感激。

typedef struct {
    char fname[1000];
    char lname[1000];
    long int id;
    double gpa;
} student_t;

int main(int argc, char *argv[]) {
    FILE *db;
    student_t students[1000];
    char* fname[1000];
    char* lname[1000];
    long int id[1000];
    double gpa[1000];
    long int i, j;
    i = 0;
    db = fopen("input0", "r");
    while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], id[i], gpa[i]) != EOF) {
        //strcpy(students[i].fname, fname[i]);
        //strcpy(students[i].lname, lname[i]);
        students[i].id = id[i];
        students[i].gpa = gpa[i];
        i++;
    }
    for(j = 0; j <= i; j++) {
    //printf("%s %s %d %f\n", _SJ.fname, _SJ.lname, _SJ.id, _ST.gpa);
    }
    fclose(db);
}

【问题讨论】:

  • 从文件中读取的方式非常脆弱,请改用 fgets/sscanf alt。 fgets/strtok.

标签: c pointers segmentation-fault scanf


【解决方案1】:

当你声明例如

char* fname[1000];

您有一个1000 数组未初始化的指针。尝试使用这些指针之一将导致未定义的行为。您需要为指针分配内存,或者将它们指向其他(已分配的)内存。

其实我觉得你真正想做的是

fscanf(db, "%s %s %d %lf",
    students[i].fname, students[i].lname, &students[i].id, &students[i].gpa)

我还建议您阅读例如this fscanf reference,因为 fscanf 可以返回其他值,这意味着输入中存在错误(例如,如果输入文件格式错误)。

【讨论】:

  • 添加fscanf(db, "%999s %999s %d %lf", ... 可以防止代码溢出.fname.lname
【解决方案2】:

您忘记在fscanf 中使用&amp; 来表示long intdouble

while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], &id[i], &gpa[i]) != EOF)

【讨论】:

    【解决方案3】:

    改变这一行

    while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], id[i], gpa[i]) != EOF)
    

    while(fscanf(db, "%s %s %d %lf", students[i].fname, students[i].lname, &students[i].id, &students[i].gpa) != EOF)
    

    那么您可能不需要任何strcpy 或将intdouble 复制回结构。

    char *fname[1000]会分配char的1000个指针

    【讨论】:

      【解决方案4】:

      我修复了一些问题:

      typedef struct {
          char fname[1000];
          char lname[1000];
          long int id;
          double gpa;
      } student_t;
      
      student_t students[1000];
      
      int main(int argc, char *argv[]) {
          FILE *db;   
          long int i=0, j;    
          db = fopen("input0.txt", "r");
          if (db == NULL)
          {
              perror("Error opening file input0");
              return -1;
          }
          while (fscanf(db, "%s %s %d %lf", students[i].fname, students[i].lname, 
                                            &students[i].id, &students[i].gpa) != EOF) 
          {       
              i++;
          }
          for (j = 0; j < i; j++) {
              printf("%s %s %d %f\n", students[j].fname, students[j].lname, students[j].id, students[j].gpa);
          }
          fclose(db);
      }
      

      您可以直接读取学生数组,避免使用 strcpy。缺少的 & 也被添加了。 请注意,我将 students[1000] 移到主函数之外,与 VS2013 的标准堆栈大小一样,代码产生了堆栈溢出。打开文件时,请始终检查您是否设法打开它们......这将在未来节省数小时的调试痛苦。 j

      在您的原始代码中:

      char* fname[1000];
      

      您使用了 1000 个字符*,但这一行只为指针本身分配空间。我认为您正在尝试编写如下内容:

      char fname[1000];
      

      在这种情况下,frame 将有 1000 个字符,您可以使用它来存储从输入文件中读取的名称。在进一步学习 C 之前注意这两行之间的区别非常重要。在 fname[1000] 的情况下,您可以读取到 fname,即没有索引。然后 strcpy(students[i].fname, fname)。希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2021-05-04
        • 2015-05-12
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 2014-04-11
        • 1970-01-01
        • 1970-01-01
        • 2016-09-07
        相关资源
        最近更新 更多