課題7 課題9

課題8

書式付入力(scanf)

数字当てプログラムで当てる数字を入力させたあとの処理は面倒で、 一桁の数字を読み込むための処理としては、エラー処理を除いても、次の手順が必要であった。

    int ch;  /* 答を格納する変数 */

    ch = getchar();  /* 標準入力から1文字読み込む */
    ch = ch - '0';
  

さらに桁数が2になると、煩雑さが増えた。エラー処理を省略した手順は次の通りであった。

    int i, j; /* 作業用変数 */
    int ch;  /* 答を格納する変数 */

    ch = 0;  /* 最初は 0 にしておく */
    for (i = 0; i < 2; ++i) {
        ch *= 10;
        j = getchar();
        j -= '0';
        ch += j;
    }
  

出力の場合は、printf() を使うと、 単に書式を指定するだけで変数の中身を表示することができたのと比較すると大きく異なる。

    printf("%d\n", ch);
  

しかし、出力の場合も、putchar()しか使えなければ同程度に煩雑である。 変数 ch に入っている数を標準出力に表示するためには次のような手順が必要である。

    /* 1桁の数字の出力 */
    int ch = 5; /* 1桁の数を保持する出力したい変数 */

    putchar(ch + '0');
  
    int i;    /* 作業用変数 */
    int ch = 12345;
    int factor = 10000;

    while (ch > 0) {
         i = ch / factor;
         i = i + '0';
         putchar(i);
         ch %= factor;
         factor /= 10;
    }
    putchar('\n');
  

ならば、入力にも printf のような簡便な方法があっても良いのでは?と感じないだろうか? 実際 scanf という関数が用意されている。 scanf関数は、printf関数と同様な書式を用いて、 与えられた内容を変換して変数に格納する。 たとえば、変数 ch1, ch2 に標準入力から10進数の数字を読み込み、 配列 string に文字列を読み込むためには、次のようにプログラミングすれば良い。

/* scanf_demo.c */
#include <stdio.h>

int main() {
        int ch1, ch2;
        char string[50];

        printf("数字を2つ入力してください => ");
        /* 変数名の前には & をつける */
        scanf("%d%d", &ch1, &ch2);

	printf("なにか文字列を入力してください => ");
        /* 文字列の場合には、配列名だけをあたえる */
	scanf("%s", string);

        printf("入力された値は %d と %d でした。\n", ch1, ch2);
	printf("入力された文字列は %s でした。\n", string);
}

格納する変数の前には、"&" がついていることに注意する。 ただし、文字列を読み込む場合は、格納する配列名を引数として与える。 この"&"は、変数のアドレスを求める演算子であるが、 詳細については次の課題として取り上げる予定である。

数値を読み込む際の書式指定子には10進数として読み込む場合の"%d" 以外に "%o"(8進数として読み込み), "%x" (16進数として読み込み)も使用可能である。 これを使うと簡単な基数変換プログラムを次のように作ることができる。

/* kisu_henkan.c */
#include <stdio.h>
/* scanf を用いた 8, 10, 16進数で表現されたデータを別の基数へ変換 */

char *format[] = {
	"%o", "%d", "%x"
};

int main()
{
	int input, output, data;

	printf("8, 10, 16での基数変換を行います。\n");
	printf("入力の基数を選んでください。");
        printf("(8進数 = 0, 10進数 = 1, 16進数 = 2) -> ");
	scanf("%d", &input);

	printf("出力の基数を選んでください。");
        printf("(8進数 = 0, 10進数 = 1, 16進数 = 2) -> ");
	scanf("%d", &output);

	printf("変換するデータを入力してください。-> ");
	scanf(format[input], &data);

	printf(format[output], data);
	printf("\n");
}

問題 8

次のような数字当てプログラムを作成せよ。


なお、scanf関数は、書式で指定された内容と異なる入力が与えられた場合、 変換を行わないなど期待にそぐわないの結果を与えたることもある上、 格納先の変数の大きさの確認を行わない(特に文字列の場合)ので、 使用時には十分注意を払うこと。

ストリームに書式付で出力する fprintf と同様、 ストリームから書式付きで読み込を行う fscanf も存在する。 fprintf と同様、書式の前に FILE 型のポインタを第1引数として取る。


課題7 日程表 課題9

tacha@tack.fukui-med.ac.jp
$Id: kadai08.html,v 1.2 2008/06/13 01:46:36 tacha Exp tacha $