fgetwc EOF loop test fails, but 65535 OK

人盡茶涼 提交于 2019-12-25 08:56:57

问题


VS10 & MCBS:

For this I have created a file called c:\eoftest containing the text "test". The value of ch on the 5th pass in the following code is 65535 returned by fgetwc, but it does not equate to EOF, which we all know is defined in stdio.h as (-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));
            }
}

Replacing the condition (sic) with (ch = fgetwc(stream)) != 65535) works in this case, but what is not done to ensure the EOF test can succeed?


回答1:


From MSDN documentation for fgetc, fgetwc

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 is defined as 0xFFFF which is what you substituted earlier 65535

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

So the EOF test for wide char should be changed to

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

Edit

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;
}

Edit 2: This will print content of unicode file line by line:

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;
}


来源:https://stackoverflow.com/questions/34964197/fgetwc-eof-loop-test-fails-but-65535-ok

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!