Removing a comma from a c++ output

六眼飞鱼酱① 提交于 2019-11-26 23:37:20

问题


I wrote this program that sorts numbers in vectors from greatest to least, it works great but the only thing that is bugging me is trying to remove the comma from the last number. Heres my code

#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;
}

and here is the output

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

as you can see after the last 0 there is a comma which doesn't make sense grammatically speaking. How can I remove that comma?


回答1:


Rather than removing the simplest way is just to print commas only for other values than the first:

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

I am using this idiom regularly to format e.g. SQL parameter lists, or similar where a delimiter isn't wanted after the last element but for any others.
There are other ways to detect the first element (e.g. using a bool variable initialized to true before the loop starts, and set to false upon the first iteration).
For your example it seems just checking for vi3.begin() is the easiest and most natural way.

Here's the generic variant in pseudo code:

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



回答2:


If begin, end are at least bidirectional iterators (as yours are), you can just check initially that begin != end; if not print nothing; if so print ", "-puncuated elements incrementing begin != std::prev(end), and finally print *begin(). like so:

main.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;
}

Output:

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

Live



来源:https://stackoverflow.com/questions/55735410/removing-a-comma-from-a-c-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!