"."
时结束。所以我写了一个do
-while
循环。我遇到了这样的事情:循环将始终从其主体内部结束-这正是所希望的结果。
但是,这段代码有些令人讨厌。还有什么更好的方法吗?
要注意的另一件事:我不希望将
"."
推到向量上,因此这就是为什么我添加了这个小if (temp == ".") break;
语句的原因。#1 楼
不要忘记检查流状态是否有错误或EOF。while (cin >> temp && temp != ".")
{
params.push_back(temp);
}
编辑:您不一定需要发明自己的中断条件。已经有一个文件结尾了。您可以阅读字符串,直到达到为止。这样,您的程序也可以很好地处理非交互式输入。要在终端上生成文件结尾,请在Unix / Linux上键入Ctrl + D,在Windows上键入Ctrl + Z。
while (cin >> temp)
{
params.push_back(temp);
}
#2 楼
我更喜欢:cin >> temp;
while (temp != ".")
{
params.push_back(temp);
cin >> temp;
}
#3 楼
string temp;
vector<string> params;
while (true)
{
cin >> temp;
if (temp == ".")
break;
params.push_back(temp);
}
该测试-在我的情况下为
true
,在您的情况下为temp != "."
,除非确实如此,否则它永远不会真正运行。因此也可能是true
。评论
\ $ \ begingroup \ $
这是我的建议,修改为使用for(;;)而不是{} while(true);我更喜欢Michael K的答案,因为它不会重复循环的“主体”(cin >> temp),而且速度也不慢(尽管仍然需要执行分支)。如果循环的“主体”不止一行,那么显然是代码重复。
\ $ \ endgroup \ $
– mmocny
2011年5月4日,3:14
\ $ \ begingroup \ $
我建议while(true)(不这样做)比for(;;)或while(true)更加清楚意图,即使对于经验不足的程序员也是如此。
\ $ \ endgroup \ $
– Hosam Aly
2011年5月4日,9:36
\ $ \ begingroup \ $
好的,@ Hosam Aly;我已根据您的建议进行了更新。谢谢!
\ $ \ endgroup \ $
–卡尔·曼纳斯特(Carl Manaster)
2011年5月4日13:32
#4 楼
我更喜欢建立一些基础结构,使其余的代码变得微不足道。基础架构可能需要一点额外的工作,但长期节省的费用可能是可观的。在这种情况下,它采用特殊迭代器的形式,该迭代器允许您指定将结束输入的“前哨”。它的作用类似于普通的istream_iterator
,只是在构造“范围结束”迭代器时指定了哨兵值。// sentinel_iterator.h
#pragma once
#if !defined(SENTINEL_ITERATOR_H_)
#define SENTINEL_ITERATOR_H_
#include <istream>
#include <iterator>
template <class T,
class charT=char,
class traits=std::char_traits<charT>,
class distance = ptrdiff_t>
class sentinel_iterator :
public std::iterator<std::input_iterator_tag,distance,void,void,void>
{
std::basic_istream<charT,traits> *is;
T value;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_istream<charT,traits> istream_type;
sentinel_iterator(istream_type& s)
: is(&s)
{ s >> value; }
sentinel_iterator(T const &s) : is(0), value(s) { }
const T &operator*() const { return value; }
const T *operator->() const { return &value; }
sentinel_iterator &operator++() {
(*is)>>value;
return *this;
}
sentinel_iterator &operator++(int) {
sentinel_iterator tmp = *this;
(*is)>>value;
return (tmp);
}
bool operator==(sentinel_iterator<T,charT,traits,distance> const &x) {
return value == x.value;
}
bool operator!=(sentinel_iterator<T,charT,traits,distance> const &x) {
return !(value == x.value);
}
};
#endif
有了它,就可以读取数据变得琐碎:
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include "sentinel_iterator.h"
int main() {
// As per spec, read until a "." is entered:
std::vector<std::string> strings(
sentinel_iterator<std::string>(std::cin),
sentinel_iterator<std::string>("."));
// It's not restricted to strings either. Read numbers until -1 is entered:
std::vector<int> numbers(
sentinel_iterator<int>(std::cin),
sentinel_iterator<int>(-1));
// show the strings:
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
// show the numbers:
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
return 0;
}
输入以下内容:
This is a string .
1 2 3 5 -1
它产生的输出:
This
is
a
string
1
2
3
5
它基本上适用于定义流提取器并测试相等性的任何类型(即说
x==y
将编译并产生有意义的结果)。评论
\ $ \ begingroup \ $
我喜欢这个主意(和+1)。相反,std :: istream_iterator在比较流指针而不是读取值。这具有很小的效率成本,因为构造函数和operator ++都需要一个额外的if()来查看读取是否失败,以便使流指针无效。您的sentinel_iterator不需要它。您还可以使用它从std :: cin读取直到读取失败吗?
\ $ \ endgroup \ $
–TemplateRex
2013年9月17日9:36
#5 楼
如果我们不是在谈论特定于语言的详细信息,那么我会喜欢这样的东西:// this is inspired by LINQ and C#
var params = Enumerable.Generate<string>(() => {string temp; cin >> temp; return temp; })
.TakeWhile(s => s != ".")
.ToVector();
其中Enumerable.Generate()是一些lambda,它从
cin
读取数据。通常回答“如何使用休息时间”的问题。我认为不应使用休息时间,至少在这种琐碎的情况下不应该使用。评论
\ $ \ begingroup \ $
我不喜欢这种特定语法,但是我喜欢这种方法。
\ $ \ endgroup \ $
– mmocny
2011年5月4日15:07
评论
\ $ \ begingroup \ $
几乎是一个非常好的解决方案–它只缺少{},即使对于单行主体,我也非常希望看到它。
\ $ \ endgroup \ $
–克里斯托弗·克雷齐格
2011年5月4日在12:18
\ $ \ begingroup \ $
@Christopher:这是个人风格的问题。尽管如此,我将编辑此答案以使其更加清晰。
\ $ \ endgroup \ $
– Andrey Vihrov
2011年5月4日13:17
\ $ \ begingroup \ $
是的,我没有其他意思。 (但请注意,某些版本的gcc会用-Wall标记此类“缺少括号”,这实际上应该是任何开发人员的标准设置之一。)
\ $ \ endgroup \ $
–克里斯托弗·克雷齐格
2011年5月4日14:27
\ $ \ begingroup \ $
几乎是一个非常好的解决方案-它只有那些丑陋,完全不必要的{}污染和混淆了本来不错的代码。 :-)
\ $ \ endgroup \ $
–杰里·科芬(Jerry Coffin)
2011年5月5日,2:40
\ $ \ begingroup \ $
@Christopher哪些版本的GCC对此进行了标记?我一直使用-Wall(及更多),从来没有戴上牙套,也从未见过这个警告。
\ $ \ endgroup \ $
–康拉德·鲁道夫(Konrad Rudolph)
2012年4月21日,下午1:52