ふじ@メガネボーイズのメモのような日記 RSSフィード

2009-08-21

汎用的なスタックをC言語で

前回に引き続き「汎用的なをC言語で」シリーズ。

OSが提供する機能を使わないようなローレイヤー向けの汎用スタックを作ってみた。

データとして整数値/アドレスのどちらでも格納できること、

スタック用のメモリ領域を自由に設定できることが特徴。

(datatype.hは環境に合わせて書き換えてね)

datatype.h

キューと同じ。⇒http://meganeboy.g.hatena.ne.jp/fuji_ttt/20090804

stack.h

#ifndef __STACK_H__
#define __STACK_H__

#include "datatype.h"

/* スタック構造体 */
typedef struct {
	VP_INT	*p_data;	/* データ配列の先頭アドレス */
	UINT	num;		/* 格納されているデータ数 */
	UINT	depth;		/* スタックの深さ(最大データ数) */
} STACK;

/* スタック初期化 */
ER stack_initialize(STACK *p_stack, VP_INT a_data[], UINT depth);

/* プッシュ */
ER stack_push(STACK *p_stack, VP_INT data);

/* ポップ */
ER stack_pop(STACK *p_stack, VP_INT *p_data);

#endif /* __STACK_H__ */

stack.c

#include "datatype.h"
#include "stack.h"

ER stack_initialize(STACK *p_stack, VP_INT a_data[], UINT depth) {
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_stack == NULL || a_data == NULL || depth <= 0 ) {
		return E_PAR;
	}
	
	/* メンバーの初期値を格納 */
	p_stack->p_data = a_data;
	p_stack->num = 0;
	p_stack->depth = depth;
	
	/* 初期化できた場合はE_OKを返却 */
	return E_OK;
}

ER stack_push(STACK *p_stack, VP_INT data) {
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_stack == NULL ) {
		return E_PAR;
	}
	
	/* スタックが満杯の場合はプッシュせずにE_OBJを返却 */
	if ( p_stack->num >= p_stack->depth ) {
		return E_OBJ;
	}
	
	/* スタックに格納 */
	p_stack->p_data[p_stack->num] = data;
	p_stack->num++;
	
	/* プッシュできた場合はE_OKを返却*/
	return E_OK;
}

ER stack_pop(STACK *p_stack, VP_INT *p_data) {
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_stack == NULL || p_data == NULL) {
		return E_PAR;
	}
	
	/* スタックが空の場合は何もせずにE_OBJを返却 */
	if ( p_stack->num == 0 ) {
		return E_OBJ;
	}
	
	/* トップのデータを取り出して指定されたアドレスに格納 */
	*p_data = p_stack->p_data[p_stack->num-1];
	
	/* 格納されているデータ数を更新 */
	p_stack->num--;
	
	/* ポップできた場合はE_OKを返却 */
	return E_OK;
}

jvdfrgzwvxjvdfrgzwvx2014/01/19 02:32ddjffnfhbofcpz, <a href="http://www.rfhbisblww.com/">lwwyimaspn</a>

osqlhymyrvosqlhymyrv2014/01/21 16:24gjcyqnfhbofcpz, <a href="http://www.wkhjvgxhes.com/">znmldtctdb</a>

eebuwgzjdieebuwgzjdi2014/01/24 18:09fqgognfhbofcpz, http://www.iosmxaiqvf.com/ gjcujgfpab

guuhpdpqyrguuhpdpqyr2014/01/29 21:03upsynnfhbofcpz, <a href="http://www.cjikclonds.com/">vhwnmephfp</a> , [url=http://www.qfjfzqiuhh.com/]gzqzcyntls[/url], http://www.nzeockmese.com/ vhwnmephfp

xjjfnhslfhxjjfnhslfh2014/06/02 18:00sclcpnfhbofcpz, <a href="http://www.nnevhzeaoy.com/">vgegvytadw</a> , [url=http://www.ecyvzziytg.com/]wgxpnrpgeu[/url], http://www.jmisxysenl.com/ vgegvytadw

2009-08-04

汎用的なキューをC言語で

OSの提供する機能を使わないようなローレイヤー向けの汎用キューを作ってみた。

パフォーマンスが気になる場合は剰余の計算をどうにかしようw。

データとして整数値/アドレスのどちらでも格納できること、

キュー用のメモリ領域を自由に設定できることが特徴。

(datatype.hは環境に合わせて書き換えてね)

datatype.h

#ifndef __DATATYPE_H__
#define __DATATYPE_H__

/* 型定義 */
typedef	unsigned int	UINT;	/* 符号無し整数 */
typedef	int		VP_INT;	/* voidポインタまたはint(どちらでも格納できる型で定義) */
typedef	int		ER;	/* エラーコード */

/* 定数定義 */
#ifndef NULL
#define NULL	0		/* 無効ポインタ */
#endif	/* NULL */
#define E_OK	0		/* 正常終了 */
#define E_PAR	(-17)		/* パラメータエラー */
#define E_OBJ	(-41)		/* オブジェクト状態エラー */

#endif /* __DATA_TYPE_H__ */

queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include "datatype.h"

/* キュー構造体 */
typedef struct {
	VP_INT	*p_data;	/* データ配列の先頭アドレス */
	UINT	head;		/* キュー先頭データの添え字 */
	UINT	num;		/* 格納されているデータ数 */
	UINT	len;		/* キューの長さ(最大データ数) */
} QUEUE;

/* キュー初期化 */
ER queue_initialize(QUEUE *p_queue, VP_INT a_data[], UINT len);

/* エンキュー */
ER queue_enqueue(QUEUE *p_queue, VP_INT data);

/* デキュー */
ER queue_dequeue(QUEUE *p_queue, VP_INT *p_data);

#endif /* __QUEUE_H__ */

queue.c

#include "datatype.h"
#include "queue.h"

ER queue_initialize(QUEUE *p_queue, VP_INT a_data[], UINT len) {
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_queue == NULL || a_data == NULL || len <= 0 ) {
		return E_PAR;
	}
	
	/* メンバーの初期値を格納 */
	p_queue->p_data = a_data;
	p_queue->head = 0;
	p_queue->num = 0;
	p_queue->len = len;
	
	/* 初期化できた場合はE_OKを返却 */
	return E_OK;
}

ER queue_enqueue(QUEUE *p_queue, VP_INT data) {
	UINT index;
	
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_queue == NULL ) {
		return E_PAR;
	}
	
	/* キューが満杯の場合はエンキューせずにE_OBJを返却 */
	if ( p_queue->num >= p_queue->len ) {
		return E_OBJ;
	}
	
	/* 末尾より1つ後の格納位置を計算 */
	index = ( p_queue->head + p_queue->num ) % p_queue->len;
	
	/* キューに格納 */
	p_queue->p_data[index] = data;
	p_queue->num++;
	
	/* エンキューできた場合はE_OKを返却*/
	return E_OK;
}

ER queue_dequeue(QUEUE *p_queue, VP_INT *p_data) {
	/* 引数が不正な場合はE_PARを返却 */
	if ( p_queue == NULL || p_data == NULL) {
		return E_PAR;
	}
	
	/* キューが空の場合は何もせずにE_OBJを返却 */
	if ( p_queue->num == 0 ) {
		return E_OBJ;
	}
	
	/* 先頭データを取り出して指定されたアドレスに格納 */
	*p_data = p_queue->p_data[p_queue->head];
	
	/* 先頭の添え字を更新 */
	p_queue->head = ( p_queue->head + 1 ) % p_queue->len;
	
	/* 格納されているデータ数を更新 */
	p_queue->num--;
	
	/* デキューできた場合はE_OKを返却 */
	return E_OK;
}

ekhjqkkavpekhjqkkavp2013/12/17 16:08cuvzrnfhbofcpz, <a href="http://www.kxcbmwblsw.com/">soenthfoby</a> , [url=http://www.axdcokrawl.com/]yqubwljtxo[/url], http://www.mdcczuzjvs.com/ soenthfoby

2008-09-26

privateとprotectedの使い分け

※これは自分の考え方なので正しいかわかりません。(^^;

これまでの考え方

  • 基本はprotected
  • 派生クラスで使うことを意図的に禁止するものはprivate

最近の考え方

  • 利用する言語の思想に合わせる
C++

C++は、仮想関数として指定した関数のみ動的結合され、継承によるポリモフィズムが利用できる。

このような作りであることから、指定したもののみ継承を許可する思想だと考えられる。

この思想に合わせ、基本はprivateにした方がよいと思う。

  • 基本はprivate
  • 派生クラスで使うことを意図的に許可するものはprotected
Java

Javaは、finalを指定したクラスのみ継承が禁止される。

このような作りであることから、指定したもの以外は継承を許可する思想だとわかる。

この思想に合わせ、基本はprotectedにした方がよいと思う。

  • 基本はprotected
  • 派生クラスで使うことを意図的に禁止するものはprivate

skelton_boyskelton_boy2008/09/27 01:00こういうのってEffective C++とかに書いてないのかな?

fuji_tttfuji_ttt2008/09/27 19:48デストラクタがvirtualでないクラスは一般的に継承してはいけないとかってのは書いてあるみたいだけど、この日記に関連する内容が書いてあるかは不明です。C++を使う人は読むべき1冊だと言われているので、そのうち読みたいなぁ。。。