OOP Suma de números romanos (sobrecarga de entrada y salida + conversión de tipo)

【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)

Aquí utilizamos el método de convertir un corto sin firmar en un constructor.

Al anular la operación de suma, lo que se devuelve no es una clase, sino un corto sin firmar.

Lo que debe tenerse en cuenta aquí es que en la asignación de clase posterior a la operación y la salida posterior a la operación, los efectos de la suma son diferentes en la superficie.

Pero puedes aprovechar la diversidad de constructores.

La operación de suma de la salida no se puede cambiar.

Al sobrecargar el operador de entrada >>, lo que se debe pasar es un puntero, no una variable de clase.

En RomanNumber y romanNumber, debe agregar el signo comercial

amigo istream &operador>>(istream &in, RomanNumber &romanNumber) {

en >> numeroromano.valor;

regresar en;

}

Al sobrecargar el operador de salida <<, & se puede agregar o no.

#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;
}

Supongo que te gusta

Origin blog.csdn.net/m0_62288512/article/details/131549992
Recomendado
Clasificación