読者です 読者をやめる 読者になる 読者になる

C言語の航海日誌(2)

今日は3点のサンプルコードを写経しました。

一つは以下。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int score[100];
    int status;
    int temp_score;
    int score_count;
    int i;

    /* 配列に値を入力する */
    score_count = 0;
    while (1) {
        status = scanf("%d", &temp_score);
        if (status == EOF) {
            break;
        } else if (status != 1) {
            fprintf(stderr, "入力エラーです\n");
            exit(1);
        }
        if (score_count >= 100) {
            fprintf(stderr, "データ件数が多すぎます\n");
            exit(1);
        }
        score[score_count] = temp_score;
        score_count++;
    }

    /* 配列の内容を表示する */
    for (i = 0; i < score_count; i++) {
        printf("score[%d]: %d\n", i, score[i]);
    }

    return 0;
}

動かすとこんな感じです。

f:id:note103:20160520012215g:plain

(ちなみにコマンドプロンプトの「2$」の「2」はカレントディレクトリ。今は第2章のサンプルコードを書いているので「2」というディレクトリ内で作業している)

「8, 9...」というふうに数字を入れていくのは前回同様ですが、今回は終了の合図を「-1」ではなく、EOFで示しています。
上記DEMOでは、標準入力からコントロール+DでEOFを伝えています。

ファイルのリダイレクトで同様のことする場合は、こんな感じ。

f:id:note103:20160520012814g:plain

標準入力版に戻って、数字ではなく文字を入れてしまうと……

f:id:note103:20160520012852g:plain

はい。

そのEOFですが、Perlだとあまり聞かないなあ、せいぜいヒアドキュメントの時に例としてそういう文字列が出てくるぐらいだけど、じゃあPerlで同様にEOFを示したい場合ってどうするんだろ?

と思ったんですが、ざらっと調べたかぎりでは、「Perlでも一応 eof という組み込み関数が用意されているけど、勝手にEOFを認識して終わってくれるから使うことはほとんどない」みたいな説明が多く、まあ確かにそのようにも思えるんだけど、じゃあ「ファイルが終わったら(あるいは標準入力からの入力が終了したら)メッセージ出してから終わらせたい」と思った場合どうするんだろ? みたいな疑問が湧いてきて……

こんなコードを考えてみました。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

print ">>> ";
while (my $t = <STDIN>) {
    print $t;
    print ">>> ";

    say 'bye' if (eof);
}

動かすと、こんな感じ。

標準入力版

f:id:note103:20160520014920g:plain

※「7」を入力した後にコントロール+Dを入れています。

リダイレクト版

f:id:note103:20160520015031g:plain

まあ確かに、特殊といえば特殊、あまり使わないケースかもしれないですが……。

とはいえ、これまで知っているようでまったく理解していなかったEOF/eofについて(図らずもPerlを含めて)知見を得られて良かったです。

今日はその他、プリプロセッサとマクロの違いについて学べるサンプルコードなども写しましたが、たしかに言われたとおりに動いていることは確認できたものの、ちょっと難しかったかな……。

次回からは上記のサンプルコードをさらに発展させた、ソートをテーマにしたコードに入っていきそうです。
今日の記事では触れませんでしたが、今回のサンプルコードからfprintfを使ったり、scanfの戻り値を利用するようになったりと、ページが進むごとに結構目覚ましくトピックが増えていくので、次も楽しみ&大変そう……な感じですが。