しき さんが書きました:
push関数の返却値というのは return stack[sp]のことでしょうか。これは数値をスタックに格納したのち、その次(上)に来る数値のために用意したものです。・・と認識していますが何か間違っているでしょうか・・・?
push関数には出口が 3つあります。
- 18行目: return stack[sp];
- 20行目: return 0;
- 31行目: }
push は int の値を呼出し元に返さないといけないのに、
何も返していないところがあります。
stack[sp] を返す時と、0 を返す時に違いがありますか?
sp の初期値は -1 です。最初の data は stack[-1] に
格納しています。これは、やってはいけないことです。
次に sp++; で sp は 0 になります。
stack[0] には何も値を入れていませんが、グローバル変数
ですから、初期値 0 が入っています。
return stack[sp]; でこの 0 を返したいのですか?
次にデータを入れる場所は、更新した sp が持っています。
それで十分です。stack[sp] の値を呼び出し元に返すことに
何の意味があるんですか?
しき さんが書きました:
また書き忘れていたのでですがこのpush関数を呼び出す際に文字を入力してこの関数を呼び出しています。
:
このせいなのか
かずまさんが提示してくださった解答では解決にはなりませんでした。
そりゃそうでしょう。私は、最初のプログラムの
main で動くように最低限の修正をしただけです。
別の main を持ち出して、解決にはなりませんでした、
と言われても困ります。
と言っておけば、その main でも動いたでしょう。
%c の前のスペースの意味をご存知ですか?
その main の 15行目でも scanf(" %c",&choice); と
使っていますね。意味も解らずそう書いているのですか?
試しにそこのスペースをとってみてください。
どうなりますか?
しき さんが書きました:
push関数で判別する前にはじかれていると思ったので再度%cを%sに変更しました。
:
と一応正常(?)に動くようになりました。
ですがなぜ%cを%sにして正常になったか理解できていません・・。
まず、"%c" でダメだった理由を説明します。
scanf(" %c",&choice);
scanf("%c",&t);
このように 2つの scanf を実行していますよね。
最初の scanf に対して、i と ENTER のキーを入力しました。
これらは 'i' と '\n' になって、標準入力のバッファに入ります。
scanf は 'i' だけを読み込んで choice に格納します。
次の scanf では '\n' を読み込んで t に格納します。
したがって、3 ENTER を入力する前に、push が呼び出されて、
data には '\n' が入っているので「格納する一桁の数字を
入力してください」が表示されるのです。
"%s" でうまくいった理由を説明します。
"%s" は先行する 0文字以上の空白類文字(スペースやタブや改行
などの文字)を読み飛ばしてから、空白類文字でない文字列を
1文字以上読み取ろうとします。
なので、改行文字の '\n'は読み飛ばされて、次の入力を待ちます。
3 ENTER を入力すると、'3' が t に格納されます。
" %c" でうまくいく理由を説明します。
書式のスペースには、0文字以上の連続する空白類文字を
読み飛ばす機能があります。これにより、%c で '3' を
t に格納できるようになります。
次に char t; scanf("%s", &t); がダメな理由を説明します。
"%s" で読み込むのは文字列です。
C がプログラム内で扱う文字列とは '\0' で終了するデータです。
たとえ '3' という 1文字を読み込んだとしても、
t に '3' と '\0' を格納しようとします。
t は char ですから 1文字しか入りません。
'\0' は t の場所の次のメモリに無理やり格納されます。
そこに重要なデータがあればそれが破壊されます。
今うまくいったように見えるのは、そこがたまたま 0 だったか、
参照されないデータだったかなのでしょう。"%s" を使うときは、
char s[100]; scanf("%s", s);
のように十分な大きさの領域(char配列)を用意して文字列を
読み込まないといけません。
しき さんが書きました:
またかずまさんが提示してくださった{data-='0';}というのもよく分かったないです・・。
t に '3' が読み込まれたとして、push が呼び出されると、
引数の data には '3' が入っています。
isdigit('3') は真です。
ところが '3' は 3 ではありません。
文字の '3' は文字コード表を見ると、
16進の 0x33、すなわち 10進の 51 という値です。
data < 10 は偽になります。
文字を数値に変換しておかないといけないのです。
data -= '0'; で data から '0' を引くと、
data が '3' だったのが 3 になります。
最後に、あれだけ何度もインデントをちゃんとする
ようにと言っているのに、そうなっていません。
main の終了はどこですか?
29行目の } ですか?
それなら while(1){ の終了の } はどれですか?
最初のプログラムの push 関数には、3つの if と
2つの else がありますが、その else がどの if に
対応するのかすぐにわかりますか?
No.4 でインデントをちゃんとしたプログラムでは
それらの対応がすぐにわかります。
さらに、maruさんの指摘のように 3つの printf が
一体化されていないこともわかります。