【问题标题】:Removing a comma from a c++ output从 C++ 输出中删除逗号
【发布时间】:2019-04-17 20:20:34
【问题描述】:

我编写了这个程序,将向量中的数字从大到小排序,它工作得很好,但唯一让我烦恼的是试图从最后一个数字中删除逗号。这是我的代码

#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;

int main() {

    vector<int> vi1, vi2, vi3;
    srand(987);

    for (int i = 0; i < 10; ++i) vi1.push_back(rand() % 10);
    sort(vi1.begin(), vi1.end());

    for (int i = 0; i < 10; ++i) vi2.push_back(rand() % 10);
    sort(vi2.begin(), vi2.end())

    while(!vi1.empty() && !vi2.empty()) {
        if(vi1.back()>=vi2.back()) {
            vi3.push_back(vi1.back());
            vi1.pop_back();
        }
        else {
            vi3.push_back(vi2.back());
            vi2.pop_back();
        }
    }

    while(!vi1.empty()) {
        vi3.push_back(vi1.back());
        vi1.pop_back();
    }
    while(!vi2.empty()) {
        vi3.push_back(vi2.back());
        vi2.pop_back();
    }

    for (auto i = vi3.begin(); i != vi3.end(); ++i)
        cout << *i << ", ";
    cout << "\nBye..." << endl;
    return 0;
}

这是输出

9, 9, 9, 8, 8, 8, 6, 6, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 
Bye...

正如你所看到的,在最后一个 0 之后有一个逗号,这在语法上没有意义。如何删除那个逗号?

【问题讨论】:

  • 逗号要么在除最后一个之外的每个元素之后,要么在除第一个之外的每个元素之前。选择其中一个条件并使用它来打印或不打印逗号。
  • 试试这个,在添加逗号时使用变量作为标志来识别:int bCount = 0; ... cout &lt;&lt; (bCount++ &gt; 0 ? ", " : "") &lt;&lt; *i
  • 或者,就像有人回答的那样:cout &lt;&lt; (i == vi3.begin()? "" : ", ") &lt;&lt; *i
  • boost::algorithm::join 会为你做这件事,如果你不介意把它带进来
  • @rajkod 我对您的代码进行了格式化以提高可读性,但是您应该考虑删除许多完全不相关的代码。将其设为minimal reproducible example,专注于您要解决的问题。

标签: c++ vector iostream


【解决方案1】:

而不是删除,最简单的方法是只为除第一个以外的其他值打印逗号:

for (auto i = vi3.begin(); i != vi3.end(); ++i) {
    if(i != vi3.begin()) {
        cout << ", ";
    }
    cout << *i;
}

我经常使用这个成语来格式化,例如SQL 参数列表,或类似的,其中在最后一个元素之后不需要分隔符但对于任何其他元素。
还有其他方法可以检测第一个元素(例如,在循环开始之前使用bool 变量初始化为true,并在第一次迭代时设置为false)。
对于您的示例,似乎只检查 vi3.begin() 是最简单、最自然的方法。

这是伪代码中的通用变体:

bool isFirstOutput = true;
for_each(element in list) {
    if(not isFirstOutput) {
        print delimiter;
    }
    print element;
    isFirstOutput = false;
}

【讨论】:

  • 如果性能是一个问题,if 可以省略,除了最后一个元素之外的所有元素都可以使用该循环打印。然后最后一个可以在没有逗号的循环之外打印。
  • @SenselessCoder 我严重怀疑这会显着提高性能。
  • 它可能对非常大的元素大小产生一些影响。
  • @SenselessCoder 您的意思可能是对集合的大尺寸的影响,而不是元素本身。即使这样,我们也可以使用分支预测提示让编译器进行优化。
  • 你说得对,我在那里打错了字。编译器很可能会对此进行优化,我忘记了。我将对此进行测试,看看是否可以。
【解决方案2】:

如果beginend 至少是双向迭代器(就像你的那样), 您最初可以检查 begin != end;如果不打印,则不打印;如果是这样打印 ", "-增加begin != std::prev(end)的标点元素,和 最后打印*begin()。像这样:

ma​​in.cpp

#include <utility>

template<typename OStream, typename BiIter, typename Punct>
void punctuated(OStream && out, Punct && punct, BiIter begin, BiIter end)
{
    if (begin != end) {
        for (--end  ;begin != end; ++begin) {
            std::forward<OStream>(out) << *begin << std::forward<Punct>(punct);
        }
        std::forward<OStream>(out) << *begin;
    }
}

#include <iostream>
#include <vector>
#include <list>
#include <set>

int main()
{
    std::vector<int> v0;
    std::vector<int> v1{{1}};
    std::list<int> l{{1,2}};
    std::set<int>s{{3,4,5,6,7}};
    std::cout << "v0 [";
    punctuated(std::cout,",",v0.begin(),v0.end());
    std::cout << "]\n";
    std::cout << "v1 [";
    punctuated(std::cout,",",v1.begin(),v1.end());
    std::cout << "]\n";
    std::cout << "l [";
    punctuated(std::cout,",",l.begin(),l.end());
    std::cout << "]\n";
    std::cout << "s [";
    punctuated(std::cout,"|",s.begin(),s.end());
    std::cout << "]\n";
    return 0;
}

输出:

g++ -Wall -Wextra main.cpp && ./a.out
v0 []
v1 [1]
l [1,2]
s [3|4|5|6|7]

Live

【讨论】:

    猜你喜欢
    • 2015-08-12
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多