Я хочу найти причину, по которой с новой функцией setlocale(LC_ALL, ".utf8")
стандартная функция fgetwc()
не может прочитать '\u2013'
(EN DASH) из текстового файла utf8 и вместо этого возвращает WEOF
. Может быть, найти обходной путь.
Я отключил «Только мой код» и включил загрузку символа для C:\WINDOWS\SysWOW64\ucrtbased.dll
, который содержит fgetwc
Однако, когда я пытаюсь войти в эту функцию, она не может найти fgetwc.cpp
.
Эти два места не содержат этот файл, и я не могу найти другое место:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\crt\src\
Это моя тестовая программа:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <stdlib.h>
int main()
{
wint_t wc; // = L'\u2013';
FILE* file;
printf("%s\n", setlocale(LC_ALL, ".utf8"));
file = fopen("test.txt", "r");
wc = fgetwc(file);
// ffff '?' 0 0
fprintf(stdout, "%04x '%lc' %d %d\n", wc, wc, ferror(file), feof(file));
return 0;
}
Он печатает ffff
вместо 2013
. ferror()
и feof()
возвращают false.
тест.txt:
–
Он закодирован как E2 80 93
@dxiv это сработало. Спасибо
Что касается второй части, посмотрите, имеет ли значение манифест здесь.
@dxiv вы знаете, как добавить папку debug source files
глобально, чтобы она была в других проектах?
Список каталогов исходных файлов отладки устанавливается и сохраняется для каждого решения (предположительно, в подкаталоге .vs
, как указано здесь). Не знаю навскидку, откуда берутся глобальные дефолты.
Для чтения файла UTF-8 при желании отбросьте вызов setlocale
и замените строку fopen
на:
file = fopen("test.txt", "r, ccs=utf-8");
В документации fopen говорится:
ccs=encoding -- Указывает набор закодированных символов для использования (один из UTF-8, UTF-16LE или UNICODE) для этого файла. Оставьте неуказанным, если вы хотите использовать кодировку ANSI.
Похоже, это означает, что кодировка ccs=UTF-8
должна быть указана явно, чтобы прочитать файл как текст UTF-8.
Хотя, с другой стороны, «ANSI» раньше означал либо активную кодовую страницу, либо локаль системы по умолчанию. Учитывая недавнюю поддержку UTF-8 в качестве активной кодовой страницы в Windows 10 1903 и более поздних версиях, можно было бы ожидать, что «кодировка ANSI» будет такой же, как «кодировка UTF-8», когда текущим языковым стандартом является UTF-8. Однако, похоже, это не относится к текущей реализации UCRT.
Для написания широкого символа #include <io.h>
и <fcntl.h>
замените строку fprintf
на:
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"%04x '%wc' %d %d\n", wc, wc, ferror(file), feof(file));
В документации printf говорится:
wprintf — это расширенная версия printf; формат представляет собой строку расширенных символов. wprintf и printf ведут себя одинаково, если поток открыт в режиме ANSI. printf в настоящее время не поддерживает вывод в поток UNICODE.
Попробуйте
C:\Program Files (x86)\Windows Kits\10\Source\10.0.<build>\ucrt\stdio
.