
No.2ベストアンサー
- 回答日時:
こんにちは。
> こんなイメージを持ったのですが、間違っていますか?
イメージは正しい(間違ってはいない)と思います。
※当方の認識不足の場合はすみません。
リングバッファは、通信処理などでも使用されます。
※リングバッファを使用することで、送信処理と受信処理を別々に行うことが
可能となります。
※また、データの取り逃し防止、処理の渋滞回避などのためにも有効です。
参考までに、リングバッファ使用のサンプルプログラムを作成してみました。
※文字列を登録するリングバッファを使用したものです。
※C言語によるベタな作り方です。
C++ならクラス化するとか、STLなどを使用して、もっとスマートな作り方が
できると思います。
これで、リングバッファの動作が、ご理解いただければ良いのですが。。。
※的外れな内容でしたらすみません。
■サンプルの処理の流れ
1)リングバッファの初期化
↓
2)リングバッファに10個の文字列を登録
・リングバッファの登録数いっぱいまで登録
↓
3)リングバッファより1個目のデータ(文字列)を取り出して表示出力
↓
4)リングバッファへ11個目の追加データ(文字列)を登録
↓
5)リングバッファより2個目のデータ(文字列)を取り出して表示出力
↓
6)リングバッファへ12個目の追加データ(文字列)を登録
↓
7)リングバッファより3個目のデータ(文字列)を取り出して表示出力
↓
8)リングバッファへ13個目の追加データ(文字列)を登録
↓
9)リングバッファより残りのデータ(文字列)全部を表示出力
なお、今回のサンプルでは、リングバッファへのアクセスは時系列で順番に
行っていますが、
マルチスレッドのような並列処理で、書き込み処理と、読み込み処理を、別々
に行うような場合は、リングバッファへの同時アクセスを回避するために、
排他制御(片方が使用している場合は、もう片方を使用不可とする)が必要な
場合があります。
■サンプルプログラム
注)インデント等のため、全角スペースを入れています。
※コピペする際は、半角スペースorタブに置換して下さい。
=========================
/*
* tring10.c : リングバッファのテスト
*/
#include <stdio.h>
#include <string.h>
#define RING_SIZE 10 /*リングバッファのデータ登録数(上限値)*/
#define SBUF_SIZE 50 /*リングバッファ内の文字列バッファサイズ*/
#ifdef TRUE /*関数の戻り値の定義(TRUE)*/
#undef TRUE
#endif
#define TRUE 1
#ifdef FALSE /*関数の戻り値の定義(FALSE)*/
#undef FALSE
#endif
#define FALSE 0
/* リングバッファ構造体 */
typedef struct _T_RING {
int nSetNum; /*登録データ数*/
int nWtPos; /*書き込み位置*/
int nRdPos; /*読み込み位置*/
char szBuf[RING_SIZE][SBUF_SIZE]; /*文字列バッファ*/
} T_RING;
/* 関数プロトタイプ */
void InitRing( T_RING *t_ring );
int PutRing( T_RING *t_ring, char *szBuf );
int GetRing( T_RING *t_ring, char *szBuf );
/*== main ==*/
int main(void)
{
int icnt1; /*カウンタ変数(書き込み用)*/
int icnt2; /*カウンタ変数(読み込み用)*/
char szTemp[SBUF_SIZE]; /*汎用文字列*/
static T_RING t_ring; /*リングバッファ*/
/* 登録データ */
const char szPutData[][20] = {
{ "Data-01" }, /*01*/
{ "Data-02" }, /*02*/
{ "Data-03" }, /*03*/
{ "Data-04" }, /*04*/
{ "Data-05" }, /*05*/
{ "Data-06" }, /*06*/
{ "Data-07" }, /*07*/
{ "Data-08" }, /*08*/
{ "Data-09" }, /*09*/
{ "Data-10" }, /*10*/
{ "AddData-01" }, /*11*/
{ "AddData-02" }, /*12*/
{ "AddData-03" }, /*13*/
{ "\0" } /*End*/
};
/*リングバッファの初期化*/
InitRing( &t_ring );
/*リングバッファへデータ登録*/
/*※最初に10個分(リングバッファの最大登録数分)*/
for(icnt1=0; icnt1<RING_SIZE && szPutData[icnt1][0]!='\0'; icnt1++)
{
PutRing( &t_ring, (char*)szPutData[icnt1] );
}
icnt2 = 0; /*読み込み用カウンタをリセット*/
/*リングバッファより1個読み込んで出力*/
printf( "-- Get Ring (1) --\n" );
if( GetRing( &t_ring, (char*)szTemp ) ){
printf( "No.=%3d: %s\n", icnt2+1, szTemp );
icnt2++;
}
/*リングバッファへ追加データ登録(1個目)*/
if( szPutData[icnt1][0]!='\0' ){
PutRing( &t_ring, (char*)szPutData[icnt1] );
icnt1++;
}
/*リングバッファより1個読み込んで出力*/
printf( "-- Get Ring (2) --\n" );
if( GetRing( &t_ring, (char*)szTemp ) ){
printf( "No.=%3d: %s\n", icnt2+1, szTemp );
icnt2++;
}
/*リングバッファへ追加データ登録(2個目)*/
if( szPutData[icnt1][0]!='\0' ){
PutRing( &t_ring, (char*)szPutData[icnt1] );
icnt1++;
}
/*リングバッファより1個読み込んで出力*/
printf( "-- Get Ring (3) --\n" );
if( GetRing( &t_ring, (char*)szTemp ) ){
printf( "No.=%3d: %s\n", icnt2+1, szTemp );
icnt2++;
}
/*リングバッファへ追加データ登録(3個目)*/
if( szPutData[icnt1][0]!='\0' ){
PutRing( &t_ring, (char*)szPutData[icnt1] );
icnt1++;
}
/*リングバッファの残りのデータを出力*/
printf( "-- Get Ring (4) --\n" );
for(; GetRing( &t_ring, (char*)szTemp ); icnt2++)
{
printf( "No.=%3d: %s\n", icnt2+1, szTemp );
}
return 0;
}
/*== リングバッファの初期化 ==*/
void InitRing( T_RING *t_ring )
{
int i;
/* リングバッファのメンバデータを初期化 */
t_ring->nSetNum = 0;
t_ring->nWtPos = 0;
t_ring->nRdPos = 0;
/* リングバッファの文字列バッファをクリア */
for(i=0; i<RING_SIZE; i++){
memset( t_ring->szBuf[i], 0, (SBUF_SIZE * sizeof(char)) );
}
}
/*== リングバッファへのデータ登録 ==*/
int PutRing( T_RING *t_ring, char *szBuf )
{
/* リングバッファがいっぱいのときは登録しないようにする場合は */
/* 下記を有効とする */
/*
* if( t_ring->nSetNum == RING_SIZE ){
* return FALSE;
* }
*/
/* リングバッファの書き込み位置のバッファに引数の文字列をセット */
strcpy( t_ring->szBuf[t_ring->nWtPos], szBuf );
/* リングバッファの書き込み位置を+1する */
t_ring->nWtPos = (t_ring->nWtPos + 1) % RING_SIZE;
/* リングバッファのデータ登録数を+1する */
if( t_ring->nSetNum < RING_SIZE ){
/* データ登録数が上限未満のとき */
t_ring->nSetNum++;
}
else {
/* データ登録数が上限に達したとき */
/* ※読み込み位置を書き込み位置と同じにする */
t_ring->nRdPos = t_ring->nWtPos;
}
return TRUE;
}
/*== リングバッファからデータ取得 ==*/
int GetRing( T_RING *t_ring, char *szBuf )
{
/* リングバッファが空きならFALSEで戻る */
if( t_ring->nSetNum == 0 ){
return FALSE;
}
/* 引数の文字列にリングバッファの読み込み位置の文字列をセット */
strcpy( szBuf, t_ring->szBuf[t_ring->nRdPos] );
/* リングバッファの読み込み位置を+1する */
t_ring->nRdPos = (t_ring->nRdPos + 1) % RING_SIZE;
/* リングバッファのデータ登録数を-1する */
/* ※データ登録数が>0のとき */
if( t_ring->nSetNum > 0 ) t_ring->nSetNum--;
return TRUE;
}
=========================
■サンプルの実行結果
-- Get Ring (1) --
No.= 1: Data-01
-- Get Ring (2) --
No.= 2: Data-02
-- Get Ring (3) --
No.= 3: Data-03
-- Get Ring (4) --
No.= 4: Data-04
No.= 5: Data-05
No.= 6: Data-06
No.= 7: Data-07
No.= 8: Data-08
No.= 9: Data-09
No.= 10: Data-10
No.= 11: AddData-01
No.= 12: AddData-02
No.= 13: AddData-03
以上です。参考になれば幸いです。
ご丁寧な回答をありがとうございます。
リングバッファがどういうものか
分かりました。
サンプルプログラムまで作って頂いて、
本当にありがとうございました。
No.1
- 回答日時:
はい、そうです。
一定の容量を取っておいて、アドレスの最後と最初とが繋がっているかのように(プログラム上)扱うものをリングバッファと呼んでいます。
音楽の再生なんかではほぼ必ずリングバッファが使われます。一秒程度のデータをメモリに展開しておいて、それを二分割か四分割し、再生位置が切れ目に来るとイベントが起きてバッファに新しいデータを書き込みます。走る人の前の方に新しく道が出来ていくような具合です。
こういう風にすると、たとえば650MBの音楽CDを再生するときでも、バッファは1秒分だけ持てば良いことになります。
この回答への補足
素早い回答ありがとうございます。
私の持っていたイメージが当たっていたようですね。
音楽の再生で用いられるようですが、確認させて
ください!
(物分りが悪くて申し訳ありません)
<今思っているイメージ>
要素数5個の配列をリングバッファに例えてみます。
ちなみに■が読み取られていない新しいデータ、
□がすでに読み取られた古いデータとします。
最初にバッファいっぱいまでデータを書き込んでおきます。(一秒程度)
■■■■■
0, 1, 2, 3, 4
この状態で、左から順にCPUがデータを読み取っていく時、
0が読み取られ、CPUは次に1を読みに行きます。
□■■■■
この時に、0の位置に新しいデータを書き込んでおきます。
■□■■■
CPUが1を読み取り、2を読みに行く時には、2に新しいデータを
書き込んでおく…。
こんなイメージを持ったのですが、間違っていますか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- ドライブ・ストレージ HDDの未割り当て領域が認識されない 7 2022/11/27 18:51
- 日本語 「言語化する」って言い方、どうなの? 「文章化する」「言葉で説明する」ではダメなのか? 9 2023/08/01 18:03
- その他(パソコン・スマホ・電化製品) 新しく作る同好会の名前の案を募集します。 10 2022/08/18 16:02
- USBメモリー・SDカード・フラッシュメモリー microSDカードに追記出来ない 9 2023/06/18 17:19
- FTTH・光回線 ADSL→光回線、について、初歩的ですが教えて下さい 4 2022/04/23 13:24
- 数学 【圏論】モノイドにおける恒等射について 8 2022/06/09 23:52
- 宗教学 本をさがしています・・・・夢? 幻? 思い込み? 2 2022/10/18 03:55
- 相続・遺言 マンション管理組合の弁護士から委任を受けた 弁護士から書類が届き驚きました… 私の父親(亡くなった) 6 2023/04/22 15:14
- CPU・メモリ・マザーボード デスクトップPCのOS(C:)の空き領域がどんどん減ります。 9 2022/12/12 09:24
- Word(ワード) Wordで図形などの全てのオブジェクトの位置を一括で固定する方法はありますか? 1 2022/04/19 14:29
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
教えて下さい
-
【エクセル】測定時間がバラバ...
-
エクセルで2つの時系列のデー...
-
メモ帳(テキストデータ)をExc...
-
C#でデータのファイル保存と保...
-
EXCELVBAでSQLserverからデータ...
-
Xファイルの法線情報について
-
ユーザーフォームのテキストボ...
-
特定のデータの抽出方法を教え...
-
cakePHPでバルクインサートする...
-
標準ブラウザ情報の取得
-
C言語の問題なのですが、分から...
-
VBでデータ量を指定してPingす...
-
VBA セルに入っている値数挿入...
-
TBWに達するまで後5GBの時に100...
-
S9タイプからXタイプにデータ...
-
エクセルの関数:列末尾のデー...
-
[C言語] コメント文字列を無視...
-
VBA 空白セルを削除ではない方...
-
Excel VBAでのオートフィルター...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
教えて下さい
-
【エクセル】測定時間がバラバ...
-
配列でデータが入っている要素...
-
VBA 空白セルを削除ではない方...
-
メモ帳(テキストデータ)をExc...
-
EXCELVBAでSQLserverからデータ...
-
多量のSUMIF式を軽くしたい
-
この行は既に別のテーブルに属...
-
CString型の文字列連結について
-
ACCESSからEXCELに出力する際、...
-
ユーザーフォームのテキストボ...
-
エクセルで2つの時系列のデー...
-
C# でDataTableの更新を高速化...
-
特定のデータの抽出方法を教え...
-
C# ソケット通信でデータ受信時...
-
二分探索の平均探索回数
-
Excel VBAでのオートフィルター...
-
ブレーカー落ちで壊れたりしな...
-
Accessで該当データにフラグを...
-
VBAを使ってOutlookメール本文...
おすすめ情報