2013-01-11 50 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(); 
}