C言語の2次元配列について教えてください

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
かずや

C言語の2次元配列について教えてください

#1

投稿記事 by かずや » 10年前

初めまして、C言語を勉強中の者です。

今、配列について学んでいるところなのですが、多次元配列に格納してからそれを表示していくという問題に詰まっています。

行数と列数を入力し、下記のように表示したいのですが。。。

例1)入力:7 5

/1 /2 /3 /4 /5
20 21 22 23 /6
19 32 33 24 /7
18 31 34 25 /8
17 30 35 26 /9
16 29 28 27 10
15 14 13 12 11


例2)入力:4 6

/1 /2 /3 /4 /5 /6
16 17 18 19 20 /7
15 24 23 22 21 /8
14 13 12 11 10 /9

※ / はスペースです。


色々なやり方を知りたいので、どなたか教えて頂けたらと思います。
(出来たらメイン関数のみでお願い致します)

また、最後の表示の条件は、行数×列数で考えているのですがそれでも出来そうでしょうか?


よろしくお願いします!

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語の2次元配列について教えてください

#2

投稿記事 by みけCAT » 10年前

かずや さんが書きました:例1)入力:7 5

/1 /2 /3 /4 /5
20 21 22 23 /6
19 32 33 24 /7
18 31 34 25 /8
17 30 35 26 /9
16 29 28 27 10
15 14 13 12 11


例2)入力:4 6

/1 /2 /3 /4 /5 /6
16 17 18 19 20 /7
15 24 23 22 21 /8
14 13 12 11 10 /9

※ / はスペースです。
こういうことですね。

コード:

例1)
入力:7  5

  1   2   3   4   5
 20  21  22  23   6
 19  32  33  24   7
 18  31  34  25   8
 17  30  35  26   9
 16  29  28  27  10
 15  14  13  12  11

例2)
入力:4   6

   1   2   3   4   5   6
 16  17  18  19  20    7
 15  24  23  22  21    8
 14  13  12  11  10    9
数字の前のスペースの数の厳密なルール(法則、仕様)を教えて頂けますか?
かずや さんが書きました:また、最後の表示の条件は、行数×列数で考えているのですがそれでも出来そうでしょうか?
「最後の表示」とはなんですか?
オフトピック
「問題に詰まっています」と書いてあるし、大喜利に偽装した課題の丸投げだろうか…?
問題であっても課題とは限らないけど…
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: C言語の2次元配列について教えてください

#3

投稿記事 by かずま » 10年前

渦巻き状に番号を付けるだけですよね。

C では、行数と列数が与えられた後で、ちょうどそのサイズの2次元配列を確保する
ことはできないので、あらかじめ適当なサイズの2次元配列を用意しておいて、
その範囲内で配列の一部を使用するものとします。

コード:

#include <stdio.h>

#define N 20
 
int main(void)
{
    int a[N][N], row, col;

    while (printf("row col? "), scanf("%u%u", &row, &col) == 2
            && row > 0 && row <= N && col > 0 && col <= N) {
        int left = -1, top = 0, right = col-1, bottom = row-1;
        int i, j, k = 0, n = row * col;
        while (k < n) {
            for (j = ++left; j <= right; j++) a[top][j] = ++k;
            for (i = ++top; i <= bottom; i++) a[i][right] = ++k;
            if (k >= n) break;
            for (j = --right; j >= left; j--) a[bottom][j] = ++k;
            for (i = --bottom; i >= top; i--) a[i][left] = ++k;
        }
        for (i = 0; i < row; i++) {
            for (j = 0; j < col; j++) printf("%4d", a[i][j]);
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}
最後の表示とは、ループを抜ける条件のことですよね。

Aozora0630
記事: 85
登録日時: 10年前
住所: 日本
連絡を取る:

Re: C言語の2次元配列について教えてください

#4

投稿記事 by Aozora0630 » 10年前

>あらかじめ適当なサイズの2次元配列を用意しておいて

vector推し
別に二次元配列じゃなくてもいけると思うけど・・・。

コード:

#include <stdio.h>
#include <vector.h>

int main(){
   int x=0,y=0;//x = 横,y = 縦
   vector< vector<int> > result;
   
   do{
      printf("横の要素数を入力してください\n");
      scanf("%i",&x);
      printf("縦の要素数を入力してください\n");
      scanf("%i",&y);
   }while(x<=0&&y<=0);
   
   result.resize(x);
   for(int i=0;i<y;i++)result.at(i).resize(y);
   
   int ix = 0;int num = 0;
   for(int iy=0;iy<y;iy++){
      for(int i=0;i<x;i++){
         if(iy%2)ix--;
         num++;
         
         result[ix][iy] = num;
         
         if(iy%2==0)ix++;
      }
   }
   
   for(int ox=0;ox<x;ox++){
      for(int oy=0;oy<y;oy++)printf("%i ",result[oy][ox]);
      printf("\n");
   }
}
ふー。

因みに、スペースとかそういうのは調節してませんので・・・。
注意するのが、私の設計ミスで呼び出す時にresult[横][縦]になってしまったことです。
まあ、気にしない気にしない。

結果

コード:

横の要素数を入力してください
2
縦の要素数を入力してください
2
1 2 
4 3 
あ、C言語って書いてあるw
なら、vectorじゃなくて上の方の静的確保を使った方が良いかな?
改良↓

コード:

#include <stdio.h>
#include <vector.h>

int main(){
   int x=0,y=0;//x = 横,y = 縦
   int *result;
   
   do{
      printf("横の要素数を入力してください\n");
      scanf("%i",&x);
      printf("縦の要素数を入力してください\n");
      scanf("%i",&y);
   }while(x<=0&&y<=0);
   
   result = new int(x*y);
   
   int ix = 0;int num = 0;
   for(int iy=0;iy<y;iy++){
      for(int i=0;i<x;i++){
         if(iy%2)ix--;
         num++;
         
         result[iy*x+ix] = num;
         
         if(iy%2==0)ix++;
      }
   }
   
   for(int oy=0;oy<y;oy++){
      for(int ox=0;ox<x;ox++)printf("%i ",result[oy*x+ox]);
      printf("\n");
   }
   
   delete result;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語の2次元配列について教えてください

#5

投稿記事 by みけCAT » 10年前

スペースはとりあえずサンプルは通るようにしました。
バッファの各部分へのポインタを配列に持たせることで、二次元配列のような書き方でのアクセスが可能です。

コード:

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

int main(void) {
	int row, col;
	while (scanf("%d%d", &row, &col) == 2 && row > 0 && col > 0) {
		int *buffer, **array;
		int x, y, dx, dy, nx, ny, t, n, nmax;

		/* 二次元配列を確保 */
		buffer = (int*)malloc(sizeof(int) * (row * col));
		if (buffer == NULL) return 1;
		array = (int**)malloc(sizeof(int*) * row);
		if (array == NULL) {
			free(buffer);
			return 1;
		}
		for (y = 0; y < row; y++) array[y] = &buffer[col * y];

		/* 初期化 */
		for (y = 0; y < row; y++) {
			for (x = 0; x < col; x++) array[y][x] = 0;
		}

		/* データを作成 */
		y = x = 0;
		dx = 1; dy = 0;
		for (nmax = row * col, n = 1; n <= nmax; n++) {
			/* 埋める */
			array[y][x] = n;
			/* 次に進む */
			if (n < nmax) {
				nx = x + dx;
				ny = y + dy;
				while (ny < 0 || row <= ny || nx < 0 || col <= nx ||array[ny][nx] != 0) {
					/* 右に90度回転 */
					t = dx;
					dx = dy;
					dy = -t;
					/* 回転を反映させる */
					nx = x + dx;
					ny = y + dy;
				}
				y = ny;
				x = nx;
			}
		}

		/* 作成したデータを出力 */
		for (y = 0; y < row; y++) {
			for (x = 0; x < col; x++) {
				if (row == 4 && col == 6 && x == col - 1 && y > 0) {
					printf("%5d", array[y][x]);
				} else if (x > 0 || (row == 4 && col == 6 && array[y][x] == 1)) {
					printf("%4d", array[y][x]);
				} else {
					printf("%3d", array[y][x]);
				}
			}
			putchar('\n');
		}

		/* 二次元配列を開放 */
		free(buffer);
		free(array);

	}
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る