问题
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 anint
or returnsEOF
to indicate an error or end of file.fgetwc
returns, as awint_t
, the wide character that corresponds to the character read or returnsWEOF
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