25章 多次元配列

http://www.geocities.jp/ky_webid/c/025.html

配列の配列ですか。ややこしそうですね。

でも一次元配列の応用なので注意深く見ていけばそれ程迷うことは無いと思います。

問題1

二次元配列に九九の結果を格納し、それを表示するプログラムを作って下さい。ただし宣言時の初期化を使ってはいけません。

二次元配列の基本問題ですね。

int main () {
    int array[9][9];
    int i,j;
    
    for ( i=0; i<9; i++ ) {
        for ( j=0; j<9; j++ ) {
            array[i][j] = (i+1) * (j+1);
            printf("%02d ",array[i][j]);
        }
        printf("\n");
    }
    return 0;
}
01 02 03 04 05 06 07 08 09
02 04 06 08 10 12 14 16 18
03 06 09 12 15 18 21 24 27
04 08 12 16 20 24 28 32 36
05 10 15 20 25 30 35 40 45
06 12 18 24 30 36 42 48 54
07 14 21 28 35 42 49 56 63
08 16 24 32 40 48 56 64 72
09 18 27 36 45 54 63 72 81

こう、キレイに表示されるとなんだか気持ち良いですねぇ。

問題2

4列4行の二次元配列を作り、[0][0]〜[2][2]の9要素分の領域に適当な数値を代入します。各行と各列の最後の要素([0][3]、[1][3]、[2][3]、[3][0]、[3][1]、[3][2])には、その行や列の合計値を代入して下さい。さらに、[3][3]には全体の合計値を代入して下さい。それを表示させて下さい。つまり、例えば次のようになります。

 8  6  3 17
10  9  2 21
 3  0  7 10
21 15 12 48

っんじゃこりゃ。かなり難しそうですね。頑張ってみます。

int main () {
    int array[4][4] = {
        {8,6,3},
        {10,9,2},
        {3,0,7},
    };
    int i,j;
    
    array[3][3] = 0;
    for(i=0;i<3;i++) {
        array[i][3] = 0;
        array[3][i] = 0;
        for(j=0;j<3;j++) {
            array[i][3] += array[i][j];
            array[3][i] += array[j][i];
        }
        array[3][3] += array[3][i];
    }
    
    for(i=0;i<4;i++) {
        for(j=0;j<4;j++) {
            printf("%3d ",array[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

結構時間かかりました。何度も書き直しながら実行し、完成しました。

自分で言うのは何ですが、かなりうまく実装できたと思います。

答え合わせ

やっぱり一回ずつループ分けて計算してますね。僕も最初これでやろうと思ったんですが、何とか一度のループでできないかと無理やりやっちゃったわけです。

ただ気になるのが、合計値の要素を0で初期化しなくても動いてるというところでしょうか。

宣言時の初期化では、初期値を与えなかった部分には自動的に0が入る点に注目です。

なるほど。これは便利ですね。覚えておきましょう。

問題3

キーボードから入力された80文字までの文字列を、10個まで記憶します。途中で今までに入力した文字列と同じ文字列があったら、そのことをメッセージとして表示してプログラムを終了させるようにして下さい。途中で入力を中止するときは、空の文字列を入力するものとします。10個入力後、あるいは空文字列入力後に、今まで入力された文字列を全て表示して下さい。

色々習ったことが混ざってる問題ですね。

やってみましょう。

int main () {
    char str[10][81];
    int i,j;
    
    for(i=0;i<10;++i){
        scanf("%80s",str[i]);
        if ( strcmp(str[i],"0") == 0 ) {
            printf("0なので中断します\n");
            break;
        }
        for(j=0;j<i;++j){
            if ( strcmp(str[j],str[i]) == 0 ) {
                printf("同じ文字列なので終了します\n");
                return 0;
            }
        }
    }
    
    printf("入力された文字列\n");
    for(j=0;j<i;++j) {
        printf("%s\n",str[j]);
    }
    
    return 0;
}

できました。ただし空文字かどうかを検出できなかったので0を変わりに使っています。

どうやれば空文字と入力されたかを取れるんですかね。

答え合わせ

実装を見てると、scanfの戻り値が-1かどうかで空文字かどうかを判断できるみたいです。

実際に試してみたところ、やっぱりうまくいきませんでした。

何が問題なんでしょうか・・・。