2011-08-02 69 views
6

Tôi đang tìm một phương pháp đơn giản để đọc giá trị hex từ tệp văn bản bằng cách sử dụng luồng. Tôi đã tìm kiếm Stack Overflow bằng cách sử dụng "C++ hex read stream 0x" và hầu hết các câu trả lời là viết hex dưới dạng văn bản hoặc đọc trong giá trị hex mà không có tiền tố "0x". Câu hỏi này là về việc đọc số hex, với tiền tố "0x" làm số trong một thao tác.Đọc định dạng văn bản hex 0x từ luồng

phương pháp của tôi:

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

kết thúc với byte chứa '0' (0x30) từ ký tự đầu tiên.

Chức năng 'strtol` xử lý chuyển đổi, nhưng yêu cầu phải đọc dữ liệu, chuyển đổi thành chuỗi kiểu C.

Tôi đang quá tải operator>> trong một lớp học để đọc tệp văn bản có giá trị được phân tách bằng dấu phẩy (CSV). Dưới đây là một mẫu của các tập tin dữ liệu:

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

phương pháp khai thác của tôi:

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

Tôi có cần phải sử dụng std::setw?

Chỉnh sửa 1:
Tôi đang sử dụng Visual Studio 2010 Premium trên Windows 7, nền tảng 64 bit.

+2

bạn có thể tự khắc phục sự cố khi phân tích cú pháp cvs và sử dụng trình tạo phân tích cú pháp sẵn sàng đủ linh hoạt để xử lý tất cả các trường hợp (bao gồm unicode): http://tinyurl.com/3zs2o6k –

+0

@Gene Bushuyev: Cảm ơn lời đề nghị. Tôi luôn nghĩ rằng các trình phân tích cú pháp quá tải đối với các tệp CSV đơn giản. Tôi sẽ sử dụng một trình phân tích cú pháp nếu có một ngôn ngữ liên quan, hoặc một giao thức phức tạp. Chương trình này là một phân tích nhỏ và tôi nghĩ rằng một trình phân tích cú pháp sẽ làm cho chương trình quá phức tạp. –

+0

Liên quan, hãy xem [Chuyển đổi chuỗi thập lục phân có chữ “0x” thành chữ viết tắt trong C++?] (Http://stackoverflow.com/q/1487440/608639) – jww

Trả lời

7

Một giải pháp là để đọc các giá trị sử dụng một unsigned int sau đó chuyển sang unsigned char:

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

Tôi đoán có cái gì đó về loại unsigned char đó gây ra vấn đề này.

Bất kỳ luật sư ngôn ngữ nào của C++ đều có thể trích dẫn một phần mô tả hành vi này?

+2

đó là luồng văn bản, ký tự được đọc dưới dạng ký hiệu chứ không phải giá trị; do đó '0' được đọc như một char với giá trị 0x30. –

+0

Yup, đó là kiểu dữ liệu 'int' thay vì' char' tạo nên sự khác biệt ở đây. 'showbase' không ảnh hưởng đến luồng đầu vào, mỗi thông số kỹ thuật. Tôi không chắc trình biên dịch nào sẽ hoạt động, xem chuỗi này cho một số mẫu: http://www.gamedev.net/topic/540229-simple-question-of-integer-input-c/ – HostileFork

+0

@Gene Bushuyev: Các ký tự * chưa ký * vẫn được đọc là ký hiệu (ký tự)? Tôi đến từ thế giới hệ thống nhúng và chúng tôi sử dụng 'unsigned char' làm kiểu số, không phải là ký tự. –

0

Sự cố là loại dữ liệu cho thành viên m_byte của Csv_Entry của bạn. Khi trải qua quá trình trích xuất luồng đầu vào cho dữ liệu đầu vào của bạn, nó giải thích giá trị hợp lệ là 0, sau đó giải thích x làm dấu phân tách và do đó sẽ loại bỏ phần còn lại của giá trị trong quá trình trích xuất luồng. Nếu bạn thay đổi thành viên Csv_Entry::m_byte thành unsigned int, sự cố sẽ biến mất và giải thích giá trị hex đúng cách bằng cách sử dụng std::hex.

BTW, vì tất cả các thành viên của bạn là công khai, bạn cũng có thể làm cho Csv_Entry một cấu trúc, nhưng đây là một số mẫu mã làm việc sử dụng dữ liệu nhập của bạn: http://ideone.com/H7NG1

Bạn sẽ nhận thấy ở phía đầu ra, tôi chỉ cần phải bao gồm std::hexstd::showbase để nhận giá trị hex in chính xác.

0

Thomas Matthews đúng. Bạn phải chuyển đổi từ unsigned int thành unsigned char.

Nếu bạn thuận tiện với các chức năng C scanf/printf, bạn sẽ nhận thấy rằng chúng hoạt động tương tự. Nhưng chúng mô tả hơn về tình huống này tôi nghĩ.

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

Vì vậy, quan điểm của tôi là bạn có thể đọc số nguyên thập lục phân hoặc đọc ký tự, nhưng bạn cố gắng "đọc số nguyên thập lục phân trong ký tự". Vì vậy, trường hợp cụ thể cho các nhà phát triển stdlib)

Các vấn đề liên quan