Чтение ввода смешанных символов и целых чисел в Юникоде [дубликат]

Если вам это нужно для PHP:

Функции PHP DOM не будут работать должным образом, если не будут правильно отформатированы XML. Независимо от того, насколько лучше их использование для остальной части человечества.

simplehtmldom хорош, но я нашел его немного ошибкой, и он довольно тяжелый для памяти [Will crash на больших страницах.]

Я никогда не использовал querypath , поэтому не могу прокомментировать его полезность.

Еще один пример - мой DOMParser , который очень светлый для ресурсов, и я долгое время использовал его. Простота обучения & amp;

Для Python и Java были опубликованы похожие ссылки.

Для downvoters - я написал свой класс только тогда, когда синтаксические анализаторы XML оказались не в состоянии противостоять реальному использованию. Религиозное downvoting просто препятствует тому, чтобы полезные ответы были отправлены - держите вещи в пределах перспективы вопроса, пожалуйста.

11
задан Cœur 7 January 2017 в 18:38
поделиться

5 ответов

Вот пример, который показывает четыре разных метода, из которых работают только третий (C conio) и четвертый (собственный Windows API) (но только если stdin / stdout не перенаправлены). Обратите внимание, что вам по-прежнему нужен шрифт, содержащий символ, который вы хотите показать (Lucida Console поддерживает по крайней мере греческий и кириллический). Обратите внимание, что все здесь совершенно не переносимо, просто нет портативного способа ввода / вывода строк Unicode на терминале.

#ifndef UNICODE
#define UNICODE
#endif

#ifndef _UNICODE
#define _UNICODE
#endif

#define STRICT
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>

#include <conio.h>
#include <windows.h>

void testIostream();
void testStdio();
void testConio();
void testWindows();

int wmain() {
    testIostream();
    testStdio();
    testConio();
    testWindows();
    std::system("pause");
}

void testIostream() {
    std::wstring first, second;
    std::getline(std::wcin, first);
    if (!std::wcin.good()) return;
    std::getline(std::wcin, second);
    if (!std::wcin.good()) return;
    std::wcout << first << second << std::endl;
}

void testStdio() {
    wchar_t buffer[0x1000];
    if (!_getws_s(buffer)) return;
    const std::wstring first = buffer;
    if (!_getws_s(buffer)) return;
    const std::wstring second = buffer;
    const std::wstring result = first + second;
    _putws(result.c_str());
}

void testConio() {
    wchar_t buffer[0x1000];
    std::size_t numRead = 0;
    if (_cgetws_s(buffer, &numRead)) return;
    const std::wstring first(buffer, numRead);
    if (_cgetws_s(buffer, &numRead)) return;
    const std::wstring second(buffer, numRead);
    const std::wstring result = first + second + L'\n';
    _cputws(result.c_str());
}

void testWindows() {
    const HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
    WCHAR buffer[0x1000];
    DWORD numRead = 0;
    if (!ReadConsoleW(stdIn, buffer, sizeof buffer, &numRead, NULL)) return;
    const std::wstring first(buffer, numRead - 2);
    if (!ReadConsoleW(stdIn, buffer, sizeof buffer, &numRead, NULL)) return;
    const std::wstring second(buffer, numRead);
    const std::wstring result = first + second;
    const HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD numWritten = 0;
    WriteConsoleW(stdOut, result.c_str(), result.size(), &numWritten, NULL);
}
  • Редактировать 1: Я добавил метод, основанный на conio.
  • Редактирование 2: Я немного испортил _O_U16TEXT, как описано в блоге Майкла Каплана, но, похоже, только wgets интерпретировал (8-битные) данные из ReadFile как UTF-16. Я проведу это немного позже в выходные.
6
ответ дан Philipp 16 August 2018 в 00:43
поделиться
  • 1
    Благодарю. Также скажите, как писать в командной строке в юникоде? Я не могу! Он игнорирует и пишет в латинском языке. – Narek 12 July 2010 в 22:03
  • 2
    Также вы можете написать «main & quot; вместо «wmain», нет? – Narek 12 July 2010 в 22:11
  • 3
    Если вы хотите прочитать аргументы командной строки, объявите wmain как int wmain(int argc, wchar_t** argv) (w не является опечаткой!). – Philipp 13 July 2010 в 07:09
  • 4
    Нет, во всяком случае, я не могу писать в командной строке любое проклятое письмо с армянского или русского алфавита! – Narek 13 July 2010 в 08:29
  • 5
    Что вы пробовали? Кстати, я думаю, вам лучше задать новый вопрос, комментарии не являются хорошей заменой дискуссионному форуму. – Philipp 13 July 2010 в 09:09

В зависимости от того, какой тип unicode вы имеете в виду. Я предполагаю, что вы имеете в виду, что вы просто работаете с std::wstring. В этом случае используйте std::wcin и std::wcout.

Для преобразования кодировок вы можете использовать свои функции ОС, например, для Win32: WideCharToMultiByte, MultiByteToWideChar, или вы можете использовать библиотеку, например libiconv

8
ответ дан Brian R. Bondy 16 August 2018 в 00:43
поделиться
  • 1
    В этот момент вы можете использовать UTF-16 вместо UTF-8, если ваша ОС это понимает. – Crazy Eddie 8 July 2010 в 21:31
  • 2
    +1: wcout для wstring для wchar_t (в основном UTF-16 окна), cout для строки для char (по умолчанию Linux, UTF-8) – rubenvb 8 July 2010 в 21:49
  • 3
    wcin и wcout не работают в Windows. – Philipp 10 July 2010 в 08:40
  • 4
    @Philipp: Как wcin и wcout не работают для вас? Они не будут отображать символы Unicode, которые не поддерживаются вашим консольным шрифтом, но это ошибка консоли, а не iostreams. – Ben Voigt 10 July 2010 в 08:48
  • 5
    @Ben Voight: они вообще не отображают символы Unicode, даже если шрифт поддерживает его. См. Мой ответ для примера. Причина в том, что они не обертывают ReadConsoleW / WriteConsoleW. – Philipp 10 July 2010 в 09:00

Это зависит от ОС. Если ваша ОС понимает, вы можете просто отправить ее UTF-8.

-1
ответ дан Crazy Eddie 16 August 2018 в 00:43
поделиться
  • 1
    Он работает в Windows, который использует UTF-16, но для работы с текстом Unicode требуются специальные функции API (ReadConsole / WriteConsole). – Philipp 10 July 2010 в 08:41

Если у вас есть фактический текст (т. е. строка логических символов), тогда вместо этого вставьте в широкие потоки. Широкие потоки будут автоматически кодировать ваши символы в соответствии с битами, ожидаемыми кодировкой локали. (И если вместо этого вы кодировали биты, потоки будут декодировать биты, а затем перекодировать их в соответствии с локалью.)

Существует меньшее решение, если вы знаете, что вы кодируете UTF-биты (т. Е. , массив бит, предназначенный для декодирования в строку логических символов) AND , вы ЗНАЕТ, что целевой поток вывода ожидает тот же самый бит-формат, тогда вы можете пропустить декодирование и повторное кодирование, шаг кодирования и записывать () биты как есть. Это работает только тогда, когда вы знаете, что обе стороны используют один и тот же формат кодирования, что может иметь место для небольших утилит, которые не предназначены для связи с процессами в других локалях.

0
ответ дан John 16 August 2018 в 00:43
поделиться
  • 1
    В Windows локальная кодировка отсутствует, и, следовательно, широкие потоки не работают. – Philipp 10 July 2010 в 08:42

У меня была аналогичная проблема в прошлом, в моем случае imbue и sync_with_stdio сделали трюк. Попробуйте следующее:

#include <iostream>
#include <locale>
#include <string>

using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    wcin.imbue(locale("en_US.UTF-8"));
    wcout.imbue(locale("en_US.UTF-8"));

    wstring s;
    wstring t(L" la Polynésie française");

    wcin >> s;
    wcout << s << t << endl;
    return 0;
}
6
ответ дан Post Self 16 August 2018 в 00:43
поделиться
  • 1
    Пробовал ли этот тест? Я получаю ошибку времени выполнения! – Narek 9 July 2010 в 12:48
  • 2
    Я отлаживал, швы эта строка является проблемой: wcin.imbue (locale («en_US.UTF-8»)); – Narek 9 July 2010 в 12:50
  • 3
    @Narek Да, я проверил код. Он работает без проблем на моем Ubuntu. Какая у вас система? – Bolo 9 July 2010 в 18:54
  • 4
    Виндоус виста :( – Narek 10 July 2010 в 06:46
  • 5
    wcin и wcout не работают в Windows, как и аналогичные функции C. Работает только собственный API. – Philipp 10 July 2010 в 08:40
Другие вопросы по тегам:

Похожие вопросы: