【问题标题】:How to print a number with a space as thousand separator?如何打印带有空格作为千​​位分隔符的数字?
【发布时间】:2010-04-15 19:29:08
【问题描述】:

我有一个带有重载运算符

#include <cstdlib>
#include <iostream>

using namespace std;

class Currency
{
    int val;
    char curr[4];

    public:
    Currency(int _val, const char * _curr)
    {
        val = _val;
        strcpy(curr, _curr);
    }

    friend ostream & operator<< (ostream & out, const Currency & c);
};

ostream & operator<< (ostream & out, const Currency & c)
{
    out << c.val<< " " << c.curr;
    return out;
}

int main(int argc, char *argv[])
{
    Currency c(2354123, "ISK");
    cout << c;
}

让我感兴趣的是,这种特殊情况最简单的解决方案。

【问题讨论】:

  • @danben:将其标记为 [homework] 将如何改变问题的任何内容或如何判断好的答案?
  • @Roger Pate:将问题标记为家庭作业让 SO 社区知道他们应该提供指导并帮助发帖者自己找到解决方案,而不是仅仅为他编写解决方案。见meta.stackexchange.com/questions/10811/…
  • @Roger Pate - 请注意,这些链接指向得分相对较低的答案。任何人都可以对任何问题添加任何答案,但鉴于 SO 政策是由社区管理的,您真的希望对投票率最高的答案给予最大的权重。另请注意,乔尔在该顶级帖子中所做的是概述了最能协调大多数意见的政策,并且大概它是最高投票的答案。
  • @danben:Joel 还说“其他观点不一定要超过这个才能产生影响......接近成功。”

标签: c++


【解决方案1】:

这可以通过构面来完成

struct myseps : numpunct<char> { 
   /* use space as separator */
   char do_thousands_sep() const { return ' '; } 

   /* digits are grouped by 3 digits each */
   string do_grouping() const { return "\3"; }
};

int main() {
  std::cout.imbue(std::locale(std::locale(), new myseps));
  std::cout << 10000; // 10 000
}

或者,您可以编写自己的循环

void printGrouped(ostream &out, int n) {
  if(n < 0) {
    out << "-";
    return printGrouped(out, -n);
  }

  if(n < 1000) {
    out << n;
  } else {
    printGrouped(out, n / 1000);
    out << " " << setw(3) << setfill('0') << (n % 1000);
  }
}

ostream & operator<< (ostream & out, const Currency & c) {
    printGrouped(out, c.val);
    out << " " << c.curr;
    return out;
}

【讨论】:

  • 虽然几乎可以肯定不希望改变 all 数字的打印方式。
  • locale("") 是实现定义的。在 OS X 10.5 上它不起作用(抛出 runtime_exceptionwhat() "locale::facet::_S_create_c_locale name not valid")。您可以将当前全局语言环境与默认构造函数一起使用。
  • @wilhelmtell 我故意使用locale(""),因为根据 TC++PL 中 stroustrup 的语言环境附录,它使用“用户的首选语言环境”并且 C++ 标准说有效参数构成“C”和“”(我怀疑“”应该使用一些环境变量?)。现在更改为默认构造函数。有人知道在 OSX 上发生了什么,它不起作用?
  • 感谢您对除法/模 1000 的清晰而漂亮的提示。这就是我想要的。
【解决方案2】:

一种可能是为此使用locales

#include <locale>
#include <string>
#include <cstddef>

class SpaceSeparator: public std::numpunct<char>
{
public:
    SpaceSeparator(std::size_t refs): std::numpunct<char>(refs) {}
protected:
    char do_thousands_sep() const { return ' '; }
    std::string do_grouping() const { return "\03"; }
};

//...    
ostream & operator<< (ostream & out, const Currency & c)
{
    SpaceSeparator facet(1); //1 - don't delete when done
    std::locale prev = out.imbue(std::locale(std::locale(), &facet));
    out << c.val<< " " << c.curr;
    out.imbue(prev);  //restore previous locale
    return out;
}

【讨论】:

  • 然而,std::moneypunct 会是一个更好的选择。
【解决方案3】:
struct Currency {
  static char const sep = ' ';
  static int const group_size = 3;

  Currency(int val, std::string unit)
  : val(val), unit(unit)
  {}

  friend std::ostream& operator<<(std::ostream& out, Currency const& v) {
    // currently ignores stream width and fill
    std::ostringstream ss;
    bool const neg = v.val < 0;
    int const val = (neg ? -v.val : v.val);
    if (neg) out << '-';
    ss << val;
    std::string const s = ss.str();
    std::string::size_type n = s.size() % v.group_size;
    if (n) out << s.substr(0, n);
    for (; n < s.size(); n += v.group_size) {
      out << sep << s.substr(n, v.group_size);
    }
    out << ' ' << v.unit;
    return out;
  }

private:
  int val;
  std::string unit;
};

如果你想用逗号等自定义每个对象,可以使 sep 和 group_size 成为非静态成员。(如果是这样,将它们设为私有并在 ctor 中初始化,可能使用默认参数值。)你也可以使用控制输出格式的特征类。

语言环境还通过 moneypunct 方面支持货币格式。

【讨论】:

    【解决方案4】:
    #include <iostream>
    
    #include <sstream>
    
    #include <cstdlib>
    
    #define GROUP_SEP ','
    
    #define GROUP_SIZE 3
    
    using namespace std;
    
    string  output_formatted_string(long long num);
    
    
    int main() { 
    
        string temp;
    
        cout << "Enter a large number:  ";
    
        getline(cin, temp);
    
        long long num = atoll(temp.c_str());
    
        string output = output_formatted_string(num);
    
    
        cout << output << endl;
    
        return 0;
    
        }
    
        string output_formatted_string(long long num)
    
        { 
    
        stringstream temp, out;
    
        temp << num;
    
        string s = temp.str();
    
    
        int n = s.size() % GROUP_SIZE;
    
        int i = 0;
    
        if(n>0 && s.size() > GROUP_SIZE)
    
          {
    
            out << s.substr(i, n) << GROUP_SEP;
    
            i += n;
    
          }
    
    
        n = s.size() / GROUP_SIZE - 1;
    
        while(n-- > 0)
             {
    
            out << s.substr(i, GROUP_SIZE) << GROUP_SEP;
    
            i += GROUP_SIZE;         
    }
    
        out << s.substr(i);
    
        return out.str();
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-13
      • 2010-12-21
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 2012-11-25
      相关资源
      最近更新 更多