

逆ポーランドを実装しようとした際に、 `while(scanf("%s", s) != EOF)` で入力を受け取った後に `if(s[0] ==
'+')` で条件分岐が始まるのですが、なぜ `s[0]` と配列 `s` のインデックスを `0` に固定したままでも良いのでしょうか？  
`s[0]` の次は `s[1]` 、さらに `s[2]` とインデックスを増やしていき、最終的に `s[n]` が `EOF`
なら終了するとイメージしているのですが、何が違うのでしょうか？

**ソースコード**

[code]

    #include <bits/stdc++.h>
    using namespace std;
    
    int top, S[1000];
    
    void push(int x) {
        S[++top] = x;
    }
    
    int pop() {
        top--;
        return S[top+1];
    }
    
    int main() {
        int a, b;
        top = 0;
        char s[100];
    
        while(scanf("%s", s) != EOF) {
            if(s[0] == '+') {
                a = pop();
                b = pop();
                push(a + b);
            } else if (s[0] == '-') {
                b = pop();
                a = pop();
                push(a - b);
            } else if (s[0] == '*') {
                a = pop();
                b = pop();
                push(a * b);
            } else {
                push(atoi(s));
            }
        }
    
        printf("%d\n", pop());
    
        return 0;
    }
    
    
[/code]

また、

[code]

    int main() {
        int a, b;
        top = 0;
        char s;
    
        while(scanf("%c", s) != EOF) {
            if(s == '+') {
                a = pop();
                b = pop();
                push(a + b);
            } else if (s == '-') {
                b = pop();
                a = pop();
                push(a - b);
            } else if (s == '*') {
                a = pop();
                b = pop();
                push(a * b);
            } else {
                push(atoi(s));
            }
        }
    
        printf("%d\n", pop());
    
        return 0;
    }
    
[/code]

と、上記のようにchar s[100]をchar sに、while(scanf("%s", s) != EOF)をwhile(scanf("%c", s)
!= EOF)に、if(s[0]== '+') をif(s == '+') に変えた場合うまくいかないのですが、理由がわかりません。  
1 + 1 のように入力する数字を1桁に絞ってます。


CC BY-SA 4.0
2020-05-04T07:20:18.937
66276
2020-06-06T13:01:55.240
2020-05-04T09:36:09.113
39983
39983
question
c++ アルゴリズム スタック
c++でのスタック構造について


scanfの%s指定子は空白類文字(半角スペースや改行)区切りに標準入力への文字列を入れていく物です  
(char s[100]へガツンと一括入力される訳ではありません)

例えば「11 12 +」という入力がある場合

1回目のsには「11」  
2回目のsには「12」  
3回目のsには「+」

がそれぞれ入ります

各記号の場合、入力毎の1文字目しか見なくても問題がないので  
s[0]を指定しているのだと思います。

余談ですが、多分どこかの本に出ている例題だったりしませんか？  
入力例のような物があれば、デバッガやprintfをはさみつつ動作を確認すると分かりやすいかもしれません  
(下記は一例です)

[code]

    int main() {
        int a, b;
        top = 0;
        char s[100];
        int cnt = 1;
    
        while(scanf("%s", s) != EOF) {
            printf("%d回目:%s\n",cnt,s);
            if(s[0] == '+') {
                a = pop();
                b = pop();
                push(a + b);
            } else if (s[0] == '-') {
                b = pop();
                a = pop();
                push(a - b);
            } else if (s[0] == '*') {
                a = pop();
                b = pop();
                push(a * b);
            } else {
                push(atoi(s));
            }
            ++cnt;
        }
    
        printf("%d\n", pop());
    
        return 0;
    }
    
[/code]

※追記質問について  
以下の3点に問題がありそうです。  
（文末に修正コードを記述しましたので、照らし合わせつつ確認してみて下さい)

1.scanfの第2引数へポインタを指定していない  
scanfには格納オブジェクトのポインタを指定する必要が有ります。  
配列型から要素型(char [100]→char)に変更していますので、この場合ポインタを取る形へ修正する必要が有ります

2.atoiへ文字列へのポインタを指定していない  
atoiは文字列をint型の数値へ変換する関数ですので、文字を変換することは出来ません

文字を数値にしたい場合は、「対象の文字 - '0'」と記述する必要が有ります  
(言語規格において、この操作はどのプラットフォームでも正しく動作する事が間接的に保証されています)  
例:  
char s = '3'  
int value = s - '0';

3.改行文字や空白文字を数値として入力してしまう  
%sと違い空白類文字を飛ばしてくれないので  
空白や改行が入力された時に数値として認識してしまいます

[code]

        while(scanf("%c", s) != EOF) { ←1.空白が入力された時
            if(s == '+') {             ←2.+ではない
                a = pop();
                b = pop();
                push(a + b);
            } else if (s == '-') {     ←3.-でもない
                b = pop();
                a = pop();
                push(a - b);
            } else if (s == '*') {     ←4.*でもない
                a = pop();
                b = pop();
                push(a * b);
            } else {                   ←5.数値じゃないのに数値として入ってしまう
                push(atoi(s));
            }
        }
    
[/code]

上記の問題点を修正して少し書き直してみました

[code]

    #include <bits/stdc++.h>
    using namespace std;
    
    int top, S[1000];
    
    void push(int x) {
        S[++top] = x;
    }
    
    int pop() {
        top--;
        return S[top+1];
    }
    
    int main() {
        int a, b;
        top = 0;
        char s;
    
        while(scanf("%c", &s) != EOF) { //1.scanfの第2引数をポインタに修正
            if(s == '+') {
                a = pop();
                b = pop();
                push(a + b);
            } else if (s == '-') {
                b = pop();
                a = pop();
                push(a - b);
            } else if (s == '*') {
                a = pop();
                b = pop();
                push(a * b);
            } else if(isspace(s)){     //3.改行文字や空白文字が入ってきたら何もせずに次へ
                /* do nothing */
            } else {
                push(s - '0');         //2.atoiが使用出来ないので、s-'0'を使用するように修正
            }
        }
    
        printf("%d\n", pop());
    
        return 0;
    }
    
[/code]

上記回答や元ソースコードと照らし合わせて確認してみて下さい


CC BY-SA 4.0
2020-05-04T08:35:22.230
66279
2020-05-04T10:59:00.203
2020-05-04T10:59:00.203
24599
24599
66276
answer