OOP 罗马数字之加法(输入输出重载+类型转换)

【id:287】【10分】G. OOP 罗马数字之加法(输入输出重载+类型转换)
时间限制
1s
内存限制
128MB
题目描述

罗马数字比阿拉伯数字早 2000 多年,起源于古罗马。它的产生标志着一种古代文明的进步。只是没有数字0。
其采用七个罗马字母作基本数字,即:I(1), V(5), X(10), L(50), C(100), D(500), M(1000)
记数的方法:
1. 相同的数字连写,所表示的数等于这些数字相加得到的数。如:III=3
2. 小数字在大数字的右边('大''小'),所表示的数等于这些数字相加得到的数。如:VIII=8
3. 小数字(仅限I,X和C)在大数字的左边('小''大'),所表示的数等于大数减小数得到的数。如:IX=9, CD=400
4. 在一个数的上面画一条横线,表示这个数增值1000倍。
组数规则: 
I,X,C,M 连写或放在大数左边不能超过3个:LIIII是非法的,应表示为 LIV (54)
I,X,C 放在大数左边只能用1个:CCM是非法的,应表示为 MCCC (800)
V,L,D 放在大数的右边只能用1个:CLL是非法的,应直接表示为 CC (200)
V,L,D 不能放在大数的左边:DM是非法的,应直接表示为 D (500)
此外,表示2900,不能写成CMMM,而应写成MMCM (因为CM(90)比M(100)小) 
表示900,不能写成DCD,而应写成CM (相比DCD,CM更简洁易算)
为避免打印横线,输入数据及运算结果范围保证为 [1,3999]
部分数字有两种写法,比如: 490(CDXC or XD)  3999(MMMCMXCIX or MMMIM) 等
本题采用较长的写法,即 CDXC(400+90) 等写法,而不是 XD(490) 写法 
整数[1,3999]转罗马数字方法如下:
using value_t = unsigned short;
/// 表1: 490 = CDXC (本题使用该表)
static const pair<value_t, string> valueSymbols[] = {
	{1000, "M"}, {900, "CM"},
	{ 500, "D"}, {400, "CD"},
	{ 100, "C"}, { 90, "XC"},
	{  50, "L"}, { 40, "XL"},
	{  10, "X"}, {  9, "IX"},
	{   5, "V"}, {  4, "IV"},
	{   1, "I"}
};
/// 表2: 490 = XD 
//static const pair<value_t, string> valueSymbols[] = {
//	{1000, "M"}, {999, "IM"}, {990, "XM"}, {900, "CM"},
//	{ 500, "D"}, {499, "ID"}, {490, "XD"}, {400, "CD"},
//	{ 100, "C"}, { 99, "IC"}, { 90, "XC"},
//	{  50, "L"}, { 49, "IL"}, { 40, "XL"},
//	{  10, "X"}, {  9, "IX"},
//	{   5, "V"}, {  4, "IV"},
//	{   1, "I"}
//};
/// 贪心, 处理罗马数字[1, 3999]
static string int2Roman(value_t num) {
	string roman;
	// for (const auto& [value, symbol] : valueSymbols) { // 8.1以上gcc编译器 
	//     for (; num >= value; num -= value) {
	//         roman += symbol;
	//     }
	//     if (num == 0) break;
	// } 
	for (int i=0; i<13; ++i) {
		value_t value = valueSymbols[i].first;
		string symbol = valueSymbols[i].second;
		for (; num>=value; num-=value) {
			roman += symbol;
		}
	}
	return roman;
}
1. 要求实现一个RomanNumber类,在"不重载" operator+ 方法的情况下实现RomanNumber的加法
2. 为RomanNumber对象重载输入输出
主函数如下: (不可修改) 
int main() {
	int n;
	cin >> n;
	while (n--) {
		RomanNumber ra, rb, rc;
		cin>>ra>>rb;
		rc = ra+rb;
		cout << ra <<'+'<< rb <<'='<< rc <<'('<< ra+rb <<')'<<endl;
	}
	return 0;
}

输入

第1行: 1个正整数n,表示测试次数 
以下n行: 每行两个正整数,用空格分隔

输出

(参见样例输出) 
对于每个测试用例,输出运算表达式(使用罗马数字表示)

样例查看模式 
正常显示
查看格式
输入样例1 <-复制
4
1 3
8 8
409 90
666 3333
输出样例1
I+III=IV(4)
VIII+VIII=XVI(16)
CDIX+XC=CDXCIX(499)
DCLXVI+MMMCCCXXXIII=MMMCMXCIX(3999)

这里使用到无符号short转换到构造函数的方法

在重写加法操作时,返回的不是类,而是一个无符号short。

这里需要注意的是,在运算后类赋值和运算后输出中,表面上看加法的作用不同

但是可以利用构造函数的多样性

输出的加法运算无法改变

在重载输入运算符>>时,需要传入的为一个指针,不是一个类变量。

在RomanNumber &romanNumber需要加&符号

friend istream &operator>>(istream &in, RomanNumber &romanNumber) {

in >> romanNumber.value;

return in;

}

在重载输出运算符<<时,&可加可不加

#include <iostream>
#include "map"

using namespace std;


class RomanNumber {
public:
    unsigned short value;
    using value_t = unsigned short;
/// 表1: 490 = CDXC (本题使用该表)
    static pair<value_t, string> valueSymbols[];

     RomanNumber(unsigned short value);

    RomanNumber();

/// 表2: 490 = XD
//static const pair<value_t, string> valueSymbols[] = {
//	{1000, "M"}, {999, "IM"}, {990, "XM"}, {900, "CM"},
//	{ 500, "D"}, {499, "ID"}, {490, "XD"}, {400, "CD"},
//	{ 100, "C"}, { 99, "IC"}, { 90, "XC"},
//	{  50, "L"}, { 49, "IL"}, { 40, "XL"},
//	{  10, "X"}, {  9, "IX"},
//	{   5, "V"}, {  4, "IV"},
//	{   1, "I"}
//};
/// 贪心, 处理罗马数字[1, 3999]
    static string int2Roman(value_t num) {
        string roman;
        // for (const auto& [value, symbol] : valueSymbols) { // 8.1以上gcc编译器
        //     for (; num >= value; num -= value) {
        //         roman += symbol;
        //     }
        //     if (num == 0) break;
        // }
        for (int i = 0; i < 13; ++i) {
            value_t value = valueSymbols[i].first;
            string symbol = valueSymbols[i].second;
            for (; num >= value; num -= value) {
                roman += symbol;
            }
        }
        return roman;
    }


    friend ostream &operator<<(ostream &out, RomanNumber romanNumber) {
        out << int2Roman(romanNumber.value);
        return out;
    }

    friend istream &operator>>(istream &in, RomanNumber &romanNumber) {
        in >> romanNumber.value;
        return in;
    }


    friend unsigned short operator+(RomanNumber one, RomanNumber two) {
        RomanNumber res(one.value + two.value);
        return one.value + two.value;
    }
};

pair<unsigned short, string> RomanNumber::valueSymbols[] = {
        {1000, "M"},
        {900,  "CM"},
        {500,  "D"},
        {400,  "CD"},
        {100,  "C"},
        {90,   "XC"},
        {50,   "L"},
        {40,   "XL"},
        {10,   "X"},
        {9,    "IX"},
        {5,    "V"},
        {4,    "IV"},
        {1,    "I"}
};

RomanNumber::RomanNumber(unsigned short value) : value(value) {}

RomanNumber::RomanNumber() {}


int main() {
    int n;
    cin >> n;
    while (n--) {
        RomanNumber ra, rb, rc;
        cin >> ra >> rb;
        rc = ra + rb;
        // cout << ra.value << endl;
        // cout << rb.value << endl;
        // cout << rc.value << endl;
        cout << ra << '+' << rb << '=' << rc << '(' << ra + rb << ')' << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_62288512/article/details/131549992
OOP