C言語でappend

1 min read読了の目安(約1600字

やりたいこと

C++では.push_back、Pythonではappendと配列のお尻にあたらしく要素を追加する方法があります。とても便利ですが、C言語の場合は自分で作る必要があります。
授業とかで必要になりそうだったので適当にでっちあげたので備忘録&共有。

配列の大きさを知る

いわゆる動的確保なので、sizeof(a)/sizeof(a[0])みたいな方法は使えません。
myVectorなる構造体を定義して、確保した数を管理するための変数を用意しました。
配列自体はdouble以外で使う予定はなかったので適当に宣言しておきます。

typedef struct 
{
    double* data;
    size_t size;
} myVector;

配列の確保

構造体変数を宣言したあとに

myVector a;
allocateMemory(&a, 10);

みたいに最初の割当をしたいので、この関数を作ります。

// a:配列の構造体 size:確保したい数
int allocateMemory(myVector* v, int size)
{
    v->data = (double *)calloc(size, sizeof(double));
    v->size = size;
    
    if(v->data == NULL)
    {
        return -1;
    }    
    return 0;
}

配列を継ぎ足す

本題の部分です。一度別の配列にdataの中身を退避させておき、dataをfreeしてしまいます。sizeを+1して、再度dataをsizeを使ってmallocすることでdataの要素数が1つ増えた配列を作り直します。最後にtmpからデータを戻して、最後にappendしたいデータを入れてあげて終わりです。tmpもmallocすることになるので開放してあげることを忘れないようにしましょう。memcpy... 知らない子ですね...~

int append(cVectorD* v, double n)
{
    // 一時的に配列の値を保存しておく
    double* tmp = (double *)malloc(sizeof(double) * v->size);
    if(tmp == NULL) return -1;
    
    for(int i = 0; i < v->size; i++)
    {
        tmp[i] = v->data[i];
    }

    // 確保してあったメモリを開放
    free(v->data);

    // v->sizeに1足す
    v->size ++;

    // v->size個メモリを新たに確保
    v->data = (double *)malloc(sizeof(double) * (v->size));
    if(v->data == NULL) return -1;

    // tmpのデータを入れて
    for(int i = 0; i < v->size - 1; i++)
    {
        v->data[i] = tmp[i];
    }
    // 最後の要素に追加したい値を入れる
    v->data[v->size-1] = n;
    //printf("vsize %d\n", v->size);

    free(tmp); //tmpはもう使わないので開放
    return 0;
}

さいごに

開放してくれるやつです

void freeMemory(cVectorD* v)
{
    free(v->data);
    v->size = 0;
}