2011-08-02 55 views
6

Estoy buscando un método simple para leer un valor hexadecimal de un archivo de texto utilizando secuencias. Busqué Desbordamiento de pila usando "secuencia de lectura hexadecimal de C++ 0x" y la mayoría de las respuestas fueron sobre escribir hexadecimal como texto o leer en valores hexadecimales sin el prefijo "0x". Esta pregunta se trata de leer el número hexadecimal, con el prefijo "0x" como número en una operación.Lea el formato de texto hexadecimal 0x de la secuencia

Mi método:

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

termina con byte contenga '0' (0x30) desde el primer carácter.

La función 'strtol` maneja la conversión, pero requiere leer los datos, convirtiéndolos en cadenas de estilo C.

Estoy sobrecargando el operator>> en una clase para leer un archivo de texto de valores separados por comas (CSV). Este es un ejemplo del archivo de datos:

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

Mi método de extracción:

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; 
} 

¿Es necesario utilizar std::setw?

Edición 1:
Estoy usando Visual Studio 2010 Premium en Windows 7, la plataforma de 64 bits.

+2

Puede ahorrarse la molestia de analizar el archivo cvs usted mismo y usar un generador de analizador listo que sea lo suficientemente flexible como para manejar todos los casos (incluido unicode): http://tinyurl.com/3zs2o6k –

+0

@Gene Bushuyev: Gracias por la sugerencia. Siempre he pensado que los analizadores sintácticos eran excesivos para archivos CSV simples. Usaría un analizador si hubiera un lenguaje involucrado, o un protocolo complejo. Este programa es un pequeño analizador y creo que un analizador haría que el programa sea demasiado complejo. –

+0

Relacionado, vea [Conversión de cadena hexadecimal con "0x" inicial a corto firmado en C++?] (Http://stackoverflow.com/q/1487440/608639) – jww

Respuesta

7

Una solución es leer el valor con un unsigned int luego convertir a unsigned char:

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

supongo que hay algo sobre el tipo unsigned char que está causando el problema.

¿Algún abogado de C++ puede citar una sección que describa este comportamiento?

+2

es una secuencia de texto, los caracteres se leen como símbolos, no como valores; por lo tanto, '0' se lee como un carácter con valor 0x30. –

+0

Sí, es el tipo de datos 'int' en lugar de' char' que hace la diferencia aquí. 'showbase' no afecta las secuencias de entrada, por especificación. No estoy seguro de en qué compiladores funcionará, consulte este hilo para ver ejemplos: http://www.gamedev.net/topic/540229-simple-question-of-integer-input-c/ – HostileFork

+0

@Gene Bushuyev: ¿Los caracteres * unsigned * todavía se leen como símbolos (caracteres)? Soy del mundo de sistemas integrados y usamos 'unsigned char' como un tipo numérico, no como un personaje. –

0

El problema es el tipo de datos para su miembro m_byte de Csv_Entry. Al pasar por la extracción de la corriente de entrada para sus datos de entrada, interpreta el 0 como un valor válido, y luego interpreta el x como separador, y por lo tanto descarta el resto de los valores en la extracción de la secuencia. Si cambia su miembro Csv_Entry::m_byte a unsigned int, el problema desaparece e interpreta el valor hexadecimal correctamente utilizando std::hex.

Por cierto, ya que todos sus miembros son públicos, que también podría hacer Csv_Entry una estructura, pero aquí tienes lo muestra el código de trabajo utilizando los datos de entrada: http://ideone.com/H7NG1

Se dará cuenta en el lado de salida, sólo necesita incluir std::hex y std::showbase para obtener los valores hexadecimales para imprimir correctamente.

0

Thomas Matthews derecho. Debe convertir de unsigned int a unsigned char.

Si es conveniente con las funciones C scanf/printf notará que se comportan de manera similar. Pero son más descriptivos para esta situación, creo.

//%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' 

Así que mi punto es que usted puede leer un número entero hexadecimal o carácter leído, pero se trata de "leer entero hexadecimal en el carácter". Caso tan específico para los desarrolladores de stdlib)

Cuestiones relacionadas