文字列の参照について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
一難民

文字列の参照について

#1

投稿記事 by 一難民 » 15年前

初めまして。一難民と申します。
私は今、配列の文字列を参照してローマ数字をアラビア数字に変換するプログラムを、
emac(Finderバージョン10.3.3)付属のXcode(バージョン1.5)を用いて作っています。
大体の面においてはうまくいくのですが、一カ所'L'についての配列でおかしな症状がでています。
1,本来+5されるべき場所がなぜか+10される
2,四桁目以降何もない場合なぜかそこでもう一度+10される
という症状がでています。
皆さんからみれば簡単なことと思いますが、どうかよろしくお願いします。

コード

#include <stdio.h>

int main (int argc, const char * argv[/url]) {
int o,t,h,th,m;
char r[100];

o=0;
t=0;
h=0;
th=0;

printf("入力してください ");
scanf("%99s",&r);


for(m=0;m<100;m++){
if(r[m-1]=='C' && r[m]=='M'){
h=h+9;
}
if(r[m-1]!='C' && r[m]=='M'){
th=th+1;
}
if(r[m-1]=='C' && r[m]=='D'){
h=h+4;
}
if(r[m-1]!='C' && r[m]=='D'){
h=h+5;
}
if(r[m-1]=='X' && r[m]=='C'){
t=t+9;
}
if(r[m]=='C' && r[m+1]=='D'){
}
if(r[m-1]!='X' && r[m+1]!='M' && r[m]=='C' && r[m+1]!='D'){
h=h+1;
}
if(r[m-1]=='X' && r[m]=='L'){
t=t+4;
}
if(r[m-1]!='X' && r[m]=='L'){
t=t+5;
}
if(r[m]=='X' && r[m+1]=='C'){
}
if(r[m]=='X' && r[m+1]=='L'){
}
if(r[m-1]=='I' && r[m]=='X'){
o=o+9;
}
if(r[m+1]!='C' && r[m+1]!='L' && r[m-1]!='I' && r[m]=='X'){
t=t+1;
}
if(r[m-1]=='I' && r[m]=='V'){
o=o+4;
}
if(r[m-1]!='X' && r[m]=='L'){
t=t+5;
}

if(r[m]=='I' && r[m+1]=='X'){
}
if(r[m]=='I' && r[m+1]=='V'){
}
if(r[m+1]!='V' && r[m+1]!='X' && r[m]=='I'){
o=o+1;
}
if(r[m]=0){
m=m+1000;
}
printf("%d%d%d%d\n",th,h,t,o);
}
printf("%d%d%d%d",th,h,t,o);

return 0;
}

パコネコ

Re:文字列の参照について

#2

投稿記事 by パコネコ » 15年前

r[m-1]ってm=0のとき大丈夫でしたっけ?
関係なさそうなことごめんなさい

パコネコ

Re:文字列の参照について

#3

投稿記事 by パコネコ » 15年前

ちなみに{}の中身がないのは使用ですか?
何も知らなくてごめんなさい
気になっちゃって

dic

Re:文字列の参照について

#4

投稿記事 by dic » 15年前

内容の理解まではできませんが
m=0 のとき
if(r[m-1]!='C'
でアクセス違反起こしてます

また m=99 のとき
if(r[m]=='X' && r[m+1]=='C'){
m+1 = 100
r[100] にアクセスしてます
これもアクセス違反ですね


あと
if(r[m-1]=='X' && r[m]=='L'){ 
            t=t+4; 
            } 
        if(r[m-1]!='X' && r[m]=='L'){ 
            t=t+5; 
            } 
...
        if(r[m-1]!='X' && r[m]=='L'){ 
            t=t+5; 
            }
同じif分が3つありますが
気になったので

シエル

Re:文字列の参照について

#5

投稿記事 by シエル » 15年前

o,t,h,thの変数は何を表しているんですか?
プログラムの内容があまり読み取れません。

Poco

Re:文字列の参照について

#6

投稿記事 by Poco » 15年前

> o,t,h,thの変数は何を表しているんですか?

ワン、テン、ハンドレッド、サウザントですかね。

シエル

Re:文字列の参照について

#7

投稿記事 by シエル » 15年前

>>ぽこさん
なるほど。ありがとうございます。
ローマ数字に関しての知識が無かった…

box

Re:文字列の参照について

#8

投稿記事 by box » 15年前

> 大体の面においてはうまくいくのですが、一カ所'L'についての配列でおかしな症状がでています。
> 1,本来+5されるべき場所がなぜか+10される
> 2,四桁目以降何もない場合なぜかそこでもう一度+10される

そのように、思った動きをしないプログラムを
仕様どおりに持っていく工程を「デバッギング」といいます。
そういう重要な工程を人任せにして、
質問者さんのC言語に関する実力が本当に付くといえるのでしょうか。

「C言語の実力なんかどうでもいい。課題の答えさえ得られればよい」とか
いうのであれば、まあそれでもいいですけれどね。

なお、プログラムにおいて「なぜかそうなる」ということは
事実上ないといってよく、「書いたとおりに動いている」というのがホントのところです。 画像

Tatu

Re:文字列の参照について

#9

投稿記事 by Tatu » 15年前

1.についてはdicさんが指摘しているところが原因だと思います。
ただ、if文の条件が全く同じなのはdicさんが挙げた3つのうち後ろの2つです。

2.について調べるとき、
数字の表示を
printf( "%d %d %d %d\n ",th,h,t,o);
にした方が良いような気がします。

Tatu

Re:文字列の参照について

#10

投稿記事 by Tatu » 15年前

2.について
scanfで取得した後の文字列を調べてみたら、
入力した文字列の後ろに0(終端文字'\0')が来て、
その後ろででたらめに文字が入っているようです。
この文字によって変数が+されるのではないでしょうか。

これが原因だとしたら
'\0'が出たところで判定をやめれば、
何もないと思っているところで変数が変わることはなくなるでしょう。

Tatu

Re:文字列の参照について

#11

投稿記事 by Tatu » 15年前

質問者が答えだけほしかったのかそれともヒントがほしかったのかを
書き込みをみて判断してから書きこみたかったのですが、
過去ログに落ちたのでプログラムを考えたときのメモと
ソースコード(cpp)を載せます。

ローマ数字について

I:1
V:5
X:10
L:50
C:100
D:500
M:1000

基本は大きな数字を左に書き、全ての数字の和がその数を表す。
しかし、4,9などは減算則が用いられる。
小さい数を大きい数の左側に置くと右の数から左の数を減じたものが示す数字となるというもの。
この減算則は右の数が左の数のちょうど5倍または10倍で左の数がI,X,Cのときに使われる。
EXCELのROMAN()関数は0~3999までをローマ数字に変換することができる。

プログラム
ローマ数字をアラビア数字にする


まずは文字列をキーボードから取得し表示するという基本のおさらい
scanf(const char *_Format,...)で取得し、
printf(const char *_Format,...)で出力することができる。

さて、プログラムを考える。


ローマ数字は文字列として扱い、アラビア数字はint型の変数一つで表したい。
というわけで文字列をinput[64],アラビア数字をoutputとする。

まずは文字列の取得
これはscanf("%s",input)でできる。
ただし、入力は常に正確なものであると仮定する。

次に左から文字を見ていく。
基本的にはそれぞれの文字が表わす数字を足していけばよいのだが
時々減算則が混ざっていることがある。これに注意しなければならない。
これに関する処理はI,X,Cの次にそれぞれ(V,X),(L,C),(D,M)があるかどうかを見て、
もしあった場合は対応した数字を足し、次の判定をとばすというようにする。

終わりになっていたらループから抜ける。



以上より書いたcppファイルがこちら。

なお、以下を実行してみたところ、
ウィキペディアの表にのっている3999までの数字については
期待通りの値が出た。

#include <stdio.h>

int main(){
char input[64];
int output=0;

int i=0;

scanf("%s",input);

while(input!='\0' && i<63 ){
switch(input){
case 'I':
switch(input[i+1]){
case 'V':
output+=4;
i++;
break;
case 'X':
output+=9;
i++;
break;
default:
output+=1;
break;
}
break;

case 'V':
output+=5;
break;

case 'X':
switch(input[i+1]){
case 'L':
output+=40;
i++;
break;
case 'C':
output+=90;
i++;
break;
default:
output+=10;
break;

}
break;

case 'L':
output+=50;
break;

case 'C':
switch(input[i+1]){
case 'D':
output+=400;
i++;
break;
case 'M':
output+=900;
i++;
break;
default:
output+=100;
break;
}
break;

case 'D':
output+=500;
break;

case 'M':
output+=1000;
break;
}
i++;
}

printf("%d\n",output);

return 0;
}

閉鎖

“C言語何でも質問掲示板” へ戻る