poj 1588(Reverse Roman Notation)

 一个中午的RE,整整排满一页,只有最后一个AC,开始一直以为只有数组越界和指针错误会是RE,今天的RE居然是因为上了一个判断条件导致调用空栈顶元素,stack空也有可能导致RE,以后要记住并且小心了……

题目大意是实现一个关于罗马数字的计算器,只包含+ - * /四种运算,每个操作数范围在1~4999。还有几种异常的处理

主要是罗马数字与十进制数字之间的相互转化,然后运用类似表达式计算原理的栈进行处理即可得到结果

Reverse Roman Notation
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 612 Accepted: 217

Description

Hermes Poseidon (HP) has produced a new calculator, the HP CXX, using the very latest in modern technology. It supports the four basic arithmetic operations on integer values from I to MMMMCMXCIX.
In this problem, you are simulating The HP CXX. Each line of input will be either a roman numeral representation of a positive integer (between I(1) and MMMMCMXCIX(4999)), which will then be pushed to the top of the virtual stack, or it will be an arithmetic operation (+ - * /) to be performed on the top two values of the stack. In addition, there is the = operation, which is a request to print the value of the top of the stack (in roman numerals, of course).
For the - operation, subtract the first number on the stack from the second. For /, divide the second number on the stack by the first. An attempt to divide by 0 should result in the error message "division by zero exception". When that happens, push the dividend (non-zero number) back onto the stack, but not the divisor (zero).
If an operation is requested, and there are insufficient numbers on the stack, print the error "stack underflow" and leave the stack unchanged. This applies to both the binary operations +-*/ and the print operation =.
If an attempt is made to print a number whose value is 0 or less, or whose value is greater than MMMMCMXCIX(4999), display the error message "out of range exception" and go on to the next line of input.

Roman Numerals
For those who are unfamiliar with Roman Numerals, here is a quick summary:
Each letter used in Roman numerals stands for a different number:
Roman Numeral       Number

--------------------------

     I                1   

     V                5   

     X                10  

     L                50  

     C                100 

     D                500 

     M                1000

A string of letters means that their values should be added together. For example, XXX = 10 + 10 + 10 = 30, and LXI = 50 + 10 + 1 = 61. If a smaller value is placed before a larger one,
we subtract instead of adding. For instance, IV = 5 − 1 = 4 and XC = 100 − 10 = 90.

  • Except for M, do not add more than three of the same letters together.
  • Subtract only powers of ten, such as I, X, or C. Writing VL for 45 is not allowed: write XLV instead.
  • Subtract only a single letter from a single numeral. Write VIII for 8, not IIX; 19 is XIX, not IXX.
  • Don't subtract a letter from another letter more than ten times greater. This means that you can only subtract I from V or X, and X from L or C, so MIM is illegal.

Input

Each input line consists of either:
  • A Roman numeral between I and MMMMCMXCIX, or
  • An arithmetic operation +, -, /, or *, or the print operator, =
    The input ends at the end-of-file.

Output

A line will be output:

  • For every print operation, print the value at the top of the stack, or
  • One of the error messages, on a line by itself:
    • division by zero exception
    • stack underflow
    • out of range exception

No other output should be produced

Sample Input

I
I
+
=
II
*
=
VIII
-
=

Sample Output

II
IV
out of range exception

Source

代码:

#include<cstdio>
#include<iostream>
#include<stack>
#include<string>
#include<cstring>

using namespace std;

int in[13] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
string ccc[13] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

int char_2_int(char ch){
    switch(ch){
        case 'I': return 1;
        case 'V': return 5;
        case 'X': return 10;
        case 'L': return 50;
        case 'C': return 100;
        case 'D': return 500;
        case 'M': return 1000;
        //default: return -1;
    }
    //return -1;
}

int to_int(char ch[]){
    int sum = 0;
    for(int i = 0; ch[i] != '\0'; i++){
        if(ch[i + 1] == '\0'){sum+=char_2_int(ch[i]);}
        else if(char_2_int(ch[i]) >= char_2_int(ch[i+1])){
            sum+=char_2_int(ch[i]);
        }
        else{
            sum+=char_2_int(ch[i+1]) - char_2_int(ch[i]);
            i++;
        }
    }
    return sum;
}

string to_string(int n){
    string str = "";
    int i = 0;
    while(n>0){
        if(n >= in[i]){
            n -= in[i];
            str +=ccc[i];
        }
        else i++;
    }
    return str;
}
int main(){
    char s[20];
    stack<int>  sta;
    int fuck;

    while(scanf("%s", s) != EOF){
        if(s[0] == '+'){
            if(sta.size()<2)  printf("stack underflow\n");
            else{
                int a = sta.top();sta.pop();
                int b = sta.top();sta.pop();
                sta.push(a+b);
            }
        }
        else if(s[0] == '-'){
            if(sta.size()<2)  printf("stack underflow\n");
            else{
                int a = sta.top();sta.pop();
                int b = sta.top();sta.pop();
                sta.push(b - a);
            }
        }
        else if(s[0] == '*'){
            if(sta.size()<2)  printf("stack underflow\n");
            else{
                int a = sta.top();sta.pop();
                int b = sta.top();sta.pop();
                sta.push(b * a);
            }
        }
        else if(s[0] == '/'){
            if(sta.size()<2)  printf("stack underflow\n");
            else{
                int a = sta.top();sta.pop();
                int b = sta.top();sta.pop();
                if(a == 0){
                    printf("division by zero exception\n");
                    sta.push(b);
                }
                else sta.push(b / a);
            }
        }
        else if(s[0] == '='){
            if(sta.size() == 0){
                printf("stack underflow\n");
            }
            else if(sta.top()>4999 || sta.top()<1){
                printf("out of range exception\n");
            }
            else{
                printf("%s\n",to_string(sta.top()).c_str());
            }
        }
        else{
            sta.push(to_int(s));
        }
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值