92165


下記のコードで、noが入力されたら終了するプログラムを組もうとしているのですが、止まらずに無限ループしてしまいます。  
どこを修正したら良いでしょうか？

[code]

    #include <stdio.h>
    #include <time.h>
    
    int main() {
        int num1, num2;
        char op;
        float answer;
        int r,a;
        FILE* fp;
        int cnt = 0;
    
        fp = fopen("log.txt", "a");
    
        if (fp == NULL) {
            printf("ファイルオープン失敗\n");
            return -1;
        }
        
        
        while (1) {
            r = scanf("%d%c%d", &num1, &op, &num2);
            if (r != 3) {
                puts("input error");
                return 1;
            }
            cnt++;
    
            if (op == '+') {
                answer = num1 + num2;
            }
            else if (op == '-') {
                answer = num1 - num2;
            }
            else if (op == '*') {
                answer = num1 * num2;
            }
            else if (op == '/') {
                answer = (float)num1 / num2;
            }
    
            time_t t = time(NULL);
            struct tm* tm = localtime(&t);
            printf("%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
            printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
            printf("%d%c%d,%f\n", num1, op, num2, answer);
            fprintf(fp, "%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
            fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
            fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer);
    
            printf("計算を続けますか？");
            scanf("%s\n", &a);
            if (a == 'no') {
                break ;
            }
        }
            fclose(fp);
        
            return 0;
    }
    
[/code]


CC BY-SA 4.0
2022-11-11T08:32:39.057
92158
2022-11-11T12:14:10.480
2022-11-11T09:25:17.190
26370
55007
question
c
C言語のbreakについて


今のソースコードのままコンパイル・実行が出来るのなら、コンパイラに依存するかもしれませんが、その状態で「止まらずに無限ループ」していますか？

「入力(scanf()関数)が完了せず if 文の処理にたどり着いていない」状態ではありませんか？

そうではなくてもし`計算を続けますか？`の表示後に何か入力して、その後にループの先頭に戻って演算式の入力・処理が出来るなら、その次の`計算を続けますか？`の表示に対して`no`ではなく`on`を入力してみてください。

もしかしたら、それでループをbreakして終了するかもしれません。

その場合はC言語としては間違った(あるいは悪い振る舞いをする)プログラムのままですが、`if (a == 'no') {`の行を`if (a ==
'on') {`というように`n`と`o`を逆にすれば、人間が`no`と入力した場合に終了するようになるはずです。

ヒントは文字定数`'no'`は`int`型の数値`0x00006e6f`として扱われるからですね。  
そして今のソースコードで動作しているなら、`no`入力後の`a`の値は`0x00006f6e`である可能性があります。  
なので、`on`と入力すると`a`の値が`0x00006e6f`となってbreak・終了する可能性があるわけです。

* * *

**とは言え、実際にはコメントが多数付いているように、C言語のプログラムとしては以下の点で間違っています。**

  * scanf()関数で入力データの書式を示す文字列に`\n`が使われている。  
そうすると`\n`まで正確に入力する必要が出てくるので、ここでは不要。  
例えば [scanf関数](http://rainbow.pc.uec.ac.jp/edu/program/b1/Ex2-1b.htm)
のページの最後を参照

  * scanf()関数で入力データを格納する変数に`int`型の変数が使われている。  
文字列(`%s`)を格納するなら`char`型の配列で、十分なサイズを用意するべき。

  * C言語で文字列(charの配列)が同じかどうかを比較するのに`==`は使えません。  
文字列の比較には[strcmp関数](https://www.orchid.co.jp/computer/cschool/CREF/strcmp.html)(大文字小文字を区別する)や[stricmp関数](https://www.orchid.co.jp/computer/cschool/CREF/stricmp.html)(大文字小文字を区別しない)等を使用する必要があります。

  * 文字列を比較する際に比較用の固定文字列を記述するには、シングルクォーテーションは使えません。  
ダブルクォーテーションで囲む必要があります。

* * *

という訳で質問のソースコードから抜粋した以下の該当部分を：

[code]

        int r,a;
    
            scanf("%s\n", &a);
            if (a == 'no') {
    
[/code]

こちらのように変更すれば良いでしょう。(`NO`も使えるように`stricmp`にしています)

[code]

        int r;
        char a[16]={0};
    
            scanf("%s", a);
            if (stricmp(a, "no") == 0) {
    
[/code]


CC BY-SA 4.0
2022-11-11T12:14:10.480
92165
2022-11-11T12:14:10.480
26370
92158
answer