今、気づきました。
アラビア数字から、ローマ数字へ変換できるだけでは、間が、抜けているということを、です。
その逆が出来なければ、あほ。
従って、その逆を行うために、ローマ数字からアラビア数字へ変換してやる方法を、考えなくてはなりません。
で、東北本線(高崎線かも)の電車の中で考えました。
基本的には、次のようになると思います。
ただ、例外があります。
こんなところでしょうか。
上記の要求にしたがって記述したら、このようになりました。
見れば分かりますが、言語はCです。
かなり汚いソースですし、洗練されていないロジックなので恥ずかしいのですが、あくまでもサンプルですので。
で、 Java に移植したソースが、こちらにあります。
Java 版は、 main関数もつけといたので、コンパイルすればそのまま実行できます。
Java なので、当然ながら、javaが必要です。
Sun からダウンロードするなりして、適当に入手して下さいませ。
で、これを、この前作ったアラビア数字→ローマ数字自動変換モジュールとくみあわせてやれば、自動判別機能付きの相互変換も出来る事になります。
ちなみに、これのGUIの実行モジュールは、めんどくさいので端折りました。
相互変換モジュールのほうは作るつもりなので、そちらを見て下さいませ。
<↑>
------ここから-----
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define null NULL
/*
(c)1999 A.Matsuda
arabic.c
*/
struct{
int c;
int v;
}tbl[] = {
{ 'm', 1000 },
{ 'd', 500 },
{ 'c', 100 },
{ 'l', 50 },
{ 'x', 10 },
{ 'v', 5 },
{ 'i', 1 },
{ -1 , -1 },
};
int chkv( int c )
{
int i;
for( i = 0 ; ; i++ ){
if( tbl[i].c == -1 ){
break;
}
if( toupper(tbl[i].c) == toupper(c) ){
return 1;
}
}
return 0;
}
int getv( int c )
{
int i;
for( i = 0 ; ; i++ ){
if( tbl[i].c == -1 ){
break;
}
if( toupper(c) == toupper(tbl[i].c) ){
return tbl[i].v;
}
}
return -1;
}
int arabic( char* buf , int* val )
{
int prev = 0;
int current = 0;
int i;
int cnt = 0;
if( buf == null || val == null ){
return 1;
}
*val = 0;
for( i = 0 ; i < strlen( buf ) ; i ++ ){
if( chkv(buf[i]) ){
current = getv( buf[i] );
if( prev == current){
cnt++;
}
else{
if( prev < current && cnt >= 1 ){
/* 2回以上引かれる数より小さな数が続いた後に減算を行う事はない */
return -2;
}
cnt = 0;
}
if( current > prev && prev != 0 ){
if( prev*5 != current && prev*10 != current ){
return -2;
}
if( prev == 5 || prev == 50 || prev == 500 ){
return -2;
}
*val -= prev*2;
*val += current;
prev = current - prev;
}
else{
/* 一度減算をおこなったら、currentよりも小さな値であるべき */
if( prev != 0 && (( (prev%9) == 0 ) && (prev/9) <= current) ) {
return -2;
}
if( prev != 0 && ( prev == 4 || prev == 40 || prev == 400 ) && ( ( prev / 4 ) <= current ) ){
return -2;
}
if( ( prev == 5 || prev == 50 || prev == 500 ) && (cnt >= 1 ) ){
return -2;
}
*val += current;
prev = current;
}
}
else{
return -3;
}
}
return 0;
}
------ここまで-----
ソースプログラムのダウンロードはこちらをクリックして下さい。
<↑>
つかいかた
つかいかたのごせつめい。
関数のつかいかたのごせつめい。
書式
引数
戻値 int
<↑>
ご注意
<↑>
------ここから-----
/*
arabic.java
(c)1999 A.Matsuda
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.Toolkit.*;
import java.applet.*;
import java.util.*;
import java.lang.*;
import java.text.*;
import java.lang.System.*;
public class arabic
{
static final char delimiter = (char)-1;
class elem{
char c;
int v;
public elem(char c, int v){
this.c = c;
this.v = v;
}
public char getChar()
{
return c;
}
public int getVal()
{
return v;
}
};
elem tbl[]={
new arabic.elem( 'm', 1000 ),
new elem( 'd', 500 ),
new elem( 'c', 100 ),
new elem( 'l', 50 ),
new elem( 'x', 10 ),
new elem( 'v', 5 ),
new elem( 'i', 1 ),
new elem( delimiter , -1 ),
};
boolean chkv( char c )
{
int i;
for( i = 0 ; ; i++ ){
if( tbl[i].getChar() == delimiter ){
break;
}
if( tbl[i].getChar() == c ){
return true;
}
}
return false;
}
int getv( char c )
{
int i;
for( i = 0 ; ; i++ ){
if( tbl[i].getChar() == (char)-1 ){
break;
}
if( c == tbl[i].getChar() ){
return tbl[i].getVal();
}
}
return -1;
}
int arabic( String buf ) throws Exception
{
int prev = 0;
int current = 0;
int i;
int val = 0;
int cnt = 0;
buf.trim();
buf = buf.toLowerCase();
for( i = 0 ; i < buf.length() ; i ++ ){
if( chkv( buf.charAt( i ) ) == true ){
current = getv( buf.charAt( i ) );
if( prev == current){
cnt++;
}
else{
if( prev < current && cnt >= 1 ){
//2回以上引かれる数より小さな数が続いた後に減算を行う事はない
throw new Exception("書式が不正です");
}
cnt = 0;
}
if( current > prev && prev != 0 ){
if( prev * 5 != current && prev * 10 != current ){
throw new Exception("書式が不正です");
}
if( prev == 5 || prev == 50 || prev == 500 ){
throw new Exception("書式が不正です");
}
val -= prev * 2;
val += current;
prev = current - prev;
}
else{
//一度減算をおこなったら、currentよりも小さな値であるべき
if( prev != 0 && ( ( ( prev % 9 ) == 0 ) && ( ( prev / 9 ) <= current) ) ) {
throw new Exception("書式が不正です");
}
if( prev != 0 && ( prev == 4 || prev == 40 || prev == 400 ) && ( (prev / 4) <= current ) ){ //減算が行われた直後に同じ桁の数は並ばない。
throw new Exception("書式が不正です");
}
if( ( prev == 5 || prev == 50 || prev == 500 ) && (cnt >= 1 ) ){
throw new Exception("書式が不正です");
}
val += current;
prev = current;
}
}
else{
throw new Exception("不正な文字が含まれています");
}
}
return val;
}
public static void main( String arg[] )
{
int i;
int val;
arabic arabic = new arabic();
for( i = 0 ; i < arg.length ; i++ ){
try{
val = arabic.arabic( arg[ i ] );
}
catch( Exception e ){
System.out.println( e.getMessage() );
continue;
}
System.out.println( arg[i] + "-->" + new Integer(val).toString() );
}
};
};
------ここまで-----
ソースプログラムのダウンロードはこちらをクリックして下さい。
<↑>
つかいかた
つかいかたのごせつめい。
引数のあたえかた
クラスの使い方のご説明。
class arabic:
int arabic( String buf ) throws Exception
引数
戻値 int
付記
<↑>
ご注意
<↑>
<ホームページへ> <ローマ数字変換へ> <ローマ数字→アラビア数字自動変換へ> <アラビア数字←→ローマ数字相互自動変換へ>
Copyright © MCMXCIX Ayumi Matsuda All rights reserved.