假设我想从控制台读取行并将它们放入容器中,直到用户输入空行。不过,我不希望那个空白行在我的容器中结束。我可以想到五种不同的解决方案:
a)从循环中断
std::vector<std::string> container;
for (; ;)
{
std::string line = get_input();
if (line.empty()) break;
container.push_back(line);
}
b)在循环和内循环之前读取
std::vector<std::string> container;
std::string line = get_input();
while (!line.empty())
{
container.push_back(line);
line = get_input();
}
c)作为循环条件的一部分读取,赋值版本
std::vector<std::string> container;
std::string line;
while (!(line = get_input()).empty())
{
container.push_back(line);
}
d)作为循环条件的一部分读取,序列版本
std::vector<std::string> container;
std::string line;
while (line = get_input(), !line.empty())
{
container.push_back(line);
}
e)读取太多,在循环后删除它
std::vector<std::string> container;
std::string line;
do
{
line = get_input();
container.push_back(line);
}
while (!line.empty());
container.pop_back();
那么,您更喜欢哪种解决方案?为什么?哪个对于初学者来说最容易理解?
答案 0 :(得分:2)
我更喜欢(a)。简单而且阅读很自然。
(b)重复获得输入的行。
(c)和(d)都使用可能使初学者感到困惑的语法(具体来说,逗号不在for
语句或定义中,并且在条件内分配)。我可能更喜欢(c)而不是(d)。
(e)......效率低下。如果最后push_back
导致重新分配怎么办?
答案 1 :(得分:2)
我实际上使用方法“d”:
- 在我看来最好的做法是:首先读取数据,然后如果不是“好”数据(空行)停止读取数据。一切都在预期的位置(检查数据是在循环条件部分,处理循环体中的数据。
Mtheod“a”隐藏了条件检查&amp; (以我的拙见)更难以看到“停止”循环的条件。
答案 2 :(得分:0)
正如你可能对我的期望,我建议代理:
class non_blank {
std::string data;
friend operator>>(std::istream &is, non_blank &n) {
std::string temp;
std::getline(is, temp);
// I'm not writing this from home, so I'm going from memory.
// The following line is probably a little wrong.
is.setbit(std::ios::fail, temp.length()!=0);
return is;
}
operator std::string() { return data; }
};
non_blank line;
while (infile >> line)
container.push_back(line);
这有一个可能出乎意料的副作用:因为它希望读取非空白行,它认为空行是转换失败 - 这意味着之后从流中读取更多内容,你必须清除流的失败位。由于它通过设置流的失败位而起作用,因此您还应该能够使用std::copy
来读取输入,并且它将在转换失败时停止。
答案 3 :(得分:0)
对(d)的修改使其更有效率并遵循您想要做得更好的事情。
std::vector<std::string> container;
std::string line;
do
{
line = get_input();
if (!line.empty())
{
container.push_back(line);
}
else
{
break;
}
}
while (true);