配列の動的追加

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
BlueRose
記事: 10
登録日時: 6年前

配列の動的追加

#1

投稿記事 by BlueRose » 6年前

以下の配列

コード:

  int list[10] = {1, 0, 6};
の残りの要素(7つ)に新たに入力していく要素を動的に追加したいのですが、以下のプログラムからどのように変更すれば良いでしょうか。
要素数0から次々追加させることはできますが、途中の追加ができません。
以下のプログラムは、ひとまず既存の配列の要素を表示させるデバッグ仕様となっています。

コード:

#include <stdio.h>
#include <stdlib.h>

/* セルの定義 */
struct Cell{
  struct Cell *prev; //先頭のセル
  struct Cell *next; //次のセル
  int data; //データ
};
/* セルのリスト定義 */
struct CellList {
  struct Cell *header; //先頭の要素
  struct Cell *tail; //末尾の要素
  int len; //リストの要素数
};

/* プロトタイプ宣言 */
void initList(struct CellList *cellList);
void addList(struct CellList *cellList, int data);
void deleteLastData(struct CellList *cellList);
void dump(struct CellList *cellList);
int isListEmpty(struct CellList *cellList);

/* リストの初期化 */
void initList(struct CellList *cellList) {
  if (cellList == NULL) {
    printf("[ERR]#initList list is empty\n");
    return;
  }
  cellList->header = cellList->tail = NULL;
  cellList->len = 0;
}

/* データをリストに追加 */
void addList(struct CellList *cellList, int data){
  struct Cell *cell;
  cell = (struct Cell *)malloc(sizeof(struct Cell));
    /* データを記憶するための記憶領域を malloc で確保し、
      その領域へのポインタを cell に代入する */
  cell->data = data;
  cell->next = NULL;

  if (isListEmpty(cellList)) {
    cell->prev = NULL;
    cellList->len = 1;
    cellList->header = cellList->tail = cell;
    return;
  }
  cellList->tail->next = cell;
  cell->prev = cellList->tail;
  cellList->tail = cell;
  cellList->len++;
}

/* 末尾のデータをリストから削除 */
void deleteLastData(struct CellList *cellList) {
  if (isListEmpty(cellList)) {
    printf("[ERR]#deleteLastData list is empty\n");
    return;
  }
  // 要素1つの場合
  if (cellList->len == 1 || cellList->tail == cellList->header) {
    free(cellList->tail);
    cellList->tail = cellList->header = NULL;
    cellList->len = 0;
    return;
  }
  cellList->tail = cellList->tail->prev;
  free(cellList->tail->next);
  cellList->tail->next = NULL;
  cellList->len--;
}

/*
リストが空ならTrue、そうでないならFalseを返す
*/
int isListEmpty(struct CellList *cellList) {
  return cellList == NULL || cellList->len == 0 || cellList->header == NULL || cellList->tail == NULL;
}

/* 全レコード表示 */
void dump(struct CellList *cellList){
  if (isListEmpty(cellList)) {
    printf("[ERR]#dump list is empty\n");
    return;
  }
  struct Cell *cell = cellList->header;
  printf("==========dump List========\n");
  while(cell != NULL) {
    printf("%d, ", cell->data);
    cell = cell->next;
  };
  printf("\n===========================\n");
  printf("dump List is %d\n", cellList->len);
}


/* メイン処理 */
int main(){
  struct CellList cellList;
  initList(&cellList);

  int list[10] = {1, 0, 6};
  // 空判定テスト
  deleteLastData(&cellList);

  int i;
  for (i = 0; i < sizeof(list)/sizeof(list[i]); i++) {
    addList(&cellList, list[i]);
  }
  dump(&cellList);
  for (i = 0; i < sizeof(list)/sizeof(list[i]); i++) {
    deleteLastData(&cellList);
  }
  dump(&cellList);
  return 0;
}

かずま

Re: 配列の動的追加

#2

投稿記事 by かずま » 6年前

回答が付かないのは、質問に問題があるためだと思います。

件名の「配列の動的追加」は、質問の本文から
「配列の要素の動的追加」だと分かります。
しかし、提示されたプログラムは、配列ではなく、
「連結リストの要素の動的追加」になっています。

C や C++ では、配列のサイズは、宣言時に固定され、要素を動的に
追加することはできません。

int a[10] = { 1, 0, 6 }; と宣言したら、a[3]~a[9] も 0 に初期化されます。

C で動的にメモリを確保するためには malloc を使用し、これによって、
動的配列を実現します。

コード:

	int *a = malloc(sizeof(int) * 3);  // malloc(sizeof(int[3]) でもよい
	a[0] = 1, a[1] = 0, a[2] = 6;
malloc が失敗したときのエラー処理は省略しています。

サイズを拡張したければ、次のようにしなければならないでしょう。

コード:

	int *p = malloc(sizeof(int) * 10);
	for (int i = 0; i < 3; i++) p[i] = a[i];
	free(a);
	a = p;
なお、malloc の代わりに realloc を使うこともできます。

配列の途中に要素を追加(挿入)しようとすると、サイズを拡張後、
挿入位置以降の要素をすべてずらした後、挿入位置にデータを代入
しなければなりません。

これを避けるために連結リストというデータ構造が使用されます。

連結リストについての質問なのでしょうか?

返信

“C言語何でも質問掲示板” へ戻る