質問するログイン新規登録

Q&A

2回答

3648閲覧

[C言語]標準入力stdinをread()する際、入力待機もしつつmainの処理を進めたいが、マルチスレッドで入力待機する以外の方法はあるか

HoriemonHack

総合スコア54

C

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2022/05/29 09:18

0

0

標準入力stdinread()する際、以下のソースだと、入力があるまでずっと read()の部分で止まってしまいます。

read()は、何も入力していないときは戻り値=0、と期待していましたがどうやら違うようです。

もちろんread()部分をマルチスレッドにすれば可能かとは思いますが、もしマルチスレッドを作る以外の方法で、stdinの中身が0か否かを即時に判定して、値を返すような手段があるのであれば、ご教授いただければと思います。

(Linuxの仕組み上、本当に手段がなさそうであれば、腹をくくってマルチスレッドを検討するつもりではいます。)

c

1 2int main(){ 3 char buf[255]; 4 int size; 5 6 memset(buf, '\0', sizeof(buf)); 7 8 while(1){ 9 size = read(STDIN_FILENO, buf, 255); 10 if (size == -1) { 11 perror("error"); 12 return 1; 13 } 14 else if (size == 0){ // 入力がまだなければ、先に進む。としたいがそうはなってくれない。 15 continue; 16 } 17 // 処理1:入力がない間、実行したい処理 18 printf("Hello\n"); 19 sleep(1); 20 // 処理2:入力がない間、実行したい処理 21 printf("World\n"); 22 sleep(1); 23 // 処理3 : 標準入力から受け取った、bufが"hoge\n"だったらwhileを抜ける 24 if(strcmp(buf, "hoge\n")==0){ 25 break; 26 } 27 } 28 return 0; 29}

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

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

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

melian

2022/05/29 09:43

"linux select polling stdin" で検索してみるとよいかもしれません。
pepperleaf

2022/05/29 09:51

詳しい人から、回答がつくと思うけど、、、、 read()は、区切りの入力(Enterとか)来るか、指定バイト数まで制御が戻らない。 面倒で無ければ、マルチタスク。 あるいは、Terminfoとかの設定で、標準入力の設定を変更する事。最近のLinuxの指定方法知らないので、こちらへ。
guest

回答2

0

read()がblockするのを回避したいなら non-blockingにする方法もあります。

int flags = fcntl(0, F_GETFL); // add fcntl(0, F_SETFL, flags | O_NONBLOCK); // add while(1){ size = read(STDIN_FILENO, buf, 255); if (size == -1 && errno != EAGAIN) { //modify perror("error"); return 1; }

投稿2022/05/30 02:03

sigsegv

総合スコア900

0

「入力がある・ない」が、「(何か打ち込んで)Enterキーを押した・押してない」ということでいいなら、selectで検知できます。

C

1#include <stdlib.h> 2#include <sys/select.h> 3 4int main(){ 5 fd_set fds; 6 struct timeval timezero = {0,0}; 7 int sel; 8 9 FD_ZERO(&fds); 10 FD_SET(STDIN_FILENO,&fds); 11 12 なんか処理; 13 sel = select(STDIN_FILENO+1, &fds, NULL, NULL, &timezero); 14 if(sel<0){ 15 perror("select"); 16 exit(1); 17 }else if(sel){ 18 入力があった場合の処理(readなど); 19 ~~~ 20 }else{ 21 入力がなかった場合の処理; 22 ~~~ 23 } 24}

selが1なら、「前回標準入力を読んで以降にEnterが押された」。0なら「押されてない」です。

通常の端末動作モードではEnterを押すまでプログラムには何も通知されないので、
Enterを押していないがキー入力ありという状態も、「入力がある」と判断しないといけないとすると、
tcsetattr()等を使って端末の動作モードを変更する必要があります。

投稿2022/05/29 09:58

編集2022/05/29 10:05
otn

総合スコア86597

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.29%

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

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

質問する

関連した質問