函数打印一个集合

C++ function to print a set

本文关键字:一个 集合 打印 函数      更新时间:2023-10-16

有没有人知道为什么

#include <set>
#include <string>
#include <iostream>
template <typename T>
std::string set2Str(const std::set<T> & S)
{
    std::string retstr = "{";
    typename std::set<T>::const_iterator it(S.begin()), offend(S.end());
    if (it != offend)
        retstr.push_back(*it++);
    while (it != offend)
    {
        retstr.push_back(',');
        retstr.push_back(*it++);
    }
    retstr.push_back('}');
    return retstr;
}
int main()
{
    std::set<int> mySet = {1, 5, 9, 69};
    std::cout << set2Str(mySet);
}
输出是

{,,   ,E}

? ?

还有,是否有更优雅的方式来写函数set2Str ?逗号的栅栏问题使我的程序很难看。

当你的算法这样做时:

retstr.push_back(*it++);

被打孔到目标字符串中的值被处理为(如果可能的话转换为)char。但{1, 5, 9, 69}不含char;它包含int。结果是将它们视为ASCII码点,请参阅此表,并特别注意其中每个字符的dec值。例如,注意E的值。

这是std::ostringstream的众多用途之一,它的好处是允许任何可以写入字符流的都是可表示的,包括使用自定义插入操作符。

#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <tuple>
template<typename T, typename... Args>
std::string set2str(const std::set<T,Args...>& obj)
{
    std::ostringstream oss;
    oss << '{';
    auto it = obj.cbegin();
    if (it != obj.cend())
    {
        oss << *it++;
        while (it != obj.cend())
            oss << ',' << *it++;            
    }
    oss << '}';
    return oss.str();
}
// custom class to demonstrate custom insertion support
class Point
{
    friend std::ostream& operator <<(std::ostream& os, const Point& pt)
    {
        return os << '(' << pt.x << ',' << pt.y << ')';
    }
private:
    double x,y;
public:
    Point(double x, double y) : x(x), y(y) {}
    // used by std::less<> for set ordering
    bool operator <(const Point& pt) const
    {
        return std::tie(x,y) < std::tie(pt.x,pt.y);
    }
};
int main()
{
    std::set<int> si = { 1,2,3,4,5 };
    std::set<double> sd = { 1.1, 2.2, 3.3, 4.4, 5.5 };
    std::set<char> sc = { 'a', 'b', 'c', 'd', 'e' };
    std::set<unsigned> empty;
    std::cout << set2str(si) << 'n';
    std::cout << set2str(sd) << 'n';
    std::cout << set2str(sc) << 'n';
    std::cout << set2str(empty) << 'n';
    // using custom class with implemented ostream inseter
    std::set<Point> pts { {2.2, 3.3}, {1.1, 2.2}, {5.5, 4.4}, {1.1, 3.3} };
    std::cout << set2str(pts) << 'n';
    return EXIT_SUCCESS;
}

{1,2,3,4,5}
{1.1,2.2,3.3,4.4,5.5}
{a,b,c,d,e}
{}
{(1.1,2.2),(1.1,3.3),(2.2,3.3),(5.5,4.4)}

您需要将*it++转换为字符串—例如使用std::to_string。否则,它可能是一个字符,并被打印出来。

例如,在您的情况下,您只需添加69,这是e的Ascii码。更可能的是,您想要"69",您将获得std::to_string(69)

您声明该类型为整型。这些数字被读取为ASCII码。它们没有被转换为字符串类型。

retstr.push_back (* + +);

这一行看到的是ANSI/ASCII大写字母E,而不是字符'6'和' 5'

使用你可能不喜欢的sprintf方法

将整型push_back转换为字符串是你的问题。

实际上,如果您的类型不是int类型,那么这将不起作用,因此您需要检测所使用的类型。或者更好的方法是使用stringstream并以这种方式进行转换。

#include <set>
#include <string>
#include <iostream>
template <typename T>
std::string set2Str(const std::set<T> & S)
{
  std::string retstr = "{";
  char buffer[20] = {0};
  typename std::set<T>::const_iterator it(S.begin()), offend(S.end());
  if (it != offend) {
    sprintf(buffer, "%u", *it++);
    retstr.append(buffer);
  }
  while (it != offend)
  {
    retstr.push_back(',');
    sprintf(buffer, "%u", *it++);
    retstr.append(buffer);
  }
  retstr.push_back('}');
  return retstr;
}
int main()
{
  std::set<int> mySet;  // // = {1, 5, 9, 69};  - didn't work with my compiler
  mySet.insert(1);
  mySet.insert(5);
  mySet.insert(9);
  mySet.insert(69);
  std::cout << set2Str(mySet);
}