2009-07-16 48 views
7

Làm cách nào để buộc std :: stringstream operator >> đọc toàn bộ chuỗi thay vì dừng ở khoảng trắng đầu tiên?Làm thế nào để buộc std :: stringstream operator >> để đọc toàn bộ chuỗi?

Tôi đã có một lớp mẫu mà các cửa hàng một giá trị đọc từ một tập tin văn bản:

template <typename T> 
class ValueContainer 
{ 
protected: 
    T m_value; 

public: 
    /* ... */ 
    virtual void fromString(std::string & str) 
    { 
    std::stringstream ss; 
    ss << str; 
    ss >> m_value; 
    } 
    /* ... */ 
}; 

tôi đã cố gắng thiết lập/unset cờ dòng nhưng nó đã không giúp đỡ.

Làm rõ

Lớp là một mẫu container với chuyển đổi tự động đến/từ loại Strings T. được chỉ có một thể hiện của các mẫu, nó cũng phải hỗ trợ nhiều loại khác nữa. Đó là lý do tại sao tôi muốn ép buộc toán tử >> bắt chước hành vi của std :: getline.

+2

Tôi không rõ vấn đề là gì. Nếu bạn muốn '>>' làm việc với lớp 'T', bạn cần ghi đè' >> 'như vậy ' stringstream & operator >> (T & receiver) '. Trong hàm này, bạn có quyền truy cập vào 'stringstream' (thông qua' this') và tới 'receiver' và bạn có thể sữa ra khỏi' * this' bất cứ lượng dữ liệu nào bạn muốn. Bạn có thể giải thích rõ hơn vấn đề không? – Ari

+0

Xin lỗi, đó là 'stringstream & operator >> (stringstream & ss, T & receiver)', tất nhiên, và bạn truy cập trực tiếp 'ss'. – Ari

Trả lời

6

Như operator >> không đáp ứng yêu cầu của chúng tôi khi T = chuỗi, chúng ta có thể viết một chức năng cụ thể cho trường hợp [T = string]. Đây có thể không phải là giải pháp đúng. Nhưng, như một công việc xung quanh đã đề cập.

Vui lòng sửa tôi nếu nó không đáp ứng yêu cầu của bạn.

Tôi đã viết một mẫu mã như sau:

#include <iostream> 
#include <sstream> 
#include <string> 

using namespace std; 

template <class T> 
class Data 
{ 
    T m_value; 
    public: 
    void set(const T& val); 
    T& get(); 
}; 

template <class T> 
void Data<T>::set(const T& val) 
{ 
    stringstream ss; 
    ss << val; 
    ss >> m_value; 
} 

void Data<string>::set(const string& val) 
{ 
    m_value = val; 
} 

template <class T> 
T& Data<T>::get() 
{ 
    return m_value; 
} 

int main() 
{ 
    Data<int> d; 
    d.set(10); 
    cout << d.get() << endl; 

    Data<float> f; 
    f.set(10.33); 
    cout << f.get() << endl; 

    Data<string> s; 
    s.set(string("This is problem")); 
    cout << s.get() << endl; 
} 
+0

Tôi đã thực sự giải quyết vấn đề theo cách này, bằng cách sử dụng mẫu chuyên biệt cho chuỗi. Cảm ơn câu trả lời! –

1

Không có cách nào với toán tử >> mà tôi biết ngoại trừ viết khía cạnh của riêng bạn (toán tử >> dừng ở ký tự đầu tiên mà không gian isspace (c, getloc()) là đúng). Nhưng có một hàm getline trong < chuỗi > có hành vi mà bạn muốn.

+0

Tôi biết điều đó nhưng tôi cũng cần chuyển đổi từ chuỗi sang các giá trị khác và tôi không muốn tạo vùng chứa riêng cho chuỗi. –

+0

Như tôi đã nói, thay thế cho việc sử dụng đường dây là viết một khía cạnh. Tôi biết những gì tôi muốn sử dụng. Lưu ý rằng việc sử dụng các đặc điểm sẽ cho phép bạn đặc biệt chỉ có hành vi của fromString chứ không phải toàn bộ vùng chứa. – AProgrammer

2

Bạn muốn dừng ở đâu? Nếu bạn muốn đọc toàn bộ dòng, bạn có thể cần chức năng getline, nếu bạn cần toàn bộ chuỗi được lưu trữ trong đối tượng chuỗi luồng, lựa chọn của bạn là phương thức ostringstream::str.

+0

Tôi nghĩ ostringstream :: str() là giải pháp tốt nhất ở đây. – p00ya

1

Tôi giả sử bạn đang tạo mẫu đó với T = std::string. Trong trường hợp đó, bạn có thể sử dụng getline:

getline(ss, m_value, '\0'); 

Tuy nhiên, điều này giả định bạn sẽ không chấp nhận các ký tự nul làm phần hợp lệ của chuỗi.

Nếu không, bạn có thể viết trình trích xuất riêng cho `T '.

5

Đây là một giải pháp:

std::istream & ReadIntoString (std::istream & istr, std::string & str) 
{ 
    std::istreambuf_iterator<char> it(istr), end; 
    std::copy(it, end, std::inserter(str, str.begin())); 
    return istr; 
} 

(Nhờ các poster ban đầu trong C++ newsgroup)

+1

Nếu bài đăng gốc trực tuyến ở đâu đó, vui lòng bao gồm liên kết! – lumbric

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