2013-01-11 40 views
0

是否有可能實現一個C++函數,它給出了每std::vector<T>的字符串表示,只要T類型的元件可以被附加到輸出流等字符串表示::矢量<T>

T x; 
... 
std::cout << x << std::endl; 

字符串表示應該像

[x, y, z] 

我已經嘗試以下,但什麼都要?是什麼?

template <typename T> std::string vectorToString(std::vector<T>& vec) { 
    std::string s; 
    for (T element : vec) { 
     ? 
    } 
    return s; 
} 
+3

參見http://stackoverflow.com/questions/4850473/pretty-print-c-stl-容器 – Dan

+0

如果你有興趣自己實現這一點,你可能想了解SFINAE,追蹤decltype()和std :: enable_if :)但它是可行的,它需要上述工具以便在編譯時檢測如果T是流式的。 – bluescarni

+1

我認爲將簽名更改爲const ref會更好:vectorToString(** const ** std :: vector < T >&vec) – borisbn

回答

3

你會想要一個stringstream做格式:

std::ostringstream ss; 
ss << '[' 
bool first = true; 
for (T const & element : vec) { 
    if (!first) { 
     ss << ", "; 
    } 
    ss << element; 
    first = false; 
} 
ss << ']'; 
return ss.str(); 
+0

+1,但你可能想要通過引用來引用元素以避免不必要的複製(因爲'operator <<'不應該修改原始對象):'for(T const&element:vec)'。 –

+0

@DavidRodríguez-dribeas:確實;我從這個問題中複製了這條線,但沒有運用我的大腦。 –

0

快一點點版本

template <typename T> std::string vectorToString(const std::vector<T>& vec) { 
    if (vec.empty()) { 
     return "[]"; 
    } 
    std::ostringstream s; 
    s << "[" << vec.front(); 

    for (auto i = vec.begin() + 1, e = vec.end(); i != e; i++) 
    { 
     s << ", " << *i; 
    } 
    s << "]"; 

    return s.str(); 
} 

另一個時刻:也許將字符串特化並引用它們是正確的,因爲如果矢量中的字符串以,開頭或結尾,很難理解打印了多少個字符串。

template <> 
std::string vectorToString<std::string>(const std::vector<std::string>& vec) { 
    if (vec.empty()) { 
     return "[]"; 
    } 
    std::ostringstream s; 
    s << "[" << vec.front(); 

    for (auto i = vec.begin() + 1, e = vec.end(); i != e; i++) 
    { 
     s << ", \"" << *i << "\""; 
    } 
    s << "]"; 

    return s.str(); 
} 
+0

但是如果元素字符串包含引號會怎麼樣? CSV的生成有點複雜,應該使用現有的庫。 –

1

如果您在C++ 11的工作,你可以使用這個簡單的版本:如果你想讓它通用於其他類型的集合

#include <sstream> 
#include <algorithm> 

using namespace std; 

template<typename T> 
string format(vector<T> const& v) 
{ 
    if (v.empty()) return "[]"; 
    ostringstream ss; 
    ss << "[" << v[0]; 
    for_each(begin(v) + 1, end(v), [&ss] (T const& s) { ss << ", " << s; }); 
    ss << "]"; 
    return ss.str(); 
} 

(不只是vector)甚至爲集合的子範圍,你可以概括這樣說:

#include <sstream> 
#include <algorithm> 

using namespace std; 

template<typename It> 
string format(It b, It e) 
{ 
    if (b == e) return "[]"; 
    ostringstream ss; 
    ss << "[" << *b; 
    for_each(++b, e, [&ss] (decltype(*b)& s) { ss << ", " << s; }); 
    ss << "]"; 
    return ss.str(); 
} 

template<typename C> 
string format(C const& c) 
{ 
    return format(begin(c), end(c)); 
} 

int main() 
{ 
    vector<int> v = { 4, 5, 5, 8 }; 
    cout << format(v) << endl; 
    return 0; 
} 
0

使用算法,這通常簡化代碼(不知道在這種情況下,倒是完成的緣故):

template <typename T> 
std::string toString(std::vector<T> const & v) { 
    if (v.empty()) 
     return "[]"; 
    typename std::vector<T>::const_iterator last = std::prev(v.end()); 
    std::ostringstream st; 
    st << "[ "; 
    std::copy(v.begin(), last, std::ostream_iterator<T>(st,", ")); 
    st << *last << " ]"; 
    return st.str(); 
}