再利用可能なベクター型
サイズと容量をまとめて扱います。
「再利用可能なベクター型」はCoddyKit上の無料C Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。
ばらばらのコードから型へ
ポインター、要素数、容量を3つの別々の変数としてあちこちに渡す方法は、エラーの原因になります。
これらを1つのstructにまとめましょう。これは再利用可能な動的配列で、一般にベクターと呼ばれます。データと管理情報を一緒にまとめて扱えます。
ベクターのstruct
ベクターには3つのフィールドが必要です。データへのポインター、使用中の要素数(len)、そしてサイズ変更前に収容できる要素数(cap)です。
typedef struct {
int *data;
size_t len;
size_t cap;
} Vec;ベクターの初期化
空のベクターでは、データポインターがNULLで、長さと容量がともに0です。短いinit関数を用意すると、意図が明確になります。
void vec_init(Vec *v) {
v->data = NULL;
v->len = 0;
v->cap = 0;
}push操作
vec_pushは末尾に要素を1つ追加します。ベクターが満杯の場合は、先に容量を2倍にします。
成功時には0を返し、メモリ確保に失敗した場合は-1を返すため、呼び出し側で対処できます。
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp;
v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}要素を読み出す
lenが使用中の要素数を記録しているため、0からlen - 1まで反復します。容量のほうが大きい場合もありますが、そのスロットはまだデータの一部ではありません。
for (size_t i = 0; i < v->len; i++)
printf("%d\n", v->data[i]);ベクターの解放
ベクターはヒープバッファを所有しているため、それに対応する解放関数が必要です。解放後はフィールドをリセットし、structが誤って使われないようにします。
void vec_free(Vec *v) {
free(v->data);
v->data = NULL;
v->len = v->cap = 0;
}全体を組み立てる
この完全なプログラムでは、ベクターを作成し、5つの値を追加して表示した後、適切に解放します。
#include <stdio.h>
#include <stdlib.h>
typedef struct { int *data; size_t len, cap; } Vec;
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp; v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}
int main(void) {
Vec v = {0};
for (int i = 0; i < 5; i++) vec_push(&v, i * 10);
for (size_t i = 0; i < v.len; i++) printf("%d\n", v.data[i]);
free(v.data);
return 0;
}{0}によるゼロ初期化
Vec v = {0};と記述すると、データポインターをNULLにすることも含め、すべてのフィールドが0に設定されます。
これは便利な省略記法で、明示的なinit関数を呼び出さなくても、ベクターをvec_pushで使える状態にできます。
Vec v = {0}; /* data=NULL, len=0, cap=0 */
vec_push(&v, 42);安全なgetヘルパー
lenを超えた位置へのインデックスアクセスはバグです。小さなアクセサーで境界を確認し、エラーを通知できます。速度を少し犠牲にして安全性を高める方法です。
int vec_get(const Vec *v, size_t i, int *out) {
if (i >= v->len) return -1; /* out of range */
*out = v->data[i];
return 0;
}lenとcapを別々に管理する理由
capは確保済みのメモリ容量であり、lenは実際に使用している量です。
余分な容量を確保しておけば、ほとんどのpushでreallocを呼び出さずに済みます。この分離によって、ベクターは高速かつ柔軟になります。
型を一般化する
このベクターはintを格納します。他の型を格納するには、要素型を変更するか、要素サイズとともにvoid *を格納します。
格納するものが何であっても、パターン、init、push、freeは変わりません。
typedef struct {
double *data;
size_t len, cap;
} DVec; /* same shape, different element type */クイックチェック
ベクター型についての理解度を確認しましょう。
まとめ
ベクターは、データポインター、len、capを1つのstructにまとめます。
満杯になるとvec_pushは容量を2倍にし、vec_freeはバッファを解放してフィールドをリセットします。また、{0}で適切に初期化できます。この再利用可能なパターンは、ばらばらの変数を個別に管理するより優れています。次は、正しく解放してリークを避ける方法です。
よくある質問
「再利用可能なベクター型」レッスンは無料ですか?
はい。「再利用可能なベクター型」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。
「再利用可能なベクター型」で何を学びますか?
サイズと容量をまとめて扱います。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「再利用可能なベクター型」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC Academyレッスンでコードを書いて実行できますか?
はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 配列を確保する
- reallocで拡張する
- 再利用可能なベクター型
- 解放してリークを防ぐ