1

я новичок в с++ и у меня проблема с обработкой строк в unicode (далее в коде будут греческие и русские символы). Требуется считать данные с клавиатуры, записать в переменную и вывести в файл в utf-8, после считать. В гугле подробностей не нашел.

Параметры проекта:

  • IDE = VS2019
  • Набор под платформу vs2015 v140
  • Проект = консольное приложение
  • в свойствах проекта = использовать Юникод
  • в свойствах консоли = текст: Lucida Console, кодировка: 65001(UTF-8)

Прикладываю отдельные части кода:

1) код обработки ввода с клавиатуры (повторяется для имени и фамилии) при дебаге в переменных 'str' 'strU' появляются кракозябры типо 0x00f436f0 L"Андрей\r\nôﺀó"

HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
const size_t MAX_NUMBERS_OF_CHARS = 128;
wchar_t* str = (wchar_t*)calloc(MAX_NUMBERS_OF_CHARS, sizeof(wchar_t)); //для введенных символов
unsigned long entered_numbers_of_chars;

static std::wstring resourceString = L"\nEnter your name >>\n"; WriteConsoleW(out, resourceString.c_str(), resourceString.size(), NULL, NULL); if (ReadConsoleW(in, str, MAX_NUMBERS_OF_CHARS, &entered_numbers_of_chars, NULL) == 0) { std::wcout << "ERROR: %ld", GetLastError(); }

// здесь удаляю '\r\n' из ввода realloc(str, (entered_numbers_of_charssizeof(wchar_t))+1); // ужимаю str в размер ввода из 128б size_t strLen = wcslen(str); // длина строки ввода = 'entered_numbers_of_chars' size_t strLenU = strLen-2; // длина строки без '\r\n' wchar_t strU = (wchar_t*)calloc(strLenU+1, sizeof(wchar_t)); //выделяю место под новую строку wcsncpy(strU, str, strLenU); // копирую введенную строку в новую без '\r\n' wdata.name = strU; // добавляю в структуру где хранятся данные (код структуры ниже)

//очищаю переменные перед следующим вводом -> фамилия memset(str, 0, (entered_numbers_of_charssizeof(wchar_t)) + 1); memset(strU, 0, (strLenUsizeof(wchar_t)) + 1);

static std::wstring loginString = L"\nEnter your surname >>\n"; WriteConsoleW(out, loginString.c_str(), loginString.size(), NULL, NULL); if (ReadConsoleW(in, str, MAX_NUMBERS_OF_CHARS, &entered_numbers_of_chars, NULL) == 0) { std::wcout << "ERROR: %ld", GetLastError(); } realloc(str, (entered_numbers_of_charssizeof(wchar_t)) + 1); strLen = wcslen(str); strLenU = strLen - 2; realloc(strU, (strLenUsizeof(wchar_t)) + 1); wcsncpy(strU, str, strLenU); wdata.surname = strU;

memset(str, 0, (entered_numbers_of_charssizeof(wchar_t)) + 1); memset(strU, 0, (strLenUsizeof(wchar_t)) + 1);

Так же, при попытке очистить переменные str и strU через free() получаю ошибку

2) код записи, отваливается на 3 строке '<<', с правильным кодом записи и чтении из файла затрудняюсь, подскажите

 std::wofstream io_file;                  //создаем поток 
 io_file.open(dirPath, std::ios::app);  // открываем файл для записи в конец
 io_file << wdata.stResource << strSep << wdata.stLogin << strSep << wdata.stCyphPassword << strSep << strSep; 

3) код структуры wdata

struct Credentials
{
    std::wstring name;
    std::wstring surname;
};
x2x
  • 65
  • Посмотрите это. – Harry Aug 27 '22 at 18:48
  • 1
    Странно, вроде как четко хотите задействовать utf-8, однако в коде нигде его использовать даже не пытаетесь. ¿Вы же в курсе, что wchar_t и большинство функций WinAPI работают в кодировке UTF-16, да? Кроме того, не стоит мешать вывод в консоль посредством WinAPI (WriteConsoleW) и средствами С++ (cout). – user7860670 Aug 27 '22 at 19:38
  • @user7860670 если есть понимание - поделитесь пожалуйста кодом? – x2x Aug 27 '22 at 19:42
  • Для того чтобы ввести текст из консоли и записать его в файл не нужна никакая специальная обработка. Все делается через обычные байтовые потоки вывода: cin >> name;, f << name;. f - типа ofstream. Utf-8 специально разработан так чтобы программы для работы с байтовыми потоками его нормально через себя пропускали. Удаление символов \n, \r также будет обработано правильно. – Stanislav Volodarskiy Aug 28 '22 at 07:22
  • @StanislavVolodarskiy Наоборот же - программы, разработанные для работы с UTF-8 могут нормально работать с однобайтовым ASCII. – user7860670 Aug 29 '22 at 07:40
  • @user7860670, это правда. Но также правда, что utf-8 - поток байтов, которые управляются теми же символами что ASCII строки. Если вы разбиваете текст на строки или слова и склеиваете их обратно, или выполняете поиски и замены, то программа написанная для ASCII нормально обработает UTF-8. Трудности начинаются с момента, когда вам надо разбивать строку на символы (а эти символы многобайтовые). – Stanislav Volodarskiy Aug 29 '22 at 13:23
  • @StanislavVolodarskiy в данном случае, обычные инструкции типа cin / ofstream / ... не работают, русские-греческие и пр. символы ими не обрабатываются, в файл записывается мешанина. – x2x Aug 31 '22 at 17:55
  • Вы ошибаетесь. Они обрабатываются нормально: если прочитали байты и эти же байты записали, что может испортиться? Покажите, конкретный пример, обсудим. – Stanislav Volodarskiy Aug 31 '22 at 18:53

0 Answers0