шестнадцатеричная строка в символ без знака []

#c #type-conversion

#c #преобразование типа

Вопрос:

сегодня я попытался преобразовать шестнадцатеричную строку в символ без знака []

 string test = "fe5f0c";
unsigned char* uchar= (unsigned char *)test.c_str();
cout << uchar << endl;
  

Это привело к выводу

 fe5f0c
  

hrmpf :-(. Желаемое поведение было бы следующим:

 unsigned char caTest[2]; 
caTest[0] = (unsigned char)0xfe;
caTest[1] = (unsigned char)0x5f;
caTest[2] = (unsigned char)0x0c;
cout << caTest << endl;
  

который печатает нечитаемый ascii-код. Как часто я делаю что-то не так ^^. Был бы признателен за любые предложения.

Заранее спасибо

Комментарии:

1. Ваш массив слишком мал, вы не можете назначить элементу 2 массив размером 2.

2. Кроме того, какой результат вы ожидаете при печати массива символов? Вы получите символы с кодами ASCII (или любой другой системы, используемой вашим компьютером) 254, 95, 12 и так далее. Какой результат вы на самом деле хотите? Это не ясно из вашего вопроса.

3. Я думаю, вы имели в виду, unsigned char caTest[4]; и забыли caTest[3] = 0; , но все еще не ясно, чего вы хотите. Похоже , что вы хотите отправить ASCII-представления значений шестнадцатеричной пары в стандартный вывод, независимо от того, доступны ли они для печати.

4. Хм, изначально я имел в виду caTest[3]; но если бы вы могли указать, зачем мне нужен caTest [3] = 0, я также был бы доволен caTest [4]. Что касается моего намерения, я попытался сделать то, что Пабло описал в своем ответе. Спасибо, что помогли мне.

5. @ftiaronsem: Вы обрабатываете caTest как строку. Строки заканчиваются нулем. Если вы этого не сделаете, то в конечном итоге вы будете читать дальше конца буфера.

Ответ №1:

Конечно, вам просто нужно изолировать интересующие вас биты после синтаксического анализа:

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

typedef unsigned char byte;

int main()
{
    std::string test = "40414243";
    unsigned long x = strtoul(test.c_str(), 0, 16);
    byte a[] = {byte(x >> 24), byte(x >> 16), byte(x >> 8), byte(x), 0};
    std::cout << a << std::endl;
}
  

Обратите внимание, что я изменил входную строку на восьмизначное число, поскольку в противном случае массив начинался бы со значения 0 и operator<< интерпретировал бы это как конец, и вы бы ничего не смогли увидеть.

Комментарии:

1. Большое вам спасибо за ваш ответ, к сожалению, это не то, что я хотел сделать, мой план состоял в том, чтобы сделать то, что Пабло описал в своем посте. У вас есть какие-нибудь предложения о том, как я мог бы это реализовать. Я был бы очень признателен за вашу помощь.

2. @fti: Я обновил свой пост. Дает ли это ожидаемые результаты?

3. вау, это здорово, идеально. Поскольку строка довольно длинная, мне придется разделить ее и запустить цикл for над кодом, который вы мне дали. Но я могу с этим справиться (по крайней мере, я на это надеюсь ;-)). Спасибо за вашу помощь.

4. @fti: В таком случае, вероятно, проще обрабатывать только один байт за раз внутри цикла for.

Ответ №2:

"fe5f0c" представляет собой строку из 6 байт (7 из которых содержат нулевой ограничитель). Если бы вы посмотрели на это как на массив, вы бы увидели:

 char str[] = { 102, 101, 53, 102, 48, 99 };
  

Но вы хотите

 unsigned char str[] = { 0xfe, 0x5f, 0x0c };
  

Первое является «удобочитаемым» представлением, тогда как второе — «машиночитаемыми» числами. Если вы хотите преобразовать между ними, вам нужно сделать это явно, используя код, аналогичный тому, что написал @Fred.

Приведение (в большинстве случаев) не подразумевает преобразования, вы просто говорите компилятору доверять вам и что он может забыть то, что, по его мнению, он знает о выражении, которое вы приводите.

Комментарии:

1. спасибо, это именно то, что я хочу. У вас есть какие-нибудь подсказки по коду, как должно выглядеть это преобразование? Это было бы действительно здорово.

Ответ №3:

Вот более простой способ для шестнадцатеричных строковых литералов:

 unsigned char *uchar = "xfex5fx0c";