配列の可変長さについてのC言語:初心者向けガイド
こんにちは、未来のプログラマーたち!今日は、C言語における可変長配列(Variable Length Arrays、以下VLA)の世界に楽しく飛び込みます。プログラミングが初めてであっても心配しないでください。私はあなたの親切なガイドとして、すべてをステップバイステップで説明します。それでは、始めましょう!
可変長配列とは?
まず、可変長配列とは何かを理解しましょう。パーティを計画しているとしますが、どれくらいのゲストが来るか分かりません。ゲストの人数に応じて魔法のようにサイズを調整できるテーブルがあれば素晴らしいでしょう。プログラミングにおけるVLAはまさにそのようなものです!
可変長配列は、そのサイズが実行時(プログラムが動作している時)で決定される配列で、コンパイル時(プログラムが実行準備される時)では決定されません。この機能はC99標準で導入され、配列の作成に柔軟性をもたらします。
可変長配列の作成
簡単な例でVLAを作成してみましょう:
#include <stdio.h>
int main() {
int n;
printf("どれだけの数を保存したいですか? ");
scanf("%d", &n);
int numbers[n]; // これは私たちの可変長配列です
printf("%d個の数を入力してください:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &numbers[i]);
}
printf("あなたが入力したのは: ");
for (int i = 0; i < n; i++) {
printf("%d ", numbers[i]);
}
return 0;
}
これを分解すると:
- ユーザーに保存したい数の個数を尋ねます。
- ユーザーの入力したサイズ
n
の配列numbers
を作成します。 - ループを使用して
n
個の数をユーザーから入力します。 - 最後に、ユーザーが入力したすべての数を表示します。
これがVLAの美しいところです。コードを書いている際に配列のサイズを知る必要はありません。サイズはプログラムが実行されたときに決定されます!
二次元可変長配列
次に、レベルアップして二次元VLAを見てみましょう。ウェディングの席の配置を考えているとしますが、どれくらいのテーブルがあって、各テーブルにどれくらいの席があるか分かりません。二次元VLAが役立ちます!
以下はその例です:
#include <stdio.h>
int main() {
int tables, seats;
printf("どれだけのテーブルがありますか? ");
scanf("%d", &tables);
printf("各テーブルにどれだけの席がありますか? ");
scanf("%d", &seats);
int seating[tables][seats]; // 私たちの2D可変長配列
// 席の番号を割り当てる
for (int i = 0; i < tables; i++) {
for (int j = 0; j < seats; j++) {
seating[i][j] = i * seats + j + 1;
}
}
// 席の配置を表示する
printf("\n席の配置:\n");
for (int i = 0; i < tables; i++) {
printf("テーブル %d: ", i + 1);
for (int j = 0; j < seats; j++) {
printf("%3d ", seating[i][j]);
}
printf("\n");
}
return 0;
}
この例では:
- ユーザーにテーブルの数と各テーブルの席の数を尋ねます。
- サイズが
[tables][seats]
の2D VLAseating
を作成します。 - 席の番号を各位置に割り当てます。
- 最後に、席の配置を表示します。
この柔軟性により、実行時に決定される任意のサイズの席の配置を作成できます!
ジャグジー配列
さて、もっと面白いところに進みましょう。ウェディングの各テーブルが異なる数の席を持っている場合を考えます。そこで登場するのがジャグジー配列です。各サブ配列が異なる長さを持つ配列です。
C言語はジャグジー配列を直接サポートしていませんが、VLAとポインタを使用してシミュレートできます。以下はその方法です:
#include <stdio.h>
#include <stdlib.h>
int main() {
int tables;
printf("どれだけのテーブルがありますか? ");
scanf("%d", &tables);
int *seats = malloc(tables * sizeof(int));
int **seating = malloc(tables * sizeof(int*));
// 各テーブルの席の数を入力する
for (int i = 0; i < tables; i++) {
printf("テーブル %d にどれだけの席がありますか? ", i + 1);
scanf("%d", &seats[i]);
seating[i] = malloc(seats[i] * sizeof(int));
}
// 席の番号を割り当てる
for (int i = 0; i < tables; i++) {
for (int j = 0; j < seats[i]; j++) {
seating[i][j] = j + 1;
}
}
// 席の配置を表示する
printf("\n席の配置:\n");
for (int i = 0; i < tables; i++) {
printf("テーブル %d: ", i + 1);
for (int j = 0; j < seats[i]; j++) {
printf("%3d ", seating[i][j]);
}
printf("\n");
}
// 配割り当てたメモリを解放する
for (int i = 0; i < tables; i++) {
free(seating[i]);
}
free(seating);
free(seats);
return 0;
}
この例は少し複雑ですが、以下を分解すると:
- テーブルの数の配列
seats
を作成し、各テーブルの席の数を格納します。 - ポインタの配列
seating
を作成してジャグジー配列をシミュレートします。 - 各テーブルに応じてメモリを動的に割り当てます。
- 席の番号を割り当て、配置を表示します。
- 最後に、割り当てたメモリを解放します。
このアプローチにより、各テーブルが異なる数の席を持つことができます。非常に柔軟です!
メソッドの表
ここで使用したメソッドの簡単な参照表を示します:
メソッド | 説明 | 例 |
---|---|---|
scanf() |
ユーザーからの形式された入力を読み取る | scanf("%d", &n); |
printf() |
コンソールに形式された出力を表示する | printf("Hello, %s!", name); |
malloc() |
動的にメモリを割り当てる | int *arr = malloc(n * sizeof(int)); |
free() |
動的に割り当てたメモリを解放する | free(arr); |
力には責任が伴います。VLAと動的メモリ割り当ては強力なツールですが、スタックオーバーフローやメモリリークを避けるために注意深く使用する必要があります。
そして、ここまででC言語の可変長配列についての初めてのステップを踏み出しました。実践が大事ですので、これらの概念を試してみてください。ハッピーコーディング!
Credits: Image by storyset