ハマっている「お菓子」を教えて!

こんにちは.タイトルのままなのですが,c言語でstdinに何かが入力されるまで待つことなく,stdinの監視がしたいです.例えば, whileループを回してる最中に,qがstdinに入力されたらbreakするけど,あとは普通に回る,みたいな感じにしたいです.fgetc(stdin)とすると,毎回入力を待つことになるので,待たないで回る方法が知りたいです.

具体的には,以下はgnuplotにsinカーブを表示するプログラムですが,コメントアウトしてある
/* if((buf = fgetc(stdin)) == 'q'){
break;
} */
の部分のようにすると毎回とまってしまいます.これを,毎回入力を待たずに,qを打ったら止まるようにするにはどうするのが普通なのでしょうか.

返信おまちしております.

#include <stdio.h>
#include <math.h>
#include <unistd.h>
FILE *gp;
#define omega (M_PI/2)
#define A 1
#define N 10
int i;
int j;
double x, t;

int main(void) {
gp = popen(gnuplot, "w");
fprintf(gp, "set xrange [0:11]\n");
fprintf(gp, "set yrange [-3.5:3.5]\n");
fprintf(gp, "set xlabel \"x\"\n");
fprintf(gp, "set ylabel \"y\"\n");

char buf;
for (j = 0; j < N*160; ++j) {
usleep(5000);
/* if((buf = fgetc(stdin)) == 'q'){
break;
} */
fprintf(gp, "plot '-' with lines linetype 1\n");
for (i = 0; i < j+1; ++i) {
t = 0.1*i;
x = A*sin(omega*t);
fprintf(gp, "%f\t%f\n", t/10, x);
}
fprintf(gp, "e\n");
}
fprintf(gp, "exit\n");
fflush(gp);
pclose(gp);

return 0;
}

A 回答 (4件)

#2です。


>返信ありがとうございます.自分でも動かせました.ただ内容は完全には理解していない気がします.こういうシステムの方まで操作する系のプログラムってどういう本で勉強するものなのでしょうか? >Linuxの教科書などになるのでしょうか?
今回のselectに関しては、ネットワーク通信でノンブロッキングによるTCP/IPの通信を行うときに必須でした。そのときに、参考にしたのは「UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI」です。(W・リチャード・スティーブンス著)(但し、難度は高いです)
実際に業務で使用されるプログラムを書く場合は、徹底的なエラー対応処理が求められますので、
上記の本は、非常に参考になりました。但し、作成するプログラグが業務で使用されるものでない場合は(多少のフリーズなどが大目に見てもらえるなら)もっと簡単な参考書でよいかと思います。
    • good
    • 0
この回答へのお礼

返信が大変遅くなってしまいました.本も紹介してもらえてとてもうれしいです.さっそく調べてみます.

お礼日時:2013/10/14 18:18

_kbhitと_getchの組み合わせでどうでしょう?


_kbhitはWindows版にしかありませんが、ネットで検索したらLunux用に作っている方がいたのでそちらを用いれば使えるかと。
    • good
    • 0
この回答へのお礼

返信ありがとうございます.その内容についても勉強させて頂きます.

お礼日時:2013/09/20 11:04

#1の方のselectを使いなさいというアドバイスに従って作りました。


あなたのプログラムに追加を行いました。
////以下の文を追加/////
・・・・・・
/////////////////////
が追加したところです。
以下のようにして下さい。
----------------------------------------------------------------
#include <stdio.h>
#include <math.h>
#include <unistd.h>
//////以下の文を追加//////
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
int read_q(void);
int SockSelect (int sd_list[],int num_sd,long u_sec,int *ready_num_sd,int r_sts[],int *error_no );
//////////////////////////

FILE *gp;
#define omega (M_PI/2)
#define A 1
#define N 10
int i;
int j;
double x, t;
int main(void) {
gp = popen("gnuplot", "w");
fprintf(gp, "set xrange [0:11]\n");
fprintf(gp, "set yrange [-3.5:3.5]\n");
fprintf(gp, "set xlabel \"x\"\n");
fprintf(gp, "set ylabel \"y\"\n");

char buf;
for (j = 0; j < N*160; ++j) {
usleep(5000);
/* if((buf = fgetc(stdin)) == 'q'){
break;
} */
/////以下の文を追加////////////
if (read_q() == 1) break;
///////////////////////////////
fprintf(gp, "plot '-' with lines linetype 1\n");
for (i = 0; i < j+1; ++i) {
t = 0.1*i;
x = A*sin(omega*t);
fprintf(gp, "%f\t%f\n", t/10, x);
}
fprintf(gp, "e\n");
}
fprintf(gp, "exit\n");
fflush(gp);
pclose(gp);

return 0;
}
/////以下の処理を追加////
#define MuS (1000000L) /* MEGA uSECOND */
#define RET_OK(0)
#define RET_SELECT_ERR (-2)
#define RET_TIMEOUT(-1)
#define SD_STS_NOT_READY (0) /* not ready for reading */
#define SD_STS_READY (1) /* ready for reading */
#define TIME_USEC_0 (0) /* Time out wait = 0 [usec] */
//qで終了(1を返す)
int read_q(void)
{
int ret, err_cd, sd_list[10], sd_list_num, r_sts[10], r_sts_cnt;
char*cp0;
charin_buf[256];
sd_list[0] = 0;
sd_list_num = 1;
ret = SockSelect(sd_list,sd_list_num,(long) 5000,&r_sts_cnt,r_sts,&err_cd);

if (ret != RET_OK) return 0;
if (r_sts[0]==SD_STS_READY){
fgets(in_buf,64,stdin);
if (in_buf[0] == 'q') return 1;
}
return 0;
}
//select
int SockSelect ( int sd_list[],
int num_sd,
long u_sec,
int *ready_num_sd,
int r_sts[],
int *error_no ) {
int ret_value = RET_OK;
int i;
int rtni;
int max_sd;
int sd_num;
fd_set sds, wds, eds;
struct timeval timeout;

*error_no = 0;
*ready_num_sd = 0;
FD_ZERO( &sds );
FD_ZERO( &wds );
FD_ZERO( &eds );
sd_num = num_sd;
for ( i=max_sd=0; i<sd_num; i++ ) {
FD_SET( sd_list[i], &sds );
if ( sd_list[i] > max_sd ) {
max_sd = sd_list[i];
}
}

timeout.tv_sec = u_sec / MuS;
timeout.tv_usec = u_sec % MuS;
errno = 0;
rtni = select(max_sd+1,&sds,&wds,&eds,&timeout );

if ( rtni < 0 ) {
*error_no = errno;
ret_value = RET_SELECT_ERR;
return( ret_value );
} else if( rtni == 0 ) {
ret_value = RET_TIMEOUT;
for ( i=0; i<sd_num; i++ ) {
r_sts[i] = SD_STS_NOT_READY;
}
return( ret_value );
}

for ( i=*ready_num_sd=0; i<sd_num; i++ ) {
if ( FD_ISSET( sd_list[i], &sds ) ) {
r_sts[i] = SD_STS_READY;
*ready_num_sd = *ready_num_sd +1;
} else {
r_sts[i] = SD_STS_NOT_READY;
}
}
if (*ready_num_sd == 0) {
ret_value = RET_TIMEOUT;
}
return( ret_value );
}
/////////////////////////////////////////////////////////////
CentOS6.3で動作確認済です。
    • good
    • 0
この回答へのお礼

返信ありがとうございます.自分でも動かせました.ただ内容は完全には理解していない気がします.こういうシステムの方まで操作する系のプログラムってどういう本で勉強するものなのでしょうか? Linuxの教科書などになるのでしょうか?

お礼日時:2013/09/20 11:02

そもそも、stdinだとバッファリングされるので、ファイルディスクリプタ0をチェックしてください。


Unix/Linuxだとシステムコールselect()でチェックします。
    • good
    • 0
この回答へのお礼

返信ありがとうございます.こういう場合はselectを使うのですね.自分でも書けるようにしっかり勉強しようと思います.

お礼日時:2013/09/20 10:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報