第五回(配列)


配列

配列とは同じ型の変数をたくさん扱うことができるようになるものです。
書き方は型名 変数名[配列の数];です。例としては、int a[100];です。これで100個の配列がとれます。
しかし、重要なこととしてこれはa[1]、a[2]、…、a[100]までの配列がとれたわけではありません。 配列は0番目から数えます。つまり、int a[100];と宣言しているので、a[0]、a[1]、…、a[99] までの配列がとれたことになります。ちなみに、[数字]←これのことを添え字と呼びます。

では、配列を使った例を見てみましょう。

サンプルソース
#include<stdio.h>
#include<stdlib.h>

#define MAX 20

int main(void);

int main(void){
	
	int i, array[MAX];
	
	for(i = 0; i < MAX; i++){
		array[i] = (i + 1) * (i + 1);
	}
	
	for(i = 0; i < MAX; i++){
		printf("%d : %d\n", i + 1, array[i]);
	}
	
	return(0);
}
実行結果
1 : 1
2 : 4
3 : 9
4 : 16
5 : 25
6 : 36
7 : 49
8 : 64
9 : 81
10 : 100
11 : 121
12 : 144
13 : 169
14 : 196
15 : 225
16 : 256
17 : 289
18 : 324
19 : 361
20 : 400

このプログラムは配列arrayを20個(0〜19番目まで)用意して、forでiが0番目から19番目までの間、その中に変数i + 1とi + 1をかけた数(i + 1の二乗)を 代入しながらi++していって、その処理後に再びforでiが0番目から19番目まで繰り返しながら、配列の中身を表示しています。

配列の初期化

配列の初期化は{0}と書くことで、配列すべてを初期化することができます。例としてはint array[10] = {0};で10個すべて初期化できます。

配列は添え字の数字を調整することでうまく計算することや、表示することができて便利です。以下に配列の添え字を用いて計算をした例を 用意してみました。

サンプルソース
#include<stdio.h>

#define MAX 30

int main(void);

int main(void){
	
	int i, array[MAX] = {0};
	
	for(i = 0; i < MAX; i++){
		array[i] = i;
		if(i != 0){
			array[i] += array[i - 1];
		}
	}
	
	for(i = 0; i < MAX; i++){
		printf("%d : %d\n", i, array[i]);
	}
	
	return(0);
}
実行結果
0 : 0
1 : 1
2 : 3
3 : 6
4 : 10
5 : 15
6 : 21
7 : 28
8 : 36
9 : 45
10 : 55
11 : 66
12 : 78
13 : 91
14 : 105
15 : 120
16 : 136
17 : 153
18 : 171
19 : 190
20 : 210
21 : 231
22 : 253
23 : 276
24 : 300
25 : 325
26 : 351
27 : 378
28 : 406
29 : 435

文字列(文字の配列)

文字列は今までもよく扱ってきました。C言語では正確には文字列とは終端にヌル文字の入った文字の配列のことを言います。 使い方はchar str[256];で256個の文字型の変数になりました。
つまり、これは0番目〜255番目までの文字を入れることのできる変数を宣言しています。

文字列の初期化

文字列では宣言の段階でのみ、好きな文字列を代入することができます。つまり、char str[100] = "RCC";はできますが 宣言後にstr[100] = "RCC";とはできません。
宣言後に代入する場合はstrcpy関数、またはstrncpy関数を使います。(後述の文字列処理関数のところで説明します。)

ヌル文字(終端文字)

ヌル文字とは終端を表す文字のことです。\0と書きますが、\nのように実際には表示されません。
fgets関数では1行の文字列を返してくれる関数なので、問題はありませんが、getchar関数では1文字を返す関数なので、 そうはいきません。まずは間違った例を見てみましょう。

サンプルソース
#include<stdio.h>

#define MAX 100

int main(void);

int main(void){
	
	int i = 0;
	char c_array[MAX];
	
	while((c_array[i] = getchar()) != '\n'){
		i++;
	}
	
	printf("[%s]", c_array);
	return(0);
}
実行結果

このように文字の終端がわからないので、変な文字が入ってしまいます。これを防ぐには、文字列を初期化するのがいいです。文字列を初期化すると、 一見すると、0が代入されたように見えますが、実は文字列すべてに\0を代入しています。では正しいプログラムと実行結果も見てみましょう。

サンプルソース
#include<stdio.h>

#define MAX 100

int main(void);

int main(void){
	
	int i = 0;
	char c_array[MAX] = {0};
	
	while((c_array[i] = getchar()) != '\n'){
		i++;
	}
	
	printf("[%s]\n", c_array);
	return(0);
}
実行結果

文字列向けの関数

文字列処理時に使うことになる関数を説明します。ヘッダファイルとしてはすべて#include<string.h>を用います。

strcat(strncat)

strcat関数は文字列の末尾に文字列を連結する関数です。形はstrcat(文字列A, 文字列B);です。これで、文字列Aの末尾に文字列Bが連結されます。
strncat関数の形はstrncpy(文字列A, 文字列B, 数字);です。文字列A、文字列Bについては同じようなものですが、 最後の数字は文字列Bからその数字分だけ連結するという意味を含んでいます。つまり、3と入っていた場合、文字列Bから最初の3文字のみ連結ということです。 以下にstrcpyと、strncpyの両方の例を示します。

strcatのサンプルソース
#include<stdio.h>
#include<string.h>

#define MAX 256

int main(void);

int main(void){
	
	char string[MAX] = "RCC";
	
	printf("%s\n", string);
	
	strcat(string, "にょろ");
	
	printf("%s\n", string);
	
	return(0);
}
実行結果
RCC
RCCにょろ
strncatのサンプルソース
#include<stdio.h>
#include<string.h>

#define MAX 256

int main(void);

int main(void){
	
	char string[MAX] = "RCC";
	
	printf("%s\n", string);
	
	strncat(string, "にょろ123", 6);
	
	printf("%s\n", string);
	
	return(0);
}
実行結果
RCC
RCCにょろ

※ひらがな、全角カタカナ、漢字等は1文字で配列2つ分を使うので、ひらがな3文字で配列が6つ必要なわけです。

strlen

strlen関数は文字列の長さ(文字数)を返す関数です。また、これで返ってくる文字数はヌル文字(\0)を含みません。例を見てみましょう。

サンプルソース
#include<stdio.h>
#include<string.h>

#define MAX 256

int main(void);

int main(void){
	
	int length;
	char string[MAX] = {0};
	
	fgets(string, MAX, stdin);
	
	length = strlen(string);
	
	printf("%sの長さは%dです。", string, length);
	return(0);
}
実行結果
RCC
RCC
の長さは4です。

これはRCC(\n)と入っているので、4で正しいです。

strcpy(strncpy)

strcpyは文字列をコピーする関数です。形式はstrcpy(文字列A, 文字列B);です。文字列Bを文字列Aにコピーします。
strncpyはstrncatと同様、文字数を指定できます。形式としてはstrncpy(文字列A, 文字列B, 数字);です。これで、文字数Bのうちのコピーする 文字数が指定できます。例をみてみましょう。

strcpyのサンプルソース
#include<stdio.h>
#include<string.h>

#define MAX 256

int main(void);

int main(void){
	
	char strA[MAX] = "カレーパン", strB[MAX] = "メロン";
	
	printf("%s\n", strA);
	
	strcpy(strA, strB);
	
	printf("%s\n", strA);
	return(0);
}
実行結果
カレーパン
メロン
strncpyのサンプルソース
#include<stdio.h>
#include<string.h>

#define MAX 256

int main(void);

int main(void){
	
	char strA[MAX] = "カレーパン", strB[MAX] = "メロン";
	
	printf("%s\n", strA);
	
	strncpy(strA, strB, 6);
	
	printf("%s\n", strA);
	return(0);
}
実行結果
カレーパン
メロンパン

多次元配列

多次元配列とは今までのように一次元の配列以外を言います。二次元配列や三次元配列のことです。
書き方は単純で、int array[100][100];、char s_array[256][256][256];のようにすることができます。
二次元配列の初期化はこのようにします。

実行結果
変数名[A][B] = {
	{Aの数字分の初期化},
	{Bの数字分の初期化}
};
以下に二次元配列の例として、二行二列の行列の和を求めるプログラムを用意しました。

サンプルソース
#include<stdio.h>

#define MAX 2

int main(void);
void Matrix(int matrix[MAX][MAX]);
void sum_matrix(int mA[MAX][MAX], int mB[MAX][MAX]);

int matrixC[MAX][MAX];

int main(void){
	
	int matrixA[MAX][MAX] = {
		{0, 1},
		{2, 3}
	};
	int matrixB[MAX][MAX] = {
		{3, 2},
		{1, 0}
	};
	
	Matrix(matrixA);
	
	printf("+\n");
	
	Matrix(matrixB);
	sum_matrix(matrixA, matrixB);
	
	printf("=\n");
	
	Matrix(matrixC);
	
	return(0);
}

void Matrix(int matrix[MAX][MAX]){
	int i, j;
	
	for(i = 0; i < MAX; i++){
		for(j = 0; j < MAX; j++){
			printf("%d ", matrix[i][j]);
		}
		printf("\n");
	}
}

void sum_matrix(int mA[MAX][MAX], int mB[MAX][MAX]){
	int i, j;
	
	for(i = 0; i < MAX; i++){
		for(j = 0; j < MAX; j++){
			matrixC[i][j] = mA[i][j] + mB[i][j];
		}
	}
}
実行結果
0 1
2 3
+
3 2
1 0
=
3 3
3 3

基本問題

フィボナッチ数列を好きな番目まで配列に格納して表示するプログラムを作成してください。 (フィボナッチ数列とは、1番目は0、2番目は1で3番目は1番目と2番目の和、4番目は2番目と3番目の和というものが無限に続いていく数字の列のことです。)

例:0、1、1、2、3、5、8、13、21、34、55、89、144、…

応用問題

小数点も扱うことのできる二行二列の行列の積を求めて標準出力するプログラムを作成してください。行列の数字は標準入力から取得しても、初期化で先に入れておいてもいいものとします。

次回予告

次回は構造体について説明します。

戻る