自動拡張する配列

GLibには自動拡張する配列があります。要素の追加、削除が容易に行えます。

GArray

#include <glib.h>
typedef struct {
  gchar *data;
  guint len;
} GArray;
GArray* g_array_new(gboolean zero_terminated, gboolean clear_, guint element_size);
#define g_array_append_val(a,v)
#define g_array_prepend_val(a,v)
#define g_array_insert_val(a,i,v)
#define g_array_index(a,t,i)
GArray* g_array_remove_index(GArray *array, guint index_);
gchar* g_array_free(GArray *array, gboolean free_segment);

GArrayでは、データを追加する際に複製したものが追加されます。
なお、GArray->dataは、要素を追加した際にアドレスが変わる可能性があるので注意しましょう。

GArray* g_array_new(gboolean zero_terminated, gboolean clear_, guint element_size);
  • 新しいGArrayを返します
  • zero_terminatedをTRUEにすると、配列の最後に0が追加されます
  • clear_をTRUEにすると、配列が0で初期化されます
  • element_sizeは、配列に格納する要素の型の大きさです
#define g_array_append_val(a,v)
#define g_array_prepend_val(a,v)
#define g_array_insert_val(a,i,v)
#define g_array_index(a,t,i)
  • aは操作を行うGArrayへのポインタです
  • vは追加するデータです。実際の呼び出しは&(v)となっているので、vは変数でないといけません
  • tはGArrayに格納されているデータの型です
  • iは添字です
  • g_array_append_val()は配列の最後に要素を追加し、g_array_prepend_val()は配列の先頭に要素を追加します
  • g_array_insert_val(a,i,v)は指定された添字の場所に要素を挿入します
  • g_array_index()は指定された添字の要素を返します
GArray* g_array_remove_index(GArray *array, guint index_);

arrayからindex_にある要素を削除します。index_よりも後ろにある要素は前にずれることに注意してください。

gchar* g_array_free(GArray *array, gboolean free_segment);

arrayを解放します。free_segmentをTRUEにすると、array->dataも解放します。

使い方
#include <glib.h>
#include <stdio.h>

int main() {
  GArray *garray;
  int a=100,b=120,c=130,d=140,i;

  garray=g_array_new(FALSE,FALSE,sizeof(int));
  g_array_append_val(garray,a);
  g_array_append_val(garray,b);
  g_array_prepend_val(garray,c);
  g_array_insert_val(garray,1,d);
  for (i=0;i<garray->len;i++) {
    printf("%d\n",g_array_index(garray,int,i));
  }
  g_array_free(garray,TRUE);
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`
実行結果
130
140
100
120

GPtrArray

#include <glib.h>
typedef struct {
  gpointer *pdata;
  guint     len;
} GPtrArray;
GPtrArray* g_ptr_array_new(void);
void g_ptr_array_add(GPtrArray *array, gpointer data);
#define g_ptr_array_index(array,index_)
gpointer g_ptr_array_remove_index(GPtrArray *array, guint index_);
gpointer* g_ptr_array_free(GPtrArray *array, gboolean free_seg);

GPtrArrayはポインタを格納する配列です。GArrayよりも関数が分かり易いですね。ただし、GArrayのように要素の挿入はできません。
GPtrArray->pdataも、要素を追加した際にアドレスが変わる可能性があるので注意しましょう。

使い方
#include <glib.h>
#include <stdio.h>

int main() {
  GPtrArray *gparray;
  int i;

  gparray=g_ptr_array_new();
  g_ptr_array_add(gparray,"aaa");
  g_ptr_array_add(gparray,"bbb");
  g_ptr_array_add(gparray,"ccc");
  for (i=0;i<gparray->len;i++) {
    printf("%s\n",g_ptr_array_index(gparray,i));
  }
  g_ptr_array_free(gparray,TRUE);
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`
実行結果
aaa
bbb
ccc

GByteArray

#include <glib.h>
typedef struct {
  guint8 *data;
  guint   len;
} GByteArray;
GByteArray* g_byte_array_new(void);
GByteArray* g_byte_array_append(GByteArray *array, const guint8 *data, guint len);
GByteArray* g_byte_array_prepend(GByteArray *array, const guint8 *data, guint len);
GByteArray* g_byte_array_remove_index(GByteArray *array, guint index_);
guint8* g_byte_array_free(GByteArray *array, gboolean free_segment);

GByteArrayは、配列にバイト単位のデータを追加していきます。追加の際には複製されたものが追加されます。
GByteArray->dataも要素を追加した際にアドレスが変わる可能性があるので注意しましょう。

使い方
#include <glib.h>
#include <stdio.h>

int main() {
  GByteArray *gbarray;
  int i;

  gbarray=g_byte_array_new();
  g_byte_array_append(gbarray,(guint8*)"aaa",3);
  g_byte_array_append(gbarray,(guint8*)"bb",2);
  g_byte_array_prepend(gbarray,(guint8*)"cccc",4);
  for (i=0;i<gbarray->len;i++) {
    printf("%c",gbarray->data[i]);
  }
  printf("\n");
  g_byte_array_free(gbarray,TRUE);
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`
実行結果
ccccaaabb