質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

1878閲覧

C言語で文字列のリングバッファをつくりたい

Mr.kyousuke

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

1クリップ

投稿2018/10/04 10:45

編集2018/10/04 10:59
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/ツールのバージョンなど) ここにより詳細な情報を記載してください。
atata0319👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/10/04 10:47

コードは、<code>ボタン、’’’の枠の中に貼り付けてください
tiitoi

2018/10/04 11:14

リングバッファの各要素が文字列という認識であってますか?
tiitoi

2018/10/04 13:25

C言語でないと駄目ですか? (std::string とか使いたい)
Mr.kyousuke

2018/10/04 13:54

開発環境がC言語なので、C言語でお願いいたします。
guest

回答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

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2018/10/05 06:57

コードは次のように囲まないとインデントが崩れてしまいます。 ```コード```
tatsu99

2018/10/05 09:16

ご指摘、ありがとうございます。 初めての投稿なので、よくわからないまま、投稿してしまいした。 投稿しなおします。
guest

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
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Mr.kyousuke

2018/10/04 11:39

ポインタ配列を用意して、文字列をコピーすればいいんですね、確認してみます。 リングバッファに入れるところまで見たいです。
Mr.kyousuke

2018/10/04 12:27

誰かリングバッファに入れるところまで、書いてくれる人はいないかなぁ
cateye

2018/10/04 12:32

可変長の文字列と言うことで、メモリを確保するようにしました。リングバッファについては、結構手間かかりそう&時間がない;; なので・・・“リングバッファ C言語” 等で検索してみてください。
Mr.kyousuke

2018/10/04 14:02

リングバッファC言語当で検索しても、文字列を使ったものが見当たらず、、困ってます。
cateye

2018/10/08 16:14

リングバッファは通常他のプロセスや他のスレッドとのデータのやり取りをする場合に使います。そのため、排他制御が必須となります。したがって、上記プログラムはリングバッファの実装の雛形にしかなりません。排他制御の方法については実装する環境に従って下さい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問