2009-03-08 36 views
111

Tôi muốn xóa và sử dụng lại một ostringstream (và bộ đệm cơ bản) để ứng dụng của tôi không phải thực hiện nhiều phân bổ. Làm cách nào để đặt lại đối tượng về trạng thái ban đầu?Làm thế nào để tái sử dụng một ostringstream?

+0

có thể trùng lặp với [In C++, làm thế nào để bạn xóa biến chuỗi?] (Http://stackoverflow.com/questions/20731/in-c-how-do-you-clear-a-stringstream -variable) – mpromonet

Trả lời

145

Tôi đã sử dụng một chuỗi các rõ ràng và str trong quá khứ:

// clear, because eof or other bits may be still set. 
s.clear(); 
s.str(""); 

nào đã làm điều cho cả đầu vào và đầu ra stringstreams. Ngoài ra, bạn có thể tự rõ ràng, sau đó tìm kiếm các chuỗi phù hợp với bắt đầu:

s.clear(); 
s.seekp(0); // for outputs: seek put ptr to start 
s.seekg(0); // for inputs: seek get ptr to start 

Điều đó sẽ ngăn ngừa một số tái phân bổ thực hiện bằng cách str bằng cách ghi đè bất cứ thứ gì trong bộ đệm đầu ra hiện nay để thay thế. Kết quả là như thế này:

std::ostringstream s; 
s << "hello"; 
s.seekp(0); 
s << "b"; 
assert(s.str() == "bello"); 

Nếu bạn muốn sử dụng các chuỗi cho c-chức năng, bạn có thể sử dụng std::ends, đặt một null chấm dứt như thế này:

std::ostringstream s; 
s << "hello"; 
s.seekp(0); 
s << "b" << std::ends; 
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1); 

std::ends là đang bị diệt vong của phản std::strstream, có thể ghi trực tiếp vào một mảng char mà bạn đã cấp phát trên ngăn xếp. Bạn phải chèn một null kết thúc bằng tay. Tuy nhiên, std::ends không được chấp nhận, tôi nghĩ vì nó vẫn hữu ích như trong các trường hợp trên.

+0

Tôi đang cố gắng sử dụng s.str() với một ostream. Kích thước là rối tung lên (tôi có thể thấy ký tự đầu tiên là null nhưng nó in nhiều hơn nữa). Có cách nào tốt để sửa chữa độ dài str? tôi đang sử dụng s.str(). c_str(); ATM và nó hoạt động độc đáo –

+0

Thực ra ngay cả điều này cũng không chính xác. Tôi chỉ làm 's.str (" ");' thay vào đó. 'auto str = s.str(); auto cstr = str.c_str(); tập tin << cstr; s.clear(); S.tìm kiếm (0); s << đầu; ' –

+0

std :: đầu không làm việc cho tôi trong google thử nghiệm 'đẩy mạnh :: bất kỳ a = 1; std :: ostringstream buffer; bộ đệm << a << std :: ends; EXPECT_EQ (buffer.str(), "bất kỳ <(int)1>"); ' 'TestUtilsTest.cpp: 27: Thất bại dự kiến: buffer.str() Đó là: "bất kỳ <(int)1> \ 0" Để được tính bằng: "bất kỳ <(int)1>" ' và nếu tôi tái sử dụng với chuỗi độ dài khác nhau tôi nhận được còn sót lại bit –

5

Dường như cuộc gọi ostr.str("") thực hiện thủ thuật.

+8

Giá trị chỉ ra rằng điều này sẽ không tái sử dụng bộ đệm cơ bản từ ostringstream - nó chỉ gán một bộ đệm mới. Vì vậy, trong khi bạn đang sử dụng lại đối tượng ostringstream, bạn vẫn phân bổ hai bộ đệm. Tôi không nghĩ rằng ostringstream được thiết kế để tái sử dụng theo cách bạn dự định. – razlebe

+2

Nó cũng không rõ ràng nhà nước, đó là những gì. Rõ ràng() không. Tôi đồng ý, nó thực sự không có nghĩa là để được sử dụng như thế này. Chỉ cần tạo một cái mới để chắc chắn. Chỉ khi bạn hồ sơ bạn sẽ tìm ra nếu nó làm cho bất kỳ sự khác biệt. –

+1

sgreeve, Brian, đúng vậy. Lưu ý, tuy nhiên, phương pháp của litb ở trên đòi hỏi phải sử dụng std :: ends như thế nào. Nó reuses bộ đệm, nhưng làm cho bạn mã khác nhau như bình thường với stringstreams (thông thường bạn không sử dụng std :: ends). –

0

Bạn không. Sử dụng hai luồng được đặt tên khác nhau để làm rõ và cho phép trình biên dịch tối ưu hóa tìm ra rằng nó có thể sử dụng lại luồng cũ.

+6

... và tất nhiên hy vọng rằng nó có, con số nó ra đó là. –

+4

xem xét trường hợp sử dụng nơi mã lặp qua dữ liệu đầu vào, ghi vào 'ostringstream' (dựa trên dữ liệu đã đọc) và sau đó phải viết chuỗi được tạo trong' ostringstream' ở đâu đó theo thời gian (ví dụ: sau một số chuỗi ký tự đã được đọc) và bắt đầu xây dựng một chuỗi mới. –

2

Nếu bạn định xóa bộ đệm theo cách sẽ làm cho bộ đệm bị xóa trước khi sử dụng lần đầu tiên, bạn sẽ cần thêm thứ gì đó vào bộ đệm đầu tiên w/MSVC.

struct Foo { 
    std::ostringstream d_str; 
    Foo() { 
     d_str << std::ends; // Add this 
    } 
    void StrFunc(const char *); 
    template<class T> 
    inline void StrIt(const T &value) { 
     d_str.clear(); 
     d_str.seekp(0); // Or else you'll get an error with this seek 
     d_str << value << std::ends; 
     StrFunc(d_str.str().c_str()); // And your string will be empty 
    } 
}; 
+0

Tôi không thấy hành vi thất bại trên VS2012. Hơn nữa, gọi ['clear'] (http://www.cplusplus.com/reference/ios/ios/clear/) sẽ _cause_' failbit' được đặt nếu luồng trống. Trong khi chỉ cần gọi ['seekp'] (http://www.cplusplus.com/reference/ostream/ostream/seekp/) chỉ cần trả lại nếu không có luồng nào tồn tại. –

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