ページ 11

ローマ文字への変換

Posted: 2007年12月08日(土) 19:14
by うしくん
OS:Vista コンパイラ:borlandC++

1~4999までの整数を入力してローマ記法に変換するプログラムを作ったのですが、実行すると
的外れの結果になります。0(ゼロ)を入力すると終了するように作ったつもりなのですが、
終了しません。どこが悪いのかまったくわかりません。宜しくお願いします。
また、もっとスマートに作れるのであれば、指摘もお願いします。
#include<stdio.h>

int main(void)
{
	int n=0,m,p,q,r;
	char seisu[5];
	printf("1~4999までの整数を入力してください。\n");
	fflush(stdout);
	while(1)
	{
		printf("Input integer (0 QUIT)====>");
		fflush(stdout);
		scanf("%s",&seisu);
		if(seisu[0]==0)break;
		printf("%s ===> ",seisu);
		fflush(stdout);
		while(seisu[n]!='\0')
		{
			n++;
		}
		p=n-3;
		q=n-2;
		r=n-1;
		if(n==4)		/*千の位*/
		{
			for(m=1;m<=seisu[0];m++)
			{
				printf("M");
			}
			n--;
		}
		if(n==3)		/*百の位*/
		{
			if(seisu[p]>=5)
			{
				printf("D");
				for(m=1;m<=seisu[p]-5;m++)
				{
					printf("C");
				}
			}
			else
			{
				for(m=1;m<=seisu[p];m++)
				{
					printf("C");
				}
			}
			n--;
		}
		if(n==2)		/*十の位*/
		{
			if(seisu[q]>=5)
			{
				printf("L");
				for(m=1;m<=seisu[q]-5;m++)
				{
					printf("X");
				}
			}
			else
			{
				for(m=1;m<=seisu[q];m++)
				{
					printf("X");
				}
			}
			n--;
		}
		if(n==1)		/*一の位*/
		{
			if(seisu[[/url]==9){
				printf("IX");
			}else if(seisu[[/url]>=5){
				printf("V");
				for(m=1;m<=seisu[[/url]-5;m++)
				{
					printf("I");
				}
			}else if(seisu[[/url]==4){
				printf("IV");
			}else{
				for(m=1;m<=seisu[[/url];m++)
				{
					printf("I");
				}
			}
		}
		printf("\n");
	}
	return 0;
}
長い文章ですみません。

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 19:56
by box
> 		if(seisu[0]==0)break;

数値の0と数字の'0'とは異なります。

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 20:16
by うしくん
ありがとうございます。終了する部分はうまくいくのですがローマ文字への変換がうまくいきません。
もしかしてこれも数値と数字の違いが原因なのでしょうか?

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 20:27
by box
私だったら、こんな構造体を作って考えます。


#include <stdio.h>

typedef struct __roman {
	char *romanChar;
	int number;
} Roman;

int main(void)
{
	Roman roman[/url] = {
		{ "I",    1 }, { "IV",   4 }, { "V",   5 }, { "IX",   9 },
		{ "X",   10 }, { "XL",  40 }, { "L",  50 }, { "XC",  90 },
		{ "C",  100 }, { "CD", 400 }, { "D", 500 }, { "CM", 900 },
		{ "M", 1000 },
	};
	
	return 0;
}

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 20:53
by box
ちょっとした例を作ってみました。
参考になるとよいのですけれど。


#include <stdio.h>

typedef struct __roman {
	char *romanChar;
	int number;
} Roman;

int main(void)
{
	Roman roman[/url] = {
		{ "I",    1 }, { "IV",   4 }, { "V",   5 }, { "IX",   9 },
		{ "X",   10 }, { "XL",  40 }, { "L",  50 }, { "XC",  90 },
		{ "C",  100 }, { "CD", 400 }, { "D", 500 }, { "CM", 900 },
		{ "M", 1000 },
	};
	int m, n, i;
	
	for (n = 1; n <= 4999; n++) {
		printf("%4d:", n);
		m = n;
		for (i = sizeof(roman) / sizeof(roman[0]) - 1; i >= 0; i--) {
			while (m / roman.number) {
				printf("%s", roman.romanChar);
				m -= roman.number;
			}
		}
		putchar('\n');
	}
	return 0;
}

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 21:31
by うしくん
ありがとうございます。参考にしてみます。

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 22:42
by うしくん
for (i = sizeof(roman) / sizeof(roman[0]) - 1; i >= 0; i--) {
			while (m / roman.number) {
				printf("%s", roman.romanChar);
				m -= roman.number;
			}
		}


この部分がいまいちよくわかりません。
解説をしていただけないでしょうか?特にforとwhileの条件式のところが
よく理解できません。お願いします。

Re:ローマ文字への変換

Posted: 2007年12月08日(土) 23:25
by box
>		for (i = sizeof(roman) / sizeof(roman[0]) - 1; i >= 0; i--) {

sizeof(roman) / sizeof(roman[0]) は、構造体の配列 roman[/url] の
要素数です。有効な添字の最大値は(要素数-1)です。
このforループでは、roman[/url] の要素を後ろから順にたどります。

>			while (m / roman.number) {

ローマ数字に変換したい数値 m を、1000, 900, 500, ..., 5, 4, 1 の順に
割ります。商が正ならば、m は割った数以上の値を持ちます。
ただし、例えば 1000 で割るとき、1 回だけ割って終わり、というわけではありません。
割れなくなるまで繰り返す必要があります。そのために、while 文による
ループを構成しています。

>				printf("%s", roman.romanChar);

割った数に対応するローマ数字を出力します。

>				m -= roman.number;

ローマ数字を出力した分を除く必要があります。

Re:ローマ文字への変換

Posted: 2007年12月09日(日) 00:01
by たかぎ
> typedef struct __roman {

二重の下線で始まる識別子は予約済み識別子ですので使用することは出来ません。
本題からは外れますが、真似する人がいるといけないので、念のため指摘しておきます。

Re:ローマ文字への変換

Posted: 2007年12月09日(日) 00:09
by box
> 二重の下線で始まる識別子は予約済み識別子ですので使用することは出来ません。

あ、そうでしたか。
後学のために、どのように修正すればよいか
教えていただけますか?

Re:ローマ文字への変換

Posted: 2007年12月09日(日) 00:30
by box
下線で始まり、下線または大文字が続く識別子は予約済とのことですので、

typedef struct roman {

あたりで十分のようです。
どうもお騒がせいたしました。

Re:ローマ文字への変換

Posted: 2007年12月09日(日) 00:39
by うしくん
分かりやすい丁寧な解説をありがとうございます。
boxさんのを参考にして作ってみたらできました。
自分が作ってたのよりとてもスマートに出来ました。
#include <stdio.h>

typedef struct __roman {
	char *romanChar;
	int number;
} Roman;

int main(void)
{
	Roman roman[/url] = {
		{ "I",    1 }, { "IV",   4 }, { "V",   5 }, { "IX",   9 },
		{ "X",   10 }, { "XL",  40 }, { "L",  50 }, { "XC",  90 },
		{ "C",  100 }, { "CD", 400 }, { "D", 500 }, { "CM", 900 },
		{ "M", 1000 },
	};
	int  n, i;
	printf("------------ OUTPUT -----------\n");
	fflush(stdout);
	while(1)
	{
		printf("Input integer (0 QUIT)====>");
		fflush(stdout);		
		scanf("%d",&n);
		if(n==0)break;
		for (i =sizeof(roman) / sizeof(roman[0]) - 1; i >= 0; i--)
		 {
			while (n/roman.number)
			 {
				printf("%s", roman.romanChar);
				n -= roman.number;
			}
		}
		putchar('\n');
	}
	printf("------------- END -------------\n");
	return 0;
}


ありがとうございました。

Re:ローマ文字への変換

Posted: 2007年12月09日(日) 00:42
by うしくん
更新していなかったので気づきませんでした。
下線は消しておきます。
ありがとうございました。