/* ppps_int_queue.c [サンプルライブラリ] int型のキュー author: K.Y (Programming Place Plus) version 1.0.2 '2019/9/23 ・Webサイト側が C99規格へ対応したことに合わせて、コードを修正。 コメントスタイルと、変数宣言位置を変えた。 bool型を使う。 1.0.1 '2013/1/26 ・ppps_int_queue_try_dequeue関数を追加。 ・外部へ公開しない関数に static を付加。 1.0.0 '2012/7/7 */ #include #include #include #include "ppps_int_queue.h" static size_t get_next_index(PPPSIntQueue queue, size_t index); static void* xmalloc(size_t size); struct PPPSIntQueue_tag { int* data; // 要素を格納する動的配列 size_t size; // data の要素数 size_t front; // 先頭の要素の位置 size_t tail; // 末尾の要素の位置 }; /* キューを作る */ PPPSIntQueue ppps_int_queue_create(size_t size) { // front == tail を空の状態にしようとすると、配列全体を使い切った状態を作れない。 // そこで、指定された size を +1 して、1つ余分に領域を確保しておく。 size += 1; struct PPPSIntQueue_tag* queue = xmalloc( sizeof(struct PPPSIntQueue_tag) ); queue->data = xmalloc( sizeof(int) * size ); queue->size = size; queue->front = 0; queue->tail = 0; return queue; } /* キューを削除する */ void ppps_int_queue_delete(PPPSIntQueue queue) { free( queue->data ); free( queue ); } /* キューに要素を入れる */ void ppps_int_queue_enqueue(PPPSIntQueue queue, int value) { assert( get_next_index(queue, queue->tail) != queue->front ); queue->data[queue->tail] = value; // 次に要素を入れるときに使う位置を求める // リングバッファ構造なので、単純に +1 するだけではダメ queue->tail = get_next_index( queue, queue->tail ); } /* キューから要素を取り出す */ int ppps_int_queue_dequeue(PPPSIntQueue queue) { assert( !ppps_int_queue_is_empty(queue) ); int pop_value = queue->data[queue->front]; // 先頭から要素が1つ取り出されるので、先頭位置を更新する // リングバッファ構造なので、単純に +1 するだけではダメ queue->front = get_next_index( queue, queue->front ); return pop_value; } /* キューから要素を取り出す (成否判定付き) */ bool ppps_int_queue_try_dequeue(PPPSIntQueue queue, int* p) { assert( p != NULL ); if( ppps_int_queue_is_empty(queue) ){ return false; } *p = queue->data[queue->front]; // 先頭から要素が1つ取り出されるので、先頭位置を更新する // リングバッファ構造なので、単純に +1 するだけではダメ queue->front = get_next_index( queue, queue->front ); return true; } /* キューが空かどうか調べる */ bool ppps_int_queue_is_empty(PPPSIntQueue queue) { return queue->front == queue->tail; } /* 1つ後ろの添字を取得する */ size_t get_next_index(PPPSIntQueue queue, size_t index) { return (index + 1) % queue->size; } /* エラーチェック付きの malloc関数 */ void* xmalloc(size_t size) { void* p = malloc( size ); if( p == NULL ){ fputs( "メモリ割り当てに失敗しました。", stderr ); exit( EXIT_FAILURE ); } return p; }