- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一些代码可以打印一些小数字(实际上是年),要求将数字打印为 Roman numerals而不是使用通常的 Hindu-Arabic numerals :
int main() {
// do something to make all integers appear in Roman numerals
std::cout << "In the year " << 2013 << " the following output was generated:\n";
// ...
}
如何将 int
格式化为罗马数字?
最佳答案
这个问题有两个独立的部分:
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;
}
每个“数字”都是通过查找相应的字符串并将其复制到迭代器来简单生成的。如果整数超出可以使用罗马数字表示的值的范围,则会抛出异常。可以生成的最长字符串是 15 个字符(3888)。
下一步是设置 std::cout
这样它就可以格式化 int
使用上述转换。当 std::ostream
需要转换任何内置数字类型(整数、 float )或类型 bool
和 void const*
, 它获得 std::num_put<cT>
来自流的 std::locale
的方面并调用 put()
在对象上,本质上是使用
std::use_facet<std::num_put<cT>>(s.getloc())
.put(std::ostreambuf_iterator<char>(s), s, s.fill(), value);
通过派生自 std::num_put<char>
并覆盖 do_put()
采用 long
的版本的成员函数作为参数,可以更改数字的格式:
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;
}
};
虽然函数比较长,但相当简单:
v
转换为罗马数字的字符串并存储在buffer
中.width()
重置为 0
)。剩下的就是创建一个 std::locale
使用此版本的 std::num_put<char>
facet 并安装生成的 std::locale
进入std::cout
:
std::cout.imbue(std::locale(std::cout.getloc(), new num_put));
std::cout << "year " << 2013 << '\n';
Here是一个活生生的例子,显示了几个不同的值和不同的对齐方式。 example还实现了 do_put()
的所有四个整数版本(即,对于 long
、long long
、unsigned long
和 unsigned long long
)。
关于c++ - 可以打印罗马数字而不是 int 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20793870/
我正在 prolog 中完成一项作业扫描数字列表并应返回该列表是否是有效的罗马数字以及数字的十进制值。例如) 1 ?- roman(N, ['I'], []). N = 1 true. 2 ?- 当我
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我正在尝试将字符串分成多个部分以读取罗马数字。例如,如果用户输入 "XI" 我希望程序能够理解我是 1,X 是 10,这样才能进行数据验证。 if(string roman == "X") int r
我是一名优秀的程序员,十分优秀!