如何打印逗号分隔的元素列表?
我知道如何用其他语言来执行此操作,而不是在C ++中进行的,我在这里被迫使用。
我有一组字符串(关键字
),我将其打印到out
作为列表中,并且字符串之间需要逗号,但不需要逗号,但不需要拖延逗号。例如,在Java中,我将使用StringBuilder
,然后在构建字符串后将逗号删除。我该如何在C ++中进行?
auto iter = keywords.begin();
for (iter; iter != keywords.end( ); iter++ )
{
out << *iter << ", ";
}
out << endl;
我最初尝试插入以下块进行操作(在此处移动逗号打印):
if (iter++ != keywords.end())
out << ", ";
iter--;
I know how to do this in other languages, but not in C++, which I am forced to use here.
I have a set of strings (keywords
) that I'm printing to out
as a list, and the strings need a comma between them, but not a trailing comma. In Java, for instance, I would use a StringBuilder
and just delete the comma off the end after I've built my string. How can I do it in C++?
auto iter = keywords.begin();
for (iter; iter != keywords.end( ); iter++ )
{
out << *iter << ", ";
}
out << endl;
I initially tried inserting the following block to do it (moving the comma printing here):
if (iter++ != keywords.end())
out << ", ";
iter--;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
我认为简单性对我来说更好,因此,在浏览所有答案之后,我准备了解决方案(需要C ++ 14):
输出示例:
I think simplicity is better for me, so after I look through all answers I prepared my solution(c++14 required):
Output example:
我建议您只需在Lambda的帮助下切换第一个角色即可。
I suggest you simply switch the first character with the help of a lambda.
尝试以下操作:
Try this:
则避免了
。
另一个可能的解决方案,如果取决于您在循环中所做的事情,
Another possible solution, which avoids an
if
Depends what you're doing in your loop.
如果值为
std :: String
S,则可以用 range-v3对于必须转换为字符串的其他类型,您只需添加一个转换调用
to_string
即可。If the values are
std::string
s you can write this nicely in a declarative style with range-v3For other types which have to be converted to string you can just add a transformation calling
to_string
.您正在使用的
++
运算符有一个小问题。您可以尝试:
这样,
++
将进行评估,然后再将迭代器与键words.end()
进行比较。There is a little problem with the
++
operator you are using.You can try:
This way,
++
will be evaluated before compare the iterator withkeywords.end()
.我使用一个小帮手课:
使用它:
I use a little helper class for that:
To use it:
以下应该这样做: -
Following should do:-
我认为 @Markb答案的这种变体达到了最佳的可读性,简单性和简洁的平衡:
I think this variant of @MarkB's answer strikes optimal balance of readability, simplicity and terseness:
解决这个问题非常容易(取自我的答案 there ):
我在许多编程语言中使用此idiom(模式?),以及各种任务,您需要在其中构建诸如输入之类的列表中构造划界输出。让我在伪代码中给出摘要:
在某些情况下,甚至可以完全省略
priventeration
指示器变量:It's very easy to fix that (taken from my answer here):
I am using this idiom (pattern?) in many programming languages, and all kind of tasks where you need to construct delimited output from list like inputs. Let me give the abstract in pseudo code:
In some cases one could even omit the
firstIteration
indicator variable completely:从C ++ 23 开始,您可以使用 <代码> std ::格式 或
std ::::::::::: print
(或std :: println
)来执行此操作。
如果您需要结果为
std :: String
使用std ::格式
。请注意,格式化范围需要C ++ 23支持,特别是 p2286r8 (检查://en.cppreference.com/w/cpp/compiler_support#c.2b.2b.2b23_library_features“ rel =“ nofollow noreferrer”> c ++ 23库特征)。如果您遇到了较旧的标准,则可以使用 fmt 库到 print ranges 。
Starting with C++23 you can use
std::format
orstd::print
(orstd::println
) to do this.If you need the result as
std::string
usestd::format
. Note that formatting ranges requires C++23 support, specifically the implementation of P2286R8 (check C++23 library features).If you are stuck to an older standard, you can use the fmt library to print ranges.
我认为这应该有效
I think this should work
使用Boost:
您可以获得一个包含向量的字符串,即逗号分隔。
编辑:
要删除最后一个逗号,请发行:
Using boost:
and you obtain a string containing the vector, comma delimited.
EDIT:
to remove the last comma, just issue:
可能是这样..
Could be like so..
这是您可以使用的两种方法,它们本质上都是相同的想法。我喜欢这些方法,因为它们不包含任何不必要的条件检查或作业操作。我将第一个打印第一个方法。
方法1:打印第一个方法
这是我首先使用的方法。它可以通过单独打印容器中的第一个元素,然后打印出逗号和空间之前的每个后续元素。这很简单,简洁,如果您需要做的一切,效果很好。一旦您想做更多的事情,例如在最后一个元素之前添加“和”,此方法就会不足。您必须检查每个循环迭代是否在最后一个元素上。不过,添加一个期间或列表之后的新线并不那么糟糕。您可以在循环之后再添加一条线,以将您想要的任何内容附加到列表中。
我更喜欢第二种方法。我称 print last方法,因为它与第一个但相反顺序的事情相同。
方法2:打印最后一个方法,
该方法是通过打印每个元素来起作用的方法,除了最后一个带有逗号和空间的元素,使您可以选择在其之前添加“和“”,一个后期和/或newline字符。如您所见,此方法为您提供了更多关于如何处理最后一个元素的选择,而不会影响循环的性能或添加很多代码。
如果您困扰您将for-loop空的第一部分留空,则可以这样写:
Here are two methods you could use, which are both essentially the same idea. I like these methods because they do not contain any unnecessary conditional checks or assignment operations. I'll call the first one the print first method.
Method 1: the print first method
This is the method I used at first. It works by printing the first element in your container by itself, and then prints every subsequent element preceded by a comma and space. It's simple, concise, and works great if that's all you need it to do. Once you want to do more things, like add an "and" before the last element, this method falls short. You'd have to check each loop iteration for if it's on the last element. Adding a period, or newline after the list wouldn't be so bad, though. You could just add one more line after the for-loop to append whatever you desire to the list.
The second method I like a lot more. That one I'll call the print last method, as it does the same thing as the first but in reverse order.
Method 2: the print last method
This one works by printing every element except for the last with a comma and space, allowing you to optionally add an "and" before it, a period after it, and/or a newline character. As you can see, this method gives you a lot more options on how you can handle that last element without affecting the performance of the loop or adding much code.
If it bothers you to leave the first part of the for-loop empty, you could write it like so:
C ++ 20带来格式化库。但是截至目前(2021年4月),海湾合作委员会和叮当尚未实施它。但是我们可以使用 fmt 其基于以下位置的库
C++20 brings the formatting library. However as of now (april 2021) neither gcc nor clang implement it yet. But we can use the fmt library on which it is based on:
我会选择这样的事情,一个简单的解决方案,应该适合所有迭代器。
I would go with something like this, an easy solution and should work for all iterators.
您可以使用
do
循环,重写第一次迭代的循环条件,并使用短路&amp;&amp;&amp;
操作员,并且有效流是<代码> true 。You can use a
do
loop, rewrite the loop condition for the first iteration, and use the short-circuit&&
operator and the fact that a valid stream istrue
.这使流操作员超载。是的,全球变量是邪恶的。
This one overloads the stream operator. Yes global variables are evil.
可以使用函子:
示例:
Can use functors:
Example:
使用infix_iterator:
用法将是:
Use an infix_iterator:
Usage would be something like:
在实验性C ++ 17即将到来的编译器中,您可以使用
std ::实验:: OSTREAM_JOINER
:使用 和 clang 3.9 svn
In an experimental C++17 ready compiler coming soon to you, you can use
std::experimental::ostream_joiner
:Live examples using GCC 6.0 SVN and Clang 3.9 SVN
因为每个人都决定在循环时使用此操作,所以我将举一个示例循环。
Because everyone has decided to do this with while loops, I'll give an example with for loops.
假设一个模糊的正常输出流,以便为其写一个空字符串确实没有任何作用:
Assuming a vaguely normal output stream, so that writing an empty string to it does indeed do nothing:
一种常见的方法是在循环之前打印第一项,而仅在其余项目上循环,在每个剩余项目之前预先打印一个逗号。
或者,您应该能够创建自己的流,该流保持线路的当前状态(在末端之前)并将逗号放在适当的位置。
编辑:
您还可以按照TED建议使用中间测试的环路,就像:
我首先提到了“打印第一项”方法,因为它使循环主体保持非常简单,但是任何方法都可以正常工作。
One common approach is to print the first item prior to the loop, and loop only over the remaining items, PRE-printing a comma before each remaining item.
Alternately you should be able to create your own stream that maintains a current state of the line (before endl) and puts commas in the appropriate place.
EDIT:
You can also use a middle-tested loop as suggested by T.E.D. It would be something like:
I mentioned the "print first item before loop" method first because it keeps the loop body really simple, but any of the approaches work fine.
有很多聪明的解决方案,太多的解决方案使代码超出了救赎的希望,而无需让编译器完成工作。
明显的解决方案是特殊案例:
这是一个死去的简单模式,它
else
块,循环主体可以包含任意语句。它可能不是绝对最有效的代码,但是单个良好预测的分支的潜在性能损失很可能会被
std :: Ostream ::操作员&lt;&lt; 。
There are lots of clever solutions, and too many that mangle the code beyond hope of salvation without letting the compiler do its job.
The obvious solution, is to special-case the first iteration:
It's a dead simple pattern which:
else
block and the loop body can contain arbitrary statements.It may not be the absolutely most efficient code, but the potential performance loss of a single well-predicted branch is very likely to be overshadowed by the massive behemoth that is
std::ostream::operator<<
.这样的东西?
Something like this?
我进行分离器的典型方法(在中,任何语言)是使用中间测试的循环。 C ++代码将是:(
注意:如果要在循环之前进行检查如果关键字为空,则需要进行检查),
最终显示的大多数其他解决方案最终都会进行整个额外的测试。您正在做I/O,所以这并不是一个大问题,但它冒犯了我的敏感性。
My typical method for doing separators (in any language) is to use a mid-tested loop. The C++ code would be:
(note: An extra
if
check is needed prior to the loop if keywords may be empty)Most of the other solutions shown end up doing an entire extra test every loop iteration. You are doing I/O, so the time taken by that isn't a huge problem, but it offends my sensibilities.
在python中,我们只是写下:
为什么不这样做:
然后只使用它:
与上面的python示例不同,其中
“”
是字符串,键>键字
一个文明的字符串,在此C ++示例中,分隔符和关键字
可以是任何流媒体In python we just write:
so why not:
and then just use it like:
Unlike in the python example above where the
" "
is a string and thekeywords
has to be an iterable of strings, here in this C++ example the separator andkeywords
can be anything streamable, e.g.为了避免将
放置在循环中,我使用此操作:
这取决于矢量类型,
int
,但是您可以用一些助手将其删除。to avoid placing an
if
inside the loop, I use this:It depends on the vector type,
int
, but you can remove it with some helper.