define N 4 typedef struct _QueueD { char Datim[32]; }QueueD; QueueD QueD[N]= { {NULL} }; int q_num=0; void enqueue(char *Datetime ){ int i; QueueD *qDuptr; qDuptr = &QueD; strcpy((qDuptr+q_num)->Datim, Datetime); if(q_num == N - 1){ q_num = 0; }else{ q_num++; } } int main{ char str[256]; QueueD *datep; strcpy(Que->Datim, str); //strはある動作をするたびに文字列が入力されると仮定 enqueue(str); datep = &QueD; for(t=0; t < 4; t++ ){ if( f_puts( "日時:", fp ) < 0 ) goto ERR; if( f_puts( (datep+t)->Datim, fp ) < 0 ) goto ERR; if( f_puts( "\r\n", fp ) < 0 ) goto ERR; Trace0("終端 \r\n"); } ``### 前提・実現したいこと ある関数を実行するたびに、文字列が出力されます。 その文字列をリングバッファに入れて、出力をしたいのですが、 文字を入れるところで、フリーズしてしまいます。 文字列を入れるリングバッファのつくりかたを教えていただけないでしょうか。 ### 試したこと ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/04 11:14
2018/10/04 13:25

回答3件
0
ベストアンサー
前回の回答が、インデントが乱れていましたので、再投稿します。
C
1#include <stdio.h> 2#include <string.h> 3#define N (10) 4#define NORMAL (0) 5#define OVERFLOW (1) 6#define EMPTY (2) 7typedef struct _QueueD { 8 char Datim[32]; 9}QueueD; 10QueueD QueD[N]= { {0} }; 11int q_wnum=0; 12int q_rnum=0; 13void init_queue(void){ 14 q_wnum = 0; 15 q_rnum = 0; 16} 17int inc_num(int num){ 18 num++; 19 if (num >= N) num = 0; 20 return num; 21} 22int enqueue(char *Datetime ){ 23 QueueD *qDuptr; 24 qDuptr = QueD; 25 if (inc_num(q_wnum) == q_rnum) return OVERFLOW; 26 strcpy((qDuptr+q_wnum)->Datim, Datetime); 27 q_wnum = inc_num(q_wnum); 28 return NORMAL; 29} 30int dequeue(char *Datetime ){ 31 int i; 32 QueueD *qDuptr; 33 qDuptr = QueD; 34 if (q_wnum == q_rnum) return EMPTY; 35 strcpy(Datetime,(qDuptr+q_rnum)->Datim); 36 q_rnum = inc_num(q_rnum); 37 return NORMAL; 38} 39int main(int argc,char **argv){ 40 int i; 41 int ret; 42 char buff[32]; 43 init_queue(); 44 for (i = 1; i < argc; i++){ 45 ret = enqueue(argv[i]); 46 if (ret != NORMAL){ 47 printf("OVERFLOW:%s\n",argv[i]); 48 return 10; 49 } 50 } 51 while(1){ 52 ret = dequeue(buff); 53 if (ret != NORMAL) break; 54 printf("<%s>\n",buff); 55 } 56 return 0; 57}
Nは1000に変更しています。
言わずもがなですが、32バイト以上の文字列を指定して、enqueueを行うと、誤動作します。
たぶん、質問者本人様もその点は承知かと思いますので、対策は講じておりません。
以下、実行結果です。(tera1は実行形式ファイル)
tera1 aaa bbb ccc ddd
<aaa>
<bbb>
<ccc>
<ddd>
投稿2018/10/05 09:27
総合スコア5533
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
#include <stdio.h>
#include <string.h>
#define N (1000)
#define NORMAL (0)
#define OVERFLOW (1)
#define EMPTY (2)
typedef struct _QueueD {
char Datim[32];
}QueueD;
QueueD QueD[N]= { {0} };
int q_wnum=0;
int q_rnum=0;
void init_queue(void){
q_wnum = 0;
q_rnum = 0;
}
int inc_num(int num){
num++;
if (num >= N) num = 0;
return num;
}
int enqueue(char *Datetime ){
QueueD *qDuptr;
qDuptr = QueD;
if (inc_num(q_wnum) == q_rnum) return OVERFLOW;
strcpy((qDuptr+q_wnum)->Datim, Datetime);
q_wnum = inc_num(q_wnum);
return NORMAL;
}
int dequeue(char *Datetime ){
int i;
QueueD *qDuptr;
qDuptr = QueD;
if (q_wnum == q_rnum) return EMPTY;
strcpy(Datetime,(qDuptr+q_rnum)->Datim);
q_rnum = inc_num(q_rnum);
return NORMAL;
}
int main(int argc,char **argv){
int i;
int ret;
char buff[32];
init_queue();
for (i = 1; i < argc; i++){
ret = enqueue(argv[i]);
if (ret != NORMAL){
printf("OVERFLOW:%s\n",argv[i]);
return 10;
}
}
while(1){
ret = dequeue(buff);
if (ret != NORMAL) break;
printf("<%s>\n",buff);
}
return 0;
}
誰かリングバッファに入れるところまで、書いてくれる人はいないかなぁ
とりあえず、作ってみました。
Nが小さいので1000にしてあります。
enquequeで、空きがないと、OVERFLOWを返します。
dequequeで、空の時は、EMPTYを返します。
以下、実行結果です。(実行形式ファイル名はtera1)
tera1 aaaaa bbbb ccccc ggggg hhhhhhhhhhhhhh mmmmmmmmm
<aaaaa>
<bbbb>
<ccccc>
<ggggg>
<hhhhhhhhhhhhhh>
<mmmmmmmmm>
投稿2018/10/05 02:36
総合スコア5533
0
c
1usr~/test/c % ./a.out ab cd ef gh aaa 123456789 2./a.out 3ab 4cd 5ef 6gh 7aaa 8123456789 9usr~/test/c % cat t.c 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13// 14int main(int agc, char *agv[]) 15{ 16 char *ptr[10]; 17 // 18 for( int i=0; i < agc; i++ ){ 19 ptr[i]= malloc(strlen(agv[i])+1); 20 strcpy(ptr[i],agv[i]); 21 } 22 // 23 for( int i=0; i < agc; i++ ){ 24 puts(ptr[i]); 25 free(ptr[i]); 26 } 27 28 return 0; 29} 30 31usr~/test/c %
あとは、ポインタの配列をリングバッフにするだけです。
//
注意:書き込み用のインデックスが読み出し用のインデックスを追い抜かないようにして下さい。さもないと、文字列を格納したアドレスが上書きされて、開放できなくなります。free()したらポインタをクリアすればどのデータが残っているか判定できます。
考え方:a[10]という配列がある場合、a[9]の次はa[0]になるわけですからインデックスが9になったら0にしてやればいいだけです。
参考:リングバッファ
「追記」
遅くなりましたが^^; たぶん動くw
usr~/test/c % ./a.out 11 22 33 44 55 6666 77 8888 99 00 aaaaaaa bb cc ddddddd ee ff ./a.out 11 22 33 44 55 6666 77 8888 99 00 aaaaaaa bb cc ddddddd ee ff count:0 usr~/test/c % cat main.c #include <stdio.h> #include <stdlib.h> #include <string.h> // typedef struct { int count; int rInx; int wInx; char *ptr[8]; } ringBuf; // enum { SET = 1, FULL = 0, EMPTY = 0 }; // static int wQ(char *str, ringBuf *bPtr) { if (bPtr->ptr[bPtr->wInx]) { return FULL; } bPtr->ptr[bPtr->wInx] = malloc(strlen(str) + 1); strcpy(bPtr->ptr[bPtr->wInx], str); // bPtr->wInx = (bPtr->wInx + 1) & 0x07; // bPtr->count++; // return SET; } // static char *rQ(ringBuf *bPtr) { char *ptr = bPtr->ptr[bPtr->rInx]; if (ptr == 0) { return EMPTY; } // bPtr->ptr[bPtr->rInx] = 0; bPtr->rInx = (bPtr->rInx + 1) & 0x07; // bPtr->count--; // return ptr; } // int main(int agc, char *agv[]) { ringBuf rbf; rbf.rInx = rbf.wInx = rbf.count = 0; for (int i = 0; i < 8; i++) { rbf.ptr[i] = 0; } // for (int i = 0; i < agc; i++) { if (wQ(agv[i], &rbf) == SET) { char *str = rQ(&rbf); if(str != 0){ puts(str); free(str); } } } // printf("count:%d\n",rbf.count); // return 0; } usr~/test/c %
char *ptr[8]; ←バファのサイズ
bPtr->rInx = (bPtr->rInx + 1) & 0x07; ←0〜7を生成(2^n)をマスクする常套手段。
・・・今のコンパイラは偉いから普通のif文で最後まで行ったら0に戻しても可d^^
投稿2018/10/04 11:21
編集2018/10/07 11:28総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。