将字符串的向量连接到std::ostream(类似于boost::Join)
Join vector of strings to std::ostream (like boost::join)
我有一个字符串向量,我想把它输出到流(实际上是文件流)。我想在矢量元素之间有一个分隔符。有一种方法可以使用标准ostream_iterator
std::vector <std::string> strs;
std::ostream_iterator<std::string> out_file_iterator ( out_file, delim );
std::copy ( strs.begin(), strs.end(), out_file_iterator );
我不喜欢这种方式,因为每个元素后面都有一个delim
文本,但我不需要在最后一个元素后面有delim
。我想用类似boost::join
的东西。然而,boost::join
返回字符串,而我的向量太大,无法将其输出到字符串。
实现我的目标最优雅的方式是什么?
对于通用解决方案(未经测试):
template<class T>
class ostream_join_iterator {
public:
// Construct like an ostream_iterator.
ostream_join_iterator(std::ostream& stream,
const std::string& delimiter = "")
: stream(stream), delimiter(delimiter), first(true) {}
// Behave like an output iterator.
ostream_join_iterator& operator++() { return *this; }
ostream_join_iterator& operator++(int) { return *this; }
ostream_join_iterator& operator*() { return *this; }
// Output a delimiter before all but the first element.
template<class T>
ostream_join_iterator& operator=(const T& value) {
if (!first) {
stream << delimiter;
} else {
first = false;
}
stream << value;
return *this;
}
private:
std::ostream& stream;
const std::string delimiter;
bool first;
};
您可以像使用常规std::ostream_iterator
:一样使用它
std::copy(strings.begin(), strings.end(),
ostream_join_iterator<std::string>(file, delimiter));
一种工作方式是分别处理最后一个。但不要认为它非常优雅。当然,您可以将丑陋封装在自己的join
函数中。
assert(strs.size() > 0);
std::ostream_iterator<std::string> out_file_iterator ( out_file, delim );
std::copy ( strs.begin(), strs.end()-1, out_file_iterator );
out_file << strs.back();
最优雅的是编写自己的循环。或者一个单独的函数。
template<class Stream, class InIt>
void print_range(Stream& s, InIt first, InIt last, char const* delim = "n"){
if(first == last)
return;
s << *first++;
for(; first != last; ++first){
s << delim << *first;
}
}
这是一个带有函子的想法
using namespace std;
struct add_delim_t {
add_delim_t(const char *_delim) : delim_(_delim), is_first_(true) {}
string operator () (const string &_val) {
if (is_first_) { is_first_ = false; return _val; } else return delim_ + _val;
}
private:
const string delim_;
bool is_first_;
};
transform(s.begin(), s.end(), ostream_iterator<string>(cout), add_delim_t(" , "));
这个解决方案的问题是它使用了有状态谓词。理论上它的意思是UB。
Boost函数输入迭代器有一个想法
using namespace std;
struct generator {
typedef string result_type;
generator(result_type _delim) : delim_(_delim), is_first_(true) {}
result_type operator () () {
if (!is_first_)
return delim_;
is_first_ = false;
return "";
}
private:
result_type delim_;
bool is_first_;
};
template<class T>
struct reverse_plus : public binary_function<T, T, T> {
T operator()(const T& _lhs, const T& _rhs) const { return (_rhs + _lhs); }
};
// output to file stream
transform
( strs.begin()
, strs.end()
, boost::make_function_input_iterator(generator(" , "), boost::infinite())
, ostream_iterator<string> out_file_iterator(out_file)
, reverse_plus<string>()
);
相关文章:
- 类似于strcat()的函数出现问题
- 如何将C++闭包与变量参数同时重用——类似于JavaScript
- 算术运算的结果类似于:C浮点变量中的1/3
- 在数组中输入 n 个整数的列表,并以类似于钟摆来回移动的方式排列它们. 输入-1 3 2 5 4,输出5 3 1 2 4
- 创建类似于布尔值的变量类型
- 如何在 Arduino 字符串的开头添加元素.类似于 JS unshift();
- Java 中是否有类似于 C++ 中引用类型"&"的内容?
- C++未知长度字符串的数组,其行为类似于 Python 字符串列表
- 如何创建类似于 QVariant 的变体类
- 对于多个字符(如 ETX/STX 对),是否有类似于 std::quote 的东西
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- C++中用于结构的纯数组的类似于TableView/DataFrame的通用功能
- 有没有类似于stoi的函数可以用于模板类
- 如何编写一个类似于kernellist_head的c++风格的双链表实现
- 序列化模式类似于boost::序列化
- 构造一个类似于JSON文件c++的字符串
- 多重继承中的派生类的行为类似于聚合
- 如何使更安全的C++变体访问者,类似于切换语句?
- C++ Python 中是否有类似于 help() 的函数
- 将字符串的向量连接到std::ostream(类似于boost::Join)