ふじ@メガネボーイズのメモのような日記 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-11-15

skelton_boyskelton_boy2008/11/16 13:27ステアリング補正のとこで、ステアリングの慣性を見極める方法がどうしたらいいんだろう?

2008-09-22

実装においてチャンピオンシップに向けて改善したい点

  • パフォーマンス改善(1ループの処理速度を測ってみて必要があれば)
  • 走行状況データに操作の履歴を追加(どのようにステアリングを切ってきたか)
  • 積極的マーカー検知走行ロジックの改良(脱線しないように)
  • ツインループ走行ロジックの実装
  • ショートカット走行ロジックの実装(できたら)

2008-09-20

走行シナリオによるETロボコン競技用プログラムの製造ライン

考えたこと

実のところ、現在のメガネパスファインダーは、製造ラインにするための基盤を備えているのではないか?

ETロボコンにおける各年の違い

大きなところでは以下の2つだと思います。

  • コース構成
  • ボーナス

各年ごとに作成するもの

  • 走行シナリオ(走行シーン含む)
  • 不足している走行ロジック

モデルから自動生成

走行シナリオのステートマシン図もどきと各走行シーンのオブジェクト図もどきを書けば、

走行プログラムやパラメタ調整用ツールは自動生成できると思います。(不足している走行ロジックプログラムを書かないといけないけど)

自動生成できるもの

もしかして

小規模なSoftwareFactoryやプロダクトラインが実現できる?

skelton_boyskelton_boy2008/09/22 20:13software facoryは言い過ぎかもしれないけど、シナリオを自動生成して、パラメタを外部から与える仕組みを作れば、なかなかおもしろいかも。
来年に向けてのチャレンジ課題?

fuji_tttfuji_ttt2008/09/22 20:35モデルで入賞を狙うなら、これぐらいしないといけないかなと思ったけど、時間的に今年やるのは難しいなとも思った。

skelton_boyskelton_boy2008/10/05 15:28冒頭の製造ラインっての、プロダクトラインだよね。日本語にすると、気づかないなー。

fuji_tttfuji_ttt2008/10/05 15:50ああ、それは、普通の工業製品の製造ラインのことを指してました。

2008-09-06

本番シナリオ案

第2回試走会が終わり、しばらくたってから、再度、本番のシナリオを考えてみました。

ふじの案をアップしときます。

f:id:fuji_ttt:20080906180238p:image

2008-08-22

各シーンについて整理してみた

f:id:fuji_ttt:20080822191700p:image

走行ロジック側から次のロジックに切り替えるタイミングを知らせる必要も出てきたね。

戻り値がtrueだったら、その走行ロジックは完了したものとして扱うのがいいかな。

2008-08-21

インスタンスごとのタスクの利用について

問題点

今回の対応

仕方がないので、クラスメソッドを指定することにする。

execi(&InputDetectionU::processSamplingInput, 0, 0, INPUT_TASK_PRI, DEFAULT_STACK_SIZE);

しかし、今回の場合、インスタンスごとにサンプリング指示の通知先を持っているので、クラスメソッドでは、どこに通知するのか定まらない。

対策としては、タスクの引数(argcとargv)として、インスタンスごとのID(アドレスを文字列に変換して使えばよいと思う)をわたしておいて、タスク内で対応するインスタンスを取得して処理を進める方法が考えられる。

上記のような対策はあるが、今回は、複数のインスタンスを使わないので、サンプリング指示の通知先をクラス変数に持たせておいて、そこに通知するようにした。

これは、明らかに正しい実装ではないので、将来的な対策を記録として残しておく(上述の方法)。時間が取れたら対処したい。

//------------------------------------------------------------------------------
// サンプリングのボタン押下を確認する
int InputDetectionU::processSamplingInput (int argc, char** argv) {  // << クラスメソッド

	while ( true ) {
		// シャットダウン要求があった場合(Offボタンが押された場合)
		if ( shutdown_requested() ) exit(0);
		// 待ちボタンではない場合は眠る
		if ( BUTTON_KIND_VIEW == OperationPanel::getButtonPressed() ) break;
		msleep (100);
	}
	m_pSamplingActionLisn->execSampling();  // << クラス変数
	
	return 0;
}

skelton_boyskelton_boy2008/08/23 19:32時間の関係上、しょうがないんじゃないかなと思います。
暫定措置のまま問題なければ、優先度高いやつに進みましょう。

2008-07-23

Singletonの実装

最初の壁

最初はクラススコープの変数としてインスタンスを定義していた。

RunningFactory RunningFactory::instance;
RunningFactory* RunningFactory::getInstance()
{
	return &instance;
}

何故か動作がおかしい(暴走する)。原因不明。

(C++を理解できていないのかも。どなたか分かる方がいらっしゃいましたら、コメントをいただけると幸いです)

2つ目の壁

次に、関数内のstatic変数でインスタンスを定義してみた。

RunningFactory* RunningFactory::getInstance()
{
	static RunningFactory instance;
	return &instance;
}

コンパイル(リンク?)時にatexitが定義されていないというエラーが出た。

(関数内static変数はインスタンスを破棄するために内部的にatexit関数を使っているのかも)

Webを調べてみると、またもやclayfishさんのブログ「yagihiro output」内に記事を見つけた。

http://d.hatena.ne.jp/clayfish/20070505

ありがたい。

最終的に

newしたインスタンスが最後までdeleteされないことを承知の上でGoFのSingletonにするか、

クラスが増えることを覚悟してSingletonDestroyerを導入するか。

【Object-Oriented & Java maneuver 別室 Singletonパターン】 http://www.02.246.ne.jp/~torutk/cxx/designpattern/singleton.html

とりあえず、GoFのSingletonで動作に問題がないことは確認済み。

fuji_tttfuji_ttt2008/07/23 19:57Destroyerクラスが1つ増えるぐらい気にしなくていいか。
どのドメインに所属させるか悩ましいけど(初期化用のドメインを作ったほうがいいかも)。

skelton_boyskelton_boy2008/07/23 19:59deleteすることは考えなくてもいいんじゃないでしょうか?電源リセットできるし。

ちなみに、走行するレベルにはなりましたか?

fuji_tttfuji_ttt2008/07/23 20:11じゃ、deleteは考えずに。
走るよー。>> ちなみに、走行するレベルにはなりましたか?