C言語で行列を扱うには?

C言語で行列を扱うためのデータ構造と、関数へ受け渡す方法についてのメモです。

1次元配列の受け渡し例

配列を関数に渡す場合、配列の先頭アドレスだけでなく、要素の個数も渡す必要があります。また配列の要素数はconstで宣言しなければなりません。

#include <stdio.h>
void reset(int x[],int N){
	int i;
	for(i=0;i<N;i++) x[i]=0;
}
int main(){
	const int N=5;//constがないとcompile error
	int i;
	int a[N]={2,4,8,1,5};
	reset(a,N);
	for(i=0;i<N;i++) printf("%d ",a[i]);
	return 0;
}

0 0 0 0 0

2次元配列の受け渡し

通常の二次元配列の情報を関数に渡すためのひな形です。列数を具体的な数値で指定しなければならないので少し使い辛い形になってしまいます。

#include <stdio.h>
#define Mmax 3
void view(int x[][Mmax],int Nmax){
	int i,j;
	for(i=0;i<Nmax;i++){
		for(j=0;j<Mmax;j++) printf("%d ",x[i][j]);
		printf("\n");
	}
	printf("\n");
}
int main(){
	const int Nmax=2;
	int a[Nmax][Mmax]={
		{2,4,3},
		{8,1,7}
	};
	view(a,Nmax);
	return 0;
}

2 4 3
8 1 7

動的1次元配列を利用した2次元配列の受け渡し

行列の要素を1次元配列に格納して扱う場合の例です。サイズを自由に設定することができます。(i,j)要素には[Col*i+j]でアクセスすることができます。

#include <stdio.h>
#include <stdlib.h>
void print(int* A,int N,int M){
	int i,j;
	for(i = 0;i < N;i++){
		for(j = 0;j < M;j++) printf("%d ", A[M*i+j]);
		printf("\n");
	}
	printf("\n");
}
int main()
{
	const int N=2;
	const int M=3;
	int i,j;

	//int*型N*M個分の領域確保
	int* A = (int*)malloc( N*M*sizeof(int) );
	if(A == NULL){
		return 1;
	}
	for(i = 0; i < N; i++){
		for(j = 0; j < M;j++) A[M*i+j] = i+j;
	}
	print(A,N,M);
	
	free(A);
	return 0;
}

0 1 2
1 2 3
2 3 4

ダブルポインタを利用した2次元配列の受け渡し

上の例と同様サイズを自由に設定することができます。まずint*型の領域をN個確保して、それぞれのアドレスにint型の領域をM個確保します。(i,j)要素へのアクセスは[i][j]と書くことができるのでとても扱いやすいです。

#include <stdio.h>
#include <stdlib.h>
void print(int** A,int N,int M){
	int i,j;
	for(i = 0;i < N; i++){
		for(j = 0;j < M; j++) printf("%d ", A[i][j]);
		printf("\n");
	}
	printf("\n");
}
int main()
{
	//N*M行列
	const int N=2;
	const int M=3;
	int i,j;
	//int*型N個分の領域確保
	int** A = (int**)malloc( N * sizeof(int*) );
	if(A == NULL){
		return 1;
	}
	for(i = 0;i < N; i++){
		//各アドレスにおいてint型M個分の領域確保
		A[i] = (int*)malloc( M * sizeof(int) );	
		if(A[i] == NULL){
			for(j = i-1;j >=0; j--){
				free(A[j]);
			}
			return 1;
		}
		for(j = 0;j < M; j++){
			A[i][j] = i*j;
		}
	}
	print(A,N,M);

	for(i = 0;i < N;i++) free(A[i]);
	free(A);
	return 0;
}

0 0 0
0 1 2
関連:C言語で作る添え字フリーなベクトル&行列 - white wheelsのメモ