92260


下記の課題に取り組んでおり、ソートは一回抜かしてファイルの読み込みに取り組んでいる状態です。

> 電卓アプリケーションの作成  
>  以下の機能を満たすアプリケーションを作成してください。  
>  ※画面の表示やログの形式は原則として例示されている内容に従ってください。
>
> 1) 四則演算が出来ること  
>  2) コンソールから計算対象となる数値と演算子を受け取る  
>  例） 5 + 6  
>  3) 結果をコンソール上に表示する  
>  例） 11  
>  4) 演算結果と実行した日、時間、秒をログファイルとして保存する  
>  ログの上限は1000行とする（上限を超過するケースはひとまず考慮しなくて良い）  
>  例） log.txt に 以下の内容を記録  
>  2015/04/27 14:30:51, 5 + 6, 11  
>  5) コンソールからパラメータを受け取り、ログを実行時間の昇順/降順に並べ替えて  
>  コンソールに表示する  
>  例） ASC を入力  
>  2015/04/26 10:20:00, 5 + 6, 11  
>  2015/04/27 14:30:51, 7 - 6, 1  
>  2015/04/27 15:30:00, 7 + 8, 15  
>  2015/04/28 14:30:51, 8 + 9, 17  
>  例） DESC を入力  
>  2015/04/28 14:30:51, 8 + 9, 17  
>  2015/04/27 15:30:00, 7 + 8, 15  
>  2015/04/27 14:30:51, 7 - 6, 1  
>  2015/04/26 10:20:00, 5 + 6, 11

しかしVisual studioでのデバックで

[code]

    for (i = 0;i < 1000;i=i+1) {
            fgets(sin[1000], sizeof(sin[0]), fp);
            if (strcmp(sin, "EOF") == 0) {
                break;
            }
    
[/code]

この行でループが抜け出せなくなってしまいました。  
どこを修正すればいいえしょうか？

[code]

    #include <stdio.h>
    #include <time.h>
    #include <string.h>
    #include <stdlib.h>
    /*
    static char ad[10];
    
    int cmp_u(const void* a, const void* d) {
        return strcmp((char*)a, (char*)d);
    }
    
    int cmp_d(const void* a, const void* d) {
        return strcmp((char*)d, (char*)a);
    }
    */
    int main() {
        int num1, num2;
        char op;
        float answer;
        int r,i,n;
        FILE* fp;
        char c[11];
        char sin[1000][1000];
        char ad[8];
    
    
        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;
            }
    
            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", &c);
            if (strcmp(c, "no") == 0) {
                break ;
            }
        }
    
        int count = 0;
        
        for (i = 0;i < 1000;i=i+1) {
            fgets(sin[1000], sizeof(sin[0]), fp);
            if (strcmp(sin, "EOF") == 0) {
                break;
            }
        }
        
        fclose(fp);
    
    /*
        printf("ASC or DESC: ");
        scanf(" %s", ad);
    
        if (strcmp(ad, "ASC") == 0) {
            qsort(sin, , sizeof(sin[0]), cmp_u);
        }
        else {
            qsort(sin, , sizeof(sin[0]), cmp_d);
        }
    */
        for (i = 1; i <= n; i++) {
            printf("%s", sin[i]);
        }
        
            return 0;
    }
    
[/code]


CC BY-SA 4.0
2022-11-16T02:49:21.397
92253
2022-11-16T06:31:35.487
2022-11-16T05:18:07.193
3060
55007
question
c
ループから抜けられない

[code]

            fgets(sin[1000], sizeof(sin[0]), fp);
            if (strcmp(sin, "EOF") == 0) {
    
[/code]

`char sin[1000][1000];` と宣言されてますから、使えるのは`sin[0]`から`sin[999]`までです。`sin[1000]`
は使えません。おそらく、`fgets(sin[i], sizeof(sin[0]), fp)` としたかったのかなと思います。

`fgets()` の結果には改行が含まれています。「`EOF`と入力したら終了」としたくても、`"EOF\n"`
と比較したほうがよいかもしれません。文字列 `"EOF"` ではなくファイル終端を検出したいなら、`fgets()` の戻り値をチェックします。

また、コード中で `fp` はデータの追記に使われているので、データを読むためには使用できません。前半で追記したファイルを読みたいなら、`fclose()`
してから `fopen()` し直すか、最初の `fopen()` のモードを `"a+"` にしてファイルポジションを先頭に戻す必要があります。


CC BY-SA 4.0
2022-11-16T04:10:52.617
92256
2022-11-16T04:51:28.753
2022-11-16T04:51:28.753
3475
3475
92253
answer


Visual Studioだとデフォルトでは色々な解説やサンプルプログラムと相性の悪い[コンパイラの警告 (レベル 3)
C4996](https://learn.microsoft.com/ja-jp/cpp/error-messages/compiler-
warnings/compiler-warning-
level-3-c4996?view=msvc-170)を無効にしたとしても、以下のようなエラーが発生してビルドが正常に終了しないはずです。(メッセージの形式は変えています。)

[code]

    行  種類    内容
    93  エラー  初期化されていないローカル変数 'n' が使用されます
    43  警告    '=': 'int' から 'float' への変換です。データが失われる可能性があります。
           46行目と49行目も同じ警告
    75  警告    '関数': 間接参照のレベルが 'const char *' と 'char [1000][1000]' で異なっています。
    75  警告    'strcmp': の型が 1 の仮引数および実引数と異なります。
    24  警告    'ad': ローカル変数は 1 度も使われていません。
    
[/code]

何かプロジェクトのプロパティ等を操作して実行ファイルが出来るようにしたのかもしれませんが、IDEで表示されるエラーや警告はキチンと調べて対処するようにしましょう。

加えて93行目のエラーを修正してビルドが通ったとしても以下のような問題があります。

  * 提示された部分の処理はファイルが追加モードでオープンされたままの状態で行われており、エラーになるか何も結果は得られないでしょう。  
→いったんログファイルをクローズして読み取りモードで再度オープンしてから処理する必要があります。

  * 74行目の引数`sin`の指定方法が間違っています。  
→2次元配列で定義されているのに1次元のインデックスしか指定していません。  
→読み込んだデータの格納位置(インデックス)が常に同じ値しか指定されていません。

  * 75行目のファイル読み込み終了判定が間違っています。  
→おそらく`fgetc()`による読み込みと終了判定から類推したものと思われますが、自身が使っている関数は`fgets()`ですし、ファイル読み込みの終了を表すのは`"EOF"`という文字列ではないのと、判定する対象の変数`sin`の指定方法がおかしい等、何重にも間違っています。

何かの講座や学習コースで出た課題ならば、それ以前に説明されているはずの内容しか使わないと思われるので、今までの学習内容を見直してみてください。

* * *

ちなみにループ終了とは無関係ですが、問題文/条件は全て記載されていますか？  
質問記事に記載された内容が全てだとすると、以下の条件があいまいだと思われます。  
出題者に質問出来るなら問い合わせた方が良いでしょう。

  * 加減算の例だけがあり、乗除算の例が提示されていません。
  * 扱うものは「数値」とだけありますが、例では整数しか提示されていません。
  * 入力値に浮動小数点数は許容されますか？
  * 乗除算の結果が浮動小数点数の場合、出力値は浮動小数点数/整数のどちらでしょう？
  * 浮動小数点数を許すなら、入出力値の形式に制限や指定はありますか？

質問されることも含めて講座やコースの一環である可能性も考えられます。


CC BY-SA 4.0
2022-11-16T04:18:49.387
92257
2022-11-16T05:11:38.133
2022-11-16T05:11:38.133
26370
26370
92253
answer


解決に行き詰まった場合の御参考として，既に回答された方の御指摘を踏まえた修正案を作りました。

[code]

        /* fp = fopen("log.txt", "a"); */
        fp = fopen("log.txt", "a+");
    
            /* scanf("%s\n", &c); */
            scanf("%s", c);
    
        /* for (i = 0;i < 1000;i=i+1) { */
        /*     fgets(sin[1000], sizeof(sin[0]), fp); */
        /*     if (strcmp(sin, "EOF") == 0) { */
        rewind(fp);
        for (i = 0; i < 1000; i++) {
            if (fgets(sin[i], sizeof(sin[0]), fp) == NULL) {
                count = i;
    
        /* for (i = 1; i <= n; i++) { */
        for (i = 0; i < count; i++) {
    
[/code]


CC BY-SA 4.0
2022-11-16T06:31:35.487
92260
2022-11-16T06:31:35.487
54588
92253
answer