Строка в жестком коде дает результаты, отличные от строки, прочитанной с консоли при приведении к PUCHAR и печати на консоль - PullRequest
0 голосов
/ 15 мая 2018

Я только что был полностью сбит с толку.Я искал несколько часов, почему я не могу преобразовать строку в PUCHAR (без знака char *).Это странно, но по какой-то причине методы шифрования окон принимают только PUCHAR ... (почему?)

Я нашел множество решений, но сначала они, кажется, не работают.Первые 128 символов из таблицы ASCII работали нормально, но другие символы, такие как 'ù' и 'µ', были преобразованы в другие (в основном странные символы ASCII, но всегда один и тот же символ для соответствующего заданного символа).

Я только что обнаружил, что приведение работает, но только для строк, которые читаются из консоли с использованием cin ?!Закодированные строки не работают ?!Я, честно говоря, не имею ни малейшего понятия о причине такого поведения.

Вот пример:

С CIN

cout << "With cin: ";
string password;
cin >> password;
unsigned char q = (unsigned char)password[0];
PUCHAR pbPassword = new unsigned char[1];      
pbPassword[0] = q;
pbPassword[1] = NULL;                       //Null or garbage is printed
cout << pbPassword;

Это выводит:

С cin:

µ
µ

Без CIN

cout << "Without cin: ";
string password = "µ";
unsigned char q = (unsigned char)password[0];
PUCHAR pbPassword = new unsigned char[1];
pbPassword[0] = q;
pbPassword[1] = NULL;
cout << pbPassword;

Это выводит:

Without cin: ╡

Я начинающий программист, поэтому извините, если кодгрязный.

Хотя я использую тот же символ, приведение к жестко закодированной строке не работает.Даже при использовании точно такого же приведения.

Я также заметил, что я могу поместить символ в индекс 1, в то время как массив имеет длину только 1, что означает, что я обращаюсь к памяти, которую я на самом деле не должен,Как это возможно?Обычно это дает ошибку доступа к памяти некоторых типов, верно?

РЕДАКТИРОВАТЬ: Главный вопрос не в том, как привести, или почему я все еще могу поместить элементы в массив, даже если он имеет длину 1. Его почему cout даетразличные результаты для приведения из строки, прочитанной из cin и жестко закодированной строки.

Ответы [ 3 ]

0 голосов
/ 15 мая 2018

Ваши строковые литералы, вероятно, закодированы в любой кодовой странице, в которой сохранены исходные файлы. Когда вы распечатываете эти строки, они отображаются в кодовой странице вашей консоли.

Строки, считанные из консоли, будутбыть на кодовой странице консоли, поэтому будет печататься правильно при отправке обратно на консоль.

В Windows, если вы хотите читать или записывать символы не ascii для консоли, вы должны использовать std::wcin и std::wcout с std::wstring, чтобы избежать этой проблемы.Затем вы можете преобразовать std::wstring в utf-8 или одну из 1-байтовых кодовых страниц, если вам нужно.

0 голосов
/ 15 мая 2018

Для случая "Без cin" это выглядит как несоответствие кодировки.Сначала вы читаете 1 байт 0xB5 (181) (что такое password.size ()?), А затем распечатываете его на консоль со стандартной кодовой страницей 437 , где 181 - это код для ╡.

0 голосов
/ 15 мая 2018

С new unsigned char[1] вы выделяете один unsigned char.Затем вы делаете pbPassword[1] = NULL, который будет индексироваться вне границ и приведет к неопределенному поведению .

Число в распределении - это не верхний индекс, это числоэлементов, как при объявлении массива.Так что это должно быть new unsigned char[2].

И даже если вам нужно где-то передать указатель на unsigned char, я рекомендую вам все же использовать std::string.Это означает, что у вас должно быть

std::string pbPassword(1, password[0]);

Это создает строку с одним символом и инициализируется password[0].Если после этого вам понадобится PUCHAR, вы можете просто разыграть его:

reinterpret_cast<const PUCHAR>(pbPassword.c_str())
...