Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以打印罗马数字而不是整数吗?_C++_Locale_Iostream_Roman Numerals - Fatal编程技术网

C++ 可以打印罗马数字而不是整数吗?

C++ 可以打印罗马数字而不是整数吗?,c++,locale,iostream,roman-numerals,C++,Locale,Iostream,Roman Numerals,我有一些打印一些小数字(实际上是年)的代码,要求打印数字,而不是使用通常的: intmain(){ //做点什么使所有整数都以罗马数字出现 这个问题有两个独立的部分: 这个问题的枯燥部分是如何将int转换为一系列具有罗马表示值的字符 如何截取int的输出并将其转换为刚才描述的序列 罗马数字遵循一条相当直截了当的规则,这似乎最容易通过简单的查找表来处理。由于问题的主要焦点是如何使其与IOStreams一起工作,因此使用了一种直截了当的算法: template <typename To>

我有一些打印一些小数字(实际上是年)的代码,要求打印数字,而不是使用通常的:

intmain(){
//做点什么使所有整数都以罗马数字出现

这个问题有两个独立的部分:

  • 这个问题的枯燥部分是如何将
    int
    转换为一系列具有罗马表示值的字符
  • 如何截取
    int
    的输出并将其转换为刚才描述的序列
  • 罗马数字遵循一条相当直截了当的规则,这似乎最容易通过简单的查找表来处理。由于问题的主要焦点是如何使其与IOStreams一起工作,因此使用了一种直截了当的算法:

    template <typename To>
    To make_roman(int value, To to) {
        if (value < 1 || 3999 < value) {
            throw std::range_error("int out of range for a Roman numeral");
        }
        static std::string const digits[4][10] = {
            { "", "M", "MM", "MMM", "", "", "", "", "", "" },
            { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" },
            { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" },
            { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" },
        };
        for (int i(0), factor(1000); i != 4; ++i, factor /= 10) {
            std::string const& s(digits[i][(value / factor) % 10]);
            to = std::copy(s.begin(), s.end(), to);
        }
        return to;
    }
    
    通过从
    std::num_put
    派生并覆盖以
    long
    为参数的版本的
    do_put()
    成员函数,可以更改数字的格式:

    class num_put
        : public std::num_put<char>
    {
        iter_type do_put(iter_type to, std::ios_base& fmt, char fill, long v) const {
            char buffer[16];
            char* end(make_roman(v, buffer));
    
            std::streamsize len(end - buffer);
            std::streamsize width(std::max(fmt.width(0), len));
            std::streamsize fc(width - (end - buffer));
    
            switch (fmt.flags() & std::ios_base::adjustfield) {
            default:
            case std::ios_base::left:
                to = std::copy(buffer, end, to);
                to = std::fill_n(to, fc, fill);
                break;
            case std::ios_base::right:
            case std::ios_base::internal:
                to = std::fill_n(to, fc, fill);
                to = std::copy(buffer, end, to);
            }
            return to;
        }
    };
    

    是一个显示具有不同对齐方式的两个不同值的实例。还实现了所有四个整数版本的
    do_put()
    (即for
    long
    long
    unsigned long
    ,和
    unsigned long
    )。

    @chris我过去写过不同的方法(但最近没有)但是这一个完全是基于。你必须为
    无符号长
    重载逐字逐句地写这整件事吗?@DietmarKühl,啊,我找了一点,发现了。我敢打赌我把它和我最近看到的一些完全不同的IO流代码混在一起了。很抱歉。@0x499602D2:如果你想的话还支持其他整数类型,您可能会使用基本逻辑创建一个内部版本,检查边界,并委托给内部版本。@0x499602D2:我已更新以覆盖所有相关的
    do_put()
    的四个版本。
    std::use_facet<std::num_put<cT>>(s.getloc())
        .put(std::ostreambuf_iterator<char>(s), s, s.fill(), value);
    
    class num_put
        : public std::num_put<char>
    {
        iter_type do_put(iter_type to, std::ios_base& fmt, char fill, long v) const {
            char buffer[16];
            char* end(make_roman(v, buffer));
    
            std::streamsize len(end - buffer);
            std::streamsize width(std::max(fmt.width(0), len));
            std::streamsize fc(width - (end - buffer));
    
            switch (fmt.flags() & std::ios_base::adjustfield) {
            default:
            case std::ios_base::left:
                to = std::copy(buffer, end, to);
                to = std::fill_n(to, fc, fill);
                break;
            case std::ios_base::right:
            case std::ios_base::internal:
                to = std::fill_n(to, fc, fill);
                to = std::copy(buffer, end, to);
            }
            return to;
        }
    };
    
    std::cout.imbue(std::locale(std::cout.getloc(), new num_put));
    std::cout << "year " << 2013 << '\n';