2009-01-13 34 views
44

Nói chung, cách tốt nhất để lưu trữ dữ liệu nhị phân trong C++ là gì? Các tùy chọn, như xa như tôi có thể nói, khá nhiều đun sôi xuống để sử dụng dây hoặc vector <char> s. (Tôi sẽ bỏ qua khả năng của char * s và malloc() s vì tôi đang đề cập cụ thể đến C++).Cách "thích hợp" để lưu trữ dữ liệu nhị phân bằng C++/STL

Thông thường tôi chỉ sử dụng một chuỗi, tuy nhiên tôi không chắc liệu có chi phí vượt quá hay không, hoặc chuyển đổi mà STL thực hiện trong nội bộ có thể gây rối loạn dữ liệu nhị phân. Có ai có bất kỳ con trỏ (har) về điều này? Đề xuất hoặc sở thích theo cách này hay cách khác?

Trả lời

38

vectơ của char rất đẹp vì bộ nhớ là tiếp giáp. Vì vậy, bạn có thể sử dụng nó với rất nhiều API của C như các ổ cắm berkley hoặc các API tệp. Bạn có thể làm như sau, ví dụ:

std::vector<char> vect; 
    ... 
    send(sock, &vect[0], vect.size()); 

và nó sẽ hoạt động tốt.

Về cơ bản, bạn có thể xử lý nó giống như bất kỳ bộ đệm char được cấp động nào khác. Bạn có thể quét lên và xuống tìm kiếm số ma thuật hoặc patters. Bạn có thể phân tích cú pháp một phần tại chỗ. Để nhận được từ một ổ cắm, bạn có thể dễ dàng thay đổi kích thước để gắn thêm dữ liệu.

Nhược điểm là thay đổi kích thước không hiệu quả khủng khiếp (thay đổi kích thước hoặc preallocate thận trọng) và xóa từ phía trước của mảng cũng sẽ rất không hiệu quả. Nếu bạn cần, nói, pop chỉ một hoặc hai ký tự tại một thời điểm ra phía trước của cấu trúc dữ liệu rất thường xuyên, sao chép vào một deque trước khi xử lý này có thể là một lựa chọn. Chi phí này cho bạn một bản sao và bộ nhớ deque không phải là tiếp giáp, vì vậy bạn không thể chỉ cần vượt qua một con trỏ đến một API C.

Tóm lại, tìm hiểu về cấu trúc dữ liệu và sự cân bằng của chúng trước khi lặn, tuy nhiên vector của char thường là những gì tôi thấy được sử dụng trong thực tiễn chung.

+2

câu trả lời hay. cho phần học tập: tôi tìm thấy một hình ảnh đẹp cho thấy việc sử dụng các thùng chứa một số thời gian trước đây, và nhúng nó vào câu trả lời này: http://stackoverflow.com/questions/366432/extending-stdlist#366710 –

6

Tôi cũng sử dụng std::string cho điều này và chưa bao giờ gặp sự cố với điều này.

Một "con trỏ", mà tôi vừa nhận được lời nhắc rõ ràng trong một đoạn mã ngày hôm qua: khi tạo chuỗi từ một khối dữ liệu nhị phân, hãy sử dụng biểu mẫu nhà xây dựng std::string(startIter, endIter), chứ không phải dạng std::string(ptr, offset, length) giả định rằng con trỏ trỏ đến một chuỗi kiểu C và bỏ qua bất kỳ điều gì sau ký tự số 0 đầu tiên (nó sao chép "tối đa" số length được chỉ định, không phải là length ký tự).

+0

Hmmm. Theo http://www.cplusplus.com/reference/string/string/string.html, std :: string (char * ptr, offset, length) ctor nên sao chép * tất cả * chiều dài byte, thậm chí bao gồm cả số byte không. Nó là std :: string (chuỗi const &, offset, length) ctor sao chép * lên đến * chiều dài byte. –

+0

Điều này nhắc tôi tra cứu nó một lần nữa, và có vẻ như đó là * không * std :: string (char * ptr, offset, length) constructor. Hàm khởi tạo có độ lệch và độ dài yêu cầu một chuỗi std :: là tham số đầu tiên, do đó, nó được tự động xây dựng một chuỗi từ các byte, đó là những gì cắt ngắn nó. –

+0

Bạn nói đúng. Tôi xin lỗi, tôi có nghĩa là std :: string (char * ptr, size_t chiều dài) ctor nên sao chép tất cả các byte. –

3

Bạn chắc chắn nên sử dụng một số thùng chứa char, nhưng vùng chứa bạn muốn sử dụng tùy thuộc vào ứng dụng của bạn.

Ký tự có một số thuộc tính giúp chúng giữ dữ liệu nhị phân: tiêu chuẩn không cho phép bất kỳ "đệm" nào cho kiểu dữ liệu char, điều quan trọng vì nó có nghĩa là bạn sẽ không nhận được rác trong bố cục nhị phân. Mỗi char cũng được bảo đảm là chính xác một byte, làm cho nó là kiểu dữ liệu đơn thuần cũ (POD) với chiều rộng thiết lập (tất cả các byte khác được xác định theo các giới hạn trên và/hoặc dưới).

Thảo luận về vùng chứa stl thích hợp để lưu trữ các ký tự được xử lý bởi Doug ở trên. Mà một trong những bạn cần phụ thuộc hoàn toàn vào trường hợp sử dụng của bạn. Nếu bạn chỉ đang nắm giữ một khối dữ liệu mà bạn lặp qua, mà không cần tìm kiếm đặc biệt, nối thêm/loại bỏ hoặc ghép nối, tôi thích vector, làm cho ý định của bạn rõ ràng hơn std :: string, mà nhiều thư viện và chức năng sẽ giả định giữ một chuỗi kiểu c-null bị chấm dứt.

8

Vấn đề lớn nhất với std :: string là tiêu chuẩn hiện tại không đảm bảo rằng lưu trữ cơ bản của nó là tiếp giáp.Tuy nhiên, không có sự triển khai STL đã biết nào mà chuỗi không tiếp giáp, vì vậy trong thực tế nó có thể sẽ không thất bại. Trong thực tế, chuẩn C++ 0x mới sẽ khắc phục vấn đề này, bằng cách bắt buộc std :: string sử dụng một bộ đệm liền kề, chẳng hạn như std :: vector.

Đối số khác chống lại chuỗi là tên của nó cho thấy rằng nó chứa chuỗi ký tự, không phải là bộ đệm nhị phân, điều này có thể gây nhầm lẫn cho những người đọc mã.

Điều đó nói rằng, tôi cũng đề xuất véc tơ.

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