Читать шестнадцатеричный текстовый формат 0x из потока - PullRequest
7 голосов
/ 02 августа 2011

Я ищу простой метод для чтения шестнадцатеричного значения из текстового файла с использованием потоков. Я искал переполнение стека, используя «C ++ hex read stream 0x», и большинство ответов касалось записи hex в виде текста или чтения в шестнадцатеричных значениях без префикса «0x». Этот вопрос касается чтения шестнадцатеричного числа с префиксом «0x» в качестве числа в одной операции.

Мой метод:

unsigned char byte;
std::istringstream sample("0xce");
sample >> std::hex >> byte;

Заканчивается byte, содержащим '0' (0x30) от первого символа.

Функция 'strtol` обрабатывает преобразование, но требует чтения данных, преобразования в строку в стиле C.

Я перегружаю operator>> в классе, чтобы прочитать текстовый файл с разделителями-запятыми (CSV). Вот пример файла данных:

1,-4.93994892,0xa5,8,115.313e+3,
2,-4.93986238,0xc0,8,114.711e+3,
3,-4.93977554,0xc2,8,114.677e+3,

Мой метод извлечения:

class Csv_Entry
{
public:
    friend std::istream& operator >>(std::istream& inp, Csv_Entry& ce);
    unsigned int    m_index;
    double      m_time;
    unsigned char   m_byte;
    unsigned int    m_data_length;
    double      m_bit_rate;
};

std::istream&
operator >> (std::istream& inp, Csv_Entry& ce)
{
    char    separator;
    inp >> ce.m_index;
    inp >> separator;
    inp >> ce.m_time;
    inp >> separator;
    inp >> std::hex >> ce.m_byte;
    inp >> separator;
    inp >> ce.m_data_length;
    inp >> separator;
    inp >> ce.m_bit_rate;
    inp.ignore(10000, '\n');
    return inp;
}

Нужно ли использовать std::setw?

Редактировать 1:
Я использую Visual Studio 2010 Premium на Windows 7, 64-битная платформа.

Ответы [ 3 ]

7 голосов
/ 02 августа 2011

Решение состоит в том, чтобы прочитать значение, используя unsigned int, а затем преобразовать в unsigned char:

unsigned int value;
inp >> hex >> value;
unsigned char byte;
byte = value & 0xFF;

Я думаю, что-то типа unsigned char вызывает проблему.

Любые юристы по языку C ++ могут цитировать раздел, описывающий это поведение?

0 голосов
/ 03 августа 2011

Томас Мэтьюз верно.Вы должны конвертировать из unsigned int в unsigned char.

Если вам удобны функции C * scanf/printf, вы заметите, что они ведут себя аналогично.Но я думаю, что они более описательны для этих ситуаций.

//%X specifies that we trying read integer in format 0x123FFF
//%c specifies that we trying read character
//0xABC is input string

unsigned char hex;
sscanf("0xABC", "%X", &hex); // error because not enough memory allocated
                             // by address &hex to store integer

unsigned char hex;
sscanf("0xABC", "%c", &hex); // reads only one character '0'

Поэтому я хочу сказать, что вы можете либо прочитать шестнадцатеричное целое число, либо прочитать символ, но вы пытаетесь «прочитать шестнадцатеричное целое число в символе».Так что конкретный случай для разработчиков stdlib)

0 голосов
/ 02 августа 2011

Проблема в типе данных для вашего m_byte члена Csv_Entry.Проходя извлечение входного потока для ваших входных данных, оно интерпретирует 0 как допустимое значение, затем интерпретирует x как разделитель и, следовательно, отбрасывает остальные значения в извлечении потока.Если вы поменяете члена Csv_Entry::m_byte на unsigned int, проблема исчезнет, ​​и он правильно интерпретирует шестнадцатеричное значение, используя std::hex.

Кстати, так как все ваши участники общедоступны, вы можетехорошо сделайте Csv_Entry структуру, но вот пример рабочего кода, использующего ваши входные данные: http://ideone.com/H7NG1

Вы заметите на выходной стороне, мне нужно только включить std::hex и std::showbaseчтобы получить шестнадцатеричные значения для правильной печати. ​​

...