Странное поведение в boost :: format hex

Я пытаюсь отформатировать двоичный массив: char* memblock в шестнадцатеричную строку.

Когда я использую следующее:

fprintf(out, "0x%02x,", memblock[0]);

Я получаю следующий вывод:

0x7f,

Когда я пытаюсь использовать boost::format на офстриме вот так:

std::ofstream outFile (path, std::ios::out); //also tried with binary
outFile << (boost::format("0x%02x")%memblock[0]);

Я получаю странный вывод, как это (видно в Vi): 0x0^?,

Что дает?

2

Решение

Учитывая, что персонаж за 0x7f является CTRL-?, похоже, это выводит memblock[0] как символ, а не как шестнадцатеричное значение, несмотря на вашу строку формата.

Это на самом деле имеет смысл, основываясь на том, что я прочитал в документации. Boost::format является типобезопасной библиотекой, в которой спецификаторы формата определяют, как будет выводиться переменная, но ограничено фактическим типом указанной переменной, который имеет приоритет.

документация говорится (мой жирный):

Устаревшие строки формата printf: %spec где spec это printf спецификация формата.

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

Это просто устанавливает соответствующие флаги на внутренний поток и / или параметры форматирования, но не требует, чтобы соответствующий аргумент был определенного типа. например : спецификация 2$xзначение «print аргумент № 2, который является целым числом в гекса» для printf, просто означает «аргумент печати 2 с флагами базового поля потока, установленными в шестнадцатеричный формат» для формата.

И, по-видимому, установка флага поля в hex не имеет большого смысла, когда вы печатаете charтак что игнорируется. Дополнительно из этой документации (хотя перефразируя немного):

type-char не облагать соответствующий аргумент должен иметь ограниченный набор типов, но просто устанавливает флаги которые связаны с этой спецификацией типа. type-char из p или же x означает шестнадцатеричный вывод, но просто устанавливает шестнадцатеричный флаг в потоке.

Это также более конкретно подтверждается текстом эта ссылка:

Мои коллеги и я обнаружили, однако, что когда %d дескриптор используется для печати char Переменная результат как будто %c дескриптор был использован — printf а также boost::format не дают тот же результат.

В документации Boost, связанной с вышеупомянутым, также объясняется, что заполнение нулями 0 модификатор работает на все типы, а не только целые, поэтому вы получаете второе 0 в 0x0^? ( ^? это не замужем персонаж).


Во многом это похоже на проблему попытки вывести const char * в C ++, так что вы видите указатель. Следующий код:

#include <iostream>
int main() {
const char *xyzzy = "plugh";
std::cout << xyzzy << '\n';
std::cout << (void*)xyzzy << '\n';
return 0;
}

будет производить что-то вроде:

plugh
0x4009a0

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

Решение в ваш конкретный случай может быть просто бросить char для int или какой-то другой тип, который интеллектуально обрабатывает %x спецификатор формата:

outFile << (boost::format("0x%02x") % static_cast<int>(memblock[0]));
7

Другие решения