【问题标题】:Trouble using fscanf to read coordinates in C使用 fscanf 读取 C 中的坐标时遇到问题
【发布时间】:2015-08-04 21:35:40
【问题描述】:

我知道有人问过类似的问题,但似乎都没有解决我的问题。当我运行我的代码时,我得到了Segmentation fault (core dumped)

“data.dat”中的第一行包含文件中的点总数,下一行包含点坐标(二维)。我使用fgets 读取第一行,然后使用fscanf 读取下一行。

这是我的代码:

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

int main(int argc, char *argv[]) {
    int n = atoi(argv[1]);
    FILE *fp;
    fp = fopen("data.dat","r");
    if (fp == NULL) {
        perror("Error");
    }

    int number;
    char str[3];

    fgets(str, 3, fp);
    number = atoi(str); // number of points to read from the file
    printf("number of lines: %d\n", number);

    // defining matrix to hold points
    float *P = (float *) malloc(sizeof(float)*2*number);

    int i = 0;
    while(i < number){
        int ret = fscanf(fp, "%f%f", P[i*number + 1], P[i*number + 2]);
        printf("%f  %f", P[i*number + 1], P[i*number + 2]);
        if (ret == 2){
            i++;
        }
    }
    fclose(fp);
    return 0;
}

编译它不会给我任何错误,但它确实给了我以下警告:

polynom.c: In function ‘main’:
polynom.c:32:24: warning: format ‘%f’ expects argument of type ‘float*’,but argument 3 has type ‘double’ [-Wformat=]

int ret = fscanf(fp, "%f%f", P[i*number + 1], P[i*number + 2]);
                    ^
polynom.c:32:24: warning: format ‘%f’ expects argument of type ‘float *’, but argument 4 has type ‘double’ [-Wformat=]

我并没有真正理解,因为我确实将参数 3 定义为浮点数。

我使用命令行变量运行代码,所以分段错误不是因为这个。

【问题讨论】:

  • 如果您正在扫描三位数字,您会遇到一个非常大的问题,因为您的字符数组正好是 3 个字节长。您必须允许空终止,否则您的 atoi 将超出界限。
  • 请发布一些示例输入数据并尝试对其进行描述。
  • 代码将float 传递给fscanf()fscanf() 不需要知道float,它需要知道存储结果的float地址。使用fscanf(fp, "%f%f", &amp;P[i*number + 1] ...(添加&amp;)注意:还有很多其他问题
  • 编译时,始终启用所有警告。然后修复警告。毕竟,编译器比我们人类更了解 C 语言,而且人类容易犯错。建议阅读 fscanf() 的手册页,它会告诉你(除其他外)变量必须是指针。
  • 建议使用调试器,例如“gdb”来单步执行代码以确定哪一行导致了段错误事件。然后,您可以检查该行(和正在进行的事件)以确定 seg 故障事件的原因。

标签: c segmentation-fault coordinates scanf


【解决方案1】:

你需要使用"%lf"说明符,如果你的变量是double,你必须将变量的地址传递给scanf()而不是变量本身,像这样

double value;

if (scanf("%lf", &value) == 1) 
{   /*        ^   ^ */
    /*        |   the address of operator. */
    /*       the correct speficier for `double' */
    fprintf(stdout, "%lf\n", value);
}

【讨论】:

  • float *P?这是地址问题,而不是float v. double
【解决方案2】:

应该是

while (2 == fscanf(fp, "%f%f", &P[i], &P[i+1]) {
    i += 2;
    if (i >= number*2)
        break;
}

【讨论】:

    【解决方案3】:

    @Weather Vane很好地回答了主要问题。

    以下是附加点。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
        // Check argc 
        if (argc < 1) Print_Error_And Quit();
        int n = atoi(argv[1]);
        FILE *fp;
        fp = fopen("data.dat","r");
        if (fp == NULL) {
            perror("Error");
        }
    
        int number;
        char str[3];
    
        // avoid naked magic numbers
        // fgets(str, 3, fp);
        fgets(str, sizeof str, fp);
        number = atoi(str); // number of points to read from the file
        printf("number of lines: %d\n", number);
    
        // defining matrix to hold points
        // No need for cast, avoid mis-match type/variable
        // float *P = (float *) malloc(sizeof(float)*2*number);
        float *P = malloc(2*number * sizeof *P);
    
        int i = 0;
        while(i < number){
            // int ret = fscanf(fp, "%f%f", P[i*number + 1], P[i*number + 2]);
            // reform
            int ret = fscanf(fp, "%f%f", &P[2*i], &P[2*i + 1]);
            // printf("%f  %f", P[i*number + 1], P[i*number + 2]);
            printf("%f  %f ", P[2*i], P[2*i + 1]);
            if (ret == 2){
                i++;
            }
            else {
              Likely_Should_Exit_Loop();
            }
        }
        fclose(fp);
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      malloc 行正在返回一个指针,该指针指向一个足以容纳“number*2”浮点数的区域。听起来不错,但实际上无法正常工作,因为一个浮点数和下一个浮点数之间没有区别。

      建议

      struct twoFloat
      {
          float float1;
          float float2;
      };
      

      然后

      struct twoFloat* P = malloc(sizeof(struct twoFloat)*number);
      if ( NULL == P ) { // handle error and exit }
      
      // implied else, malloc successful
      ....
      

      然后

          int ret = fscanf(fp, "%f%f", &P[i].float1, &P[i].float2);
          if (ret != 2) { // handle error and exit }
      
          // implied else, fscanf successful
      
          printf("%f  %f", P[i].float1, P[i].float2);
          i++;
      

      【讨论】:

      • 我不明白您所说的“一个浮点数和下一个浮点数之间没有区别”是什么意思。你能校准吗?谢谢。
      猜你喜欢
      • 2017-12-04
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2012-09-28
      • 2017-07-21
      • 2015-10-19
      • 1970-01-01
      相关资源
      最近更新 更多