C++:fopen/fgets 在读取 XML 文件时在随机点停止

C++: fopen/fgets stops at random point in reading XML file

我正在尝试读取 XML 文件(大小为 29.3 MB)并使用小型 C++ 程序将内容打印到控制台。问题是它在文件中很早就停止了(甚至不到 1%),我不知道为什么。代码如下:

#include <stdio.h>

int main( int argc, char ** argv ) {
const char * fn = "countries.xml";          // file name
const static int maxString = 1024;  // read buffer size

// read the file
printf("reading file\n");
char buf[maxString];
FILE * fr = fopen(fn, "r");

int i;
for(i = 0; i < 20000; i++) {
    fgets(buf, maxString, fr);
    printf(buf);
}
fclose(fr);
printf("done.\n");

return 0;
}

编辑:这个for循环实际上是用来查看我之前的循环条件是否出了问题。我的循环实际上在哪里:

char * rc;
while(( rc = fgets(buf, maxString, fr) )) {
    printf(buf);
}

但是,无论我使用哪种形式的循环以及哪种条件(我可以使 i 达到我想要的最高值),它都会在 XML 文件中的同一点停止打印到控制台。

下面的代码很容易导致未定义的行为应该 buf 包含 '%'.

printf() 将其第一个扩充视为一种格式,并且可能期望以下匹配参数与 "%s" 等一起使用。当然,像 "%S" 这样的格式错误的说明符会导致未定义行为。

// bad
while (fgets(buf, maxString, fr)) {
  printf(buf);

使用fputs().

// good
while (fgets(buf, maxString, fr)) {
  fputs(buf, stdout);

编译时,始终启用所有警告,然后修复这些警告。

gcc 至少使用:

-Wall -Wextra -pedantic

我也用:

-Wconversion -std=c99

编译器的输出显示了代码中的几个问题(所有警告)。一般来说,永远不应忽略警告。

  1. 未使用的参数:argc
  2. 未使用的参数:argv[]
  3. 在没有格式字符串文字和格式说明符的情况下调用 printf()
  4. 'static' 不在声明的开头。

然后循环方法还有很多不足之处,

  1. 固定循环次数
  2. 无法检查函数的返回值:fgets()

然后,在C 中,创建静态const 变量会占用文件内存空间space。最好#define那个值

为了便于我们人类的理解和阅读,请始终缩进代码。

  1. 每个左大括号后缩进 {
  2. 取消每个右大括号前的缩进 }

缩进时,切勿使用制表符,因为每个 wordprocessor/editor 的制表符 stops/tab 宽度设置不同。

建议对每个级别的缩进使用 4 space 秒,因为它足够宽,即使使用可变宽度字体也能看到,并为页面上的许多缩进级别留出空间。

调用many/most系统函数时,需要检查返回值以确保操作成功。

#include <stdio.h>
#include <stdlib.h> // exit(), EXIT_FAILURE

#define MAX_STRING (1024)

int main( void )
{
    const char * fn = "countries.xml";          // file name

    // read the file
    printf("reading file\n");
    char buf[ MAX_STRING ];

    FILE * fr = NULL;
    if( NULL == ( fr = fopen(fn, "r") ) )
    { // then fopen failed
        perror( "fopen for read of countries.xml failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    while( fgets( buf, sizeof buf, fr ) )
    {
        printf("%s", buf);
    }

    fclose(fr);
    printf("done.\n");

    return 0;
} // end function: main