【问题标题】:fscanf not reading from file as expectedfscanf 未按预期从文件中读取
【发布时间】:2015-05-01 16:33:50
【问题描述】:

我有一些代码试图从文件中读取集团实例。实例文件中的第一行和第二行分别表示顶点和边的数量。但是我的代码似乎没有正确阅读。这是我的代码中与问题相关的部分:

int num_edges=0;
int num_vertices=0;

char *clique_file = "cliqueinstance";
char *mono_file= "monotone2sat";

FILE* fp_input = fopen(clique_file, "r");
FILE* fp_output = fopen(mono_file, "w");

if (fp_input == 0 )
{
    printf( "Could not open input file\n" );
    return 0;
}

if (fp_output == 0 )
{
    printf( "Could not open output file\n" );
    return 0;
}

fscanf(fp_input, "%d ", &num_vertices);
fscanf(fp_input, "%d ", &num_edges);

printf("\n num of vertices = %d, num of edges = %d ", num_vertices, num_edges); fflush(stdout);

我的集团实例文件如下所示:

12
50
<5,1>
etc.

我希望我的代码读取 12 作为顶点数和 50 作为边数,但是当我打印出它读取的内容时,这两个值都是 0。

我不知道为什么会这样,有什么想法吗?

关于我的问题的更新:

我的实际程序是一系列的缩减。问题 P1 简化为问题 P2,问题 P2 简化为问题 P3,依此类推。我有四个这样的减少,每个都用不同的功能表示。在我的主函数中,我依次调用这四个函数中的每一个。在每个函数中,我打开一个输入文件并将我的解决方案写入一个输出文件,然后该文件是下一次缩减的输入文件,依此类推。

我注意到,如果我将 main 函数限制为单个函数,那么我可以按预期从文件中读取。为此,我依次注释掉对其他函数的调用、重新编译等。但是,如果我有多个未注释的函数调用,则它不会按预期从文件中读取。这与 fscanf/fgets 的工作方式有关吗?缓冲区在下一个函数调用中使用之前是否未清除?任何想法/想法将不胜感激。

【问题讨论】:

  • fopen 返回一个指针,失败时返回NULL。虽然 0 可以“自动”转换为 NULL,但实际上与 NULL 进行比较会更好,而不是 0 此外,perror() 是报告系统函数问题的正确方法,因为它包含 errno 值, errno 消息和随附的文本字符串。程序出错退出时,不要返回0,0表示成功,建议返回stdlib.h中定义的EXIT_FAILURE
  • 在调用 fscanf() 和函数族时,一定要检查返回值(不是参数值)以确保操作成功
  • 一般情况下,不要在格式字符串中使用尾随空格。如果用户要输入输入,而不是来自文件,则永远不要在格式字符串中使用尾随空格。原因是格式字符串中的任何空白都会消耗任意数量的空白字符,包括换行符,直到输入非空白字符。因此,要让scanf() 返回,用户必须在提示输入接下来需要输入的内容之前输入其他字符。使用"%d"。但是,也就是说,这不是您的问题的直接原因。

标签: c scanf


【解决方案1】:

我知道为什么我无法按预期读取文件。我在函数结束时关闭文件时并不小心。在我的程序中,我有一系列步骤,其中一个步骤的输出文件是下一步的输入文件,依此类推。当我确保在每个步骤结束时我使用 fclose() 关闭文件时,我的程序会按预期从所有文件中读取。谢谢!

【讨论】:

    【解决方案2】:

    在您的 fscanf 调用中删除紧接在 %d 之后的尾随空格。

    fscanf(fp_input, "%d", &num_vertices);
    fscanf(fp_input, "%d", &num_edges);
    

    如果您在第一个 fscanf 中的 %d 之后放置一个空格,则第二个将不会读取数字,除非第一个的尾随空格已被消耗(通过读取空格、\n 或制表符)。

    【讨论】:

    • 谢谢mclead_ideafix,我已经试过了,它并没有改变读取的内容,读取的值仍然是0。实际上,我猜这些值根本没有被读取。
    • fscanf返回的值是多少?它应该返回读取的变量数。在这种情况下,1.
    • 另外,检查NULL 而不是0NULL 可能与 0 不同。
    • 谢谢,我检查了 fscanf 返回的内容。它两次都返回-1。这是什么意思?
    • 表示EOF枯竭或发生错误。如果您使用的是 Unix,请检查 errno 的值以查看实际错误是什么。
    【解决方案3】:

    我使用包含的文件运行了发布的代码

    12
    20
    

    使用以下功能:(仅修改为使其成为完整功能)

    #include <stdio.h>
    
    int main( void ) 
    {
        int num_edges=0;
        int num_vertices=0;
    
        char *clique_file = "cliqueinstance";
        char *mono_file= "monotone2sat";
    
        FILE* fp_input = fopen(clique_file, "r");
        FILE* fp_output = fopen(mono_file, "w");
    
        if (fp_input == 0 )
        {
            printf( "Could not open input file\n" );
            return 0;
        }
    
        if (fp_output == 0 )
        {
            printf( "Could not open output file\n" );
            return 0;
        }
    
        fscanf(fp_input, "%d ", &num_vertices);
        fscanf(fp_input, "%d ", &num_edges);
    
        printf("\n num of vertices = %d, num of edges = %d ", 
            num_vertices, 
            num_edges); 
        fflush(stdout);
        getchar();
        return(0);      
    }
    

    结果是:

    num of vertices = 12, num of edges = 20
    

    可能是输入文件实际上是二进制文件而不是文本文件

    【讨论】:

    • @MSJ:我同意这一点。 cliqueinstance 文件是 RTF 文件,或者是开头带有 BOM 的 Unicode,或者其他类似的东西,是否存在任何危险?也许您应该对cliqueinstance 文件进行十六进制转储,或者使用fgets() 读取它,然后使用sscanf() 尝试获取整数(但这意味着您可以打印您读取的内容,如果您不转换整数)。如主要 cmets 中所述,您必须检查来自fscanf() 的返回值以了解它是否成功。
    • 我编辑了我的问题并更新了我的调试结果。请看看:)
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 2017-06-14
    • 2021-05-03
    • 2014-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多