c++ - fgetwc EOF 循环测试失败,但 65535 OK

标签 c++ c loops testing eof

VS10 和 MCBS:

为此,我创建了一个名为 c:\eoftest 的文件,其中包含文本 “test”。下面代码中第5遍ch的值是fgetwc返回的65535,但不等于EOF,我们都知道在stdio.h中定义为(-1):

#include <stdio.h>
#include <windows.h>

int main()
{
    int ch;
    FILE *stream = NULL;
    wchar_t buf[5];
    memset (buf, '\0', sizeof(buf));
    stream = _wfopen(L"C:\\eoftest.txt", L"r");

            for (int i = 0; (i  < (sizeof(buf) - 1) && ((ch = fgetwc(stream)) != EOF) && (ch != '\0')); i++) //we are reading so last null condition mandatory
            {
            ungetwc(ch, stream);
            buf[i] = (wchar_t)(ch = fgetwc(stream));
            }
}

将条件 (sic) 替换为 (ch = fgetwc(stream)) != 65535) 在这种情况下有效,但是没有做什么来确保 EOF 测试能够成功?

最佳答案

来自 fgetc, fgetwc 的 MSDN 文档

fgetc returns the character read as an int or returns EOF to indicate an error or end of file. fgetwc returns, as a wint_t, the wide character that corresponds to the character read or returns WEOF to indicate an error or end of file.

WEOF 定义为 0xFFFF,这是您之前替换的 65535

#define WEOF ((wint_t)(0xFFFF))

所以宽字符的EOF测试应该改为

if ((ch = fgetwc(stream)) != WEOF) ...

编辑

int main()
{
    wchar_t buf[5];
    memset(buf, '\0', sizeof(buf));
    wcscpy(buf, L"1234");

    FILE *stream = _wfopen(L"C:\\eoftest.txt", L"rb");
    if (!stream)
    {
        stream = _wfopen(L"C:\\eoftest.txt", L"w+b");
        if (!stream)
        {
            printf("cannot create file\n");
            return 0;
        }

        fwrite((char*)buf, sizeof(buf[0]), wcslen(buf), stream);
        fseek(stream, 0, 0);
    }

    int len = sizeof(buf) / sizeof(buf[0]);
    for (int i = 0; i < len; i++) 
    {
        wchar_t ch = fgetwc(stream);
        if (ch == WEOF) break;
        buf[i] = ch;
    }

    wprintf(L"result = %s\n", buf);

    return 0;
}

编辑 2:这将逐行打印 unicode 文件的内容:

int main()
{
    FILE *stream = _wfopen(L"c:\\test\\test.txt", L"rb");
    if (!stream) return 0;

    int buflen = 256;
    wchar_t* buf = (wchar_t*)malloc(buflen * sizeof(wchar_t));

    if (fread(buf, 2, 1, stream))
    {
        if (buf[0] != 0xFEFF)
        {
            //BOM not detected, go back to start of file
            rewind(stream);
        }//else, skip the first 2 bytes
    }

    int i = 0, line = 0;
    wint_t ch = 0;
    while (ch != WEOF)
    {
        ch = fgetwc(stream);
        if (ch == L'\n' || ch == WEOF)
        {
            //null-terminate the buffer at i
            buf[i] = L'\0';

            //trim the '\r' at the end, if any
            if (i > 0 && buf[i - 1] == '\r') buf[i - 1] = L'\0';

            wprintf(L"%3d %s\n", ++line, buf);

            //start a new line for the next pass
            i = 0;
        }
        else
        {
            buf[i] = ch;
            i++;
            if (i == buflen)
            {
                //increase buffer:
                buflen += 256;
                buf = (wchar_t*)realloc(buf, buflen * sizeof(wchar_t));
            }
        }
    }

    free(buf);
    return 0;
}

关于c++ - fgetwc EOF 循环测试失败,但 65535 OK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34964197/

相关文章:

c++ - 在 C++ 中由 ‘Sequentially Consistent Atomics’ 语义实现时,DCL(双重检查锁定)是否线程安全?

c++ - C++中sqlite3回调函数的正确使用

c++ - 最有效和最简单的表达式评估 C++ 解决方案

java - 在 do while 循环中 while 之后没有分号,即使这样代码也没有抛出语法错误或编译时错误,为什么

c - 一遍又一遍地循环堆栈

C++检查数组中是否存在元素

c++ - 用 C++ 编写多平台实现

更改用户 ID 以分配附加功能

c++ - UTF-8、Unicode 以及机器如何解释字节?

c - 套接字无法接受客户端?