【问题标题】:C Segmentation fault with fscanf使用 fscanf 的 C 分段错误
【发布时间】:2016-04-06 16:27:30
【问题描述】:

尝试使用 fscanf 读取输入的 .txt 文件,并将行内容存储到 int 变量、数组和 2D 数组中,以便稍后使用该值进行计算。我认为这里的问题是因为我没有使用 fscanf 处理“EOF”?

这是我的代码:

int main(){
FILE *fp;

int n;  // # resources
int m;  // # processes
int avail[n];
int max[m][n], allo[m][n];
char temp1[10];

fp = fopen("test.txt", "r");
if (fp == NULL){
    exit(EXIT_FAILURE);
}


fscanf(fp, "%d %d", &n, &m);
printf("%d %d", n, m);
printf("\n");

// Store the second line content to allo[]
for(int i = 0; i < n; i++){
    fscanf(fp, "%s", temp1);
    avail[i] = atoi(temp1);
    printf("%d ", avail[i]);
}
printf("\n");

// Store the line3-7 content to 2D max[][]
for(int i = 0; i < m; i++){
    for(int j = 0; j < n; j++){
        fscanf(fp, "%s", temp1);
        max[i][j] = atoi(temp1);
        printf("%d ", max[i][j]);
    }
    printf("\n");
}

// Store the line8-12 content to 2D allo
for(int i = 0; i < m; i++){
        for(int j = 0; i < n; j++){
            fscanf(fp, "%s", temp1);
            allo[i][j] = atoi(temp1);
            printf("%d ", allo[i][j]);
        }
        printf("\n");
}


fclose(fp);
return 0;
}

这是 .txt 输入文件:

3 5
9 6 3
5 5 2
4 1 3
8 3 4
5 4 2
4 4 3
0 1 0
1 1 0
1 0 2
0 0 1
1 2 2

这是输出:

3 5
9 6 3
5 5 2
4 1 3
8 3 4
5 4 2
4 4 3
Segmentation fault: 11

【问题讨论】:

  • int max[m][n], allo[m][n], need[n][m]; ... mn 尚未初始化,因此它是未定义的行为。除此之外,当您更改定义它们的变量时,VLA 不会自行调整大小。我还注意到mn 被转换为need[n][m]
  • 请不要更改问题来尝试解决问题。在您自己的办公桌上执行此操作,否则会使对话看起来无关紧要。

标签: c io scanf


【解决方案1】:

问题出在这里:

int n;  // # resources
int m;  // # processes
int avail[n];
int max[m][n], allo[m][n], need[n][m];

nm 在声明二维数组 max没有初始化。尝试在int max[m][n]; 之前打印nm 等,您会发现它们包含垃圾值。

因此,Undefined Behavior 是您所遇到的,因为您无法真正判断数组的大小。

改成这样:

int n;  // # resources
int m;  // # processes

fscanf(fp, "%d %d", &n, &m);
printf("%d %d", n, m);

int avail[n];
int max[m][n], allo[m][n], need[n][m];

现在,当您创建数组时,nm 将使用从文件中读取的值进行初始化。


如果您想在读取nm 之前声明您的数组,那么您应该使用指针,读取nm,然后读取dynamically allocate the arrays

【讨论】:

  • 但使用 fscanf 时仍然出现 seg 错误
  • 我可以先将 n & m 初始化为 0,然后 fscanf 会将输入中的一些值返回给 n & m。那么现在 n & m 不是未定义的。无论如何,我用您的更改对其进行了编辑,但仍然出现了段错误。我认为问题出在 fscanf 到达“行终止”的结束文件时。
  • 您确定您的阵列创建正确吗?也许用最新的尝试更新你的帖子@fruitlancer122?
【解决方案2】:

您声明了int max[m][n], allo[m][n], need[n][m],而mn 尚未设置,因此它们的大小未知。设置大小后,它们不会自行调整大小。所以写这些会给你“未定义的行为”

【讨论】:

    【解决方案3】:

    由于在文件顶部声明数组时 m,n 未初始化:

    int avail[n];
    int max[m][n], allo[m][n], need[n][m];
    

    正如@WeatherVane 在 cmets 中所述,您将获得未定义的行为。也许您正在覆盖程序内存的其他部分(谁知道它是未定义的!)。

    如果您需要创建动态数组,您应该执行以下操作:

    int* avail;
    ...
    fscanf(fp, "%d %d", &n, &m);
    avail = (int*)malloc(n*sizeof(int));
    

    【讨论】:

      【解决方案4】:

      当你初始化 max、allo 和需要时。 n 和 m 的值没有定义。

      您可以将maxalloneed 定义为int**

      扫描完n和m的值后,就可以调用下面的函数为上面的二维数组分配内存了。

      int ** get2DintArray(int r, int c){
          int **arr = (int **)malloc(r * sizeof(int *));
          for (i=0; i<r; i++)
               arr[i] = (int *)malloc(c * sizeof(int));
          return arr;
      }
      

      为了。例如:-

      allo = get2DintArray(m,n);
      need = get2DintArray(n,m);
      

      这种方法适用于较大的 n 和 m 值,此时堆栈内存可能不够用,因为在这种情况下您使用的是堆内存。

      【讨论】:

      • 你忘了return arr;
      • 感谢您的提醒!你也可以直接编辑它!
      猜你喜欢
      • 2017-03-29
      • 2015-02-09
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多