如何在 C++ 中逐行迭代 cin?
我想逐行迭代 std::cin
,将每一行作为 std::string
进行寻址。哪个更好:
string line;
while (getline(cin, line))
{
// process line
}
或
for (string line; getline(cin, line); )
{
// process line
}
?执行此操作的正常方法是什么?
I want to iterate over std::cin
, line by line, addressing each line as a std::string
. Which is better:
string line;
while (getline(cin, line))
{
// process line
}
or
for (string line; getline(cin, line); )
{
// process line
}
? What is the normal way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
自从 UncleBen 提出了他的 LineInputIterator 以来,我想我应该添加更多的替代方法。首先,一个非常简单的类,充当字符串代理:
有了这个,您仍然可以使用普通的 istream_iterator 进行读取。例如,要将文件中的所有行读入字符串向量,您可以使用以下内容:
关键点是,当您读取某些内容时,您指定一行 - 但否则,你只有字符串。
另一种可能性是使用大多数人几乎不知道其存在的标准库的一部分,更不用说有很多实际用途了。当您使用运算符>> 读取字符串时,流将返回一个字符串,直到该流的区域设置所说的空白字符为止。特别是如果您正在做大量面向行的工作,那么使用仅将换行符分类为空白的 ctype 方面创建一个区域设置会很方便:
要使用它,您需要注入您正在处理的流将使用该方面从语言环境中读取,然后正常读取字符串,然后使用运算符>>因为字符串总是读取整行。例如,如果我们想要读取行,并按排序顺序写出唯一的行,我们可以使用如下代码:
请记住,这会影响来自流的所有输入。使用这个几乎可以排除将面向行的输入与其他输入混合的情况(例如,使用
stream>>my_integer
从流中读取数字通常会失败)。Since UncleBen brought up his LineInputIterator, I thought I'd add a couple more alternative methods. First up, a really simple class that acts as a string proxy:
With this, you'd still read using a normal istream_iterator. For example, to read all the lines in a file into a vector of strings, you could use something like:
The crucial point is that when you're reading something, you specify a line -- but otherwise, you just have strings.
Another possibility uses a part of the standard library most people barely even know exists, not to mention being of much real use. When you read a string using operator>>, the stream returns a string of characters up to whatever that stream's locale says is a white space character. Especially if you're doing a lot of work that's all line-oriented, it can be convenient to create a locale with a ctype facet that only classifies new-line as white-space:
To use this, you imbue the stream you're going to read from with a locale using that facet, then just read strings normally, and operator>> for a string always reads a whole line. For example, if we wanted to read in lines, and write out unique lines in sorted order, we could use code like this:
Keep in mind that this affects all input from the stream. Using this pretty much rules out mixing line-oriented input with other input (e.g. reading a number from the stream using
stream>>my_integer
would normally fail).我所拥有的(作为练习编写,但也许有一天会变得有用)是 LineInputIterator:
因此您的循环可以用算法替换(C++ 中的另一种推荐实践):
也许一个常见的任务是将每一行存储在容器中:
What I have (written as an exercise, but perhaps turns out useful one day), is LineInputIterator:
So your loop could be replaced with an algorithm (another recommended practice in C++):
Perhaps a common task is to store every line in a container:
第一个。
两者的作用相同,但第一个更具可读性,而且您可以在循环完成后保留字符串变量(在第二个选项中,它包含在 for 循环范围内)
The first one.
Both do the same, but the first one is much more readable, plus you get to keep the string variable after the loop is done (in the 2nd option, its enclosed in the for loop scope)
使用 while 语句。
请参阅 Steve McConell 的《Code Complete 2》第 16.2 章(特别是第 374 和 375 页)。
引用:
。
我省略了中间的一些部分,但希望这能给您一个好主意。
Go with the while statement.
See Chapter 16.2 (specifically pages 374 and 375) of Code Complete 2 by Steve McConell.
To quote:
.
I've omitted some parts in the middle but hopefully that gives you a good idea.
这是基于杰里科芬的回答。我想展示 c++20 的
std::ranges::istream_view
。我还向类添加了行号。我在 godbolt 上做了这个,所以我可以看到发生了什么。此版本的 line 类仍可与 std::input_iterator 配合使用。https://en.cppreference.com/w/cpp/ranges/basic_istream_view
https://www.godbolt.org/z/94Khjz
打印出:
This is based on Jerry Coffin's answer. I wanted to show c++20's
std::ranges::istream_view
. I also added a line number to the class. I did this on godbolt, so I could see what happened. This version of the line class still works withstd::input_iterator
.https://en.cppreference.com/w/cpp/ranges/basic_istream_view
https://www.godbolt.org/z/94Khjz
prints out: