0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C言語でキーボード入力判定しながら出力をしたい

Last updated at Posted at 2022-01-02

はじめに

ターゲット: 私と同じくC言語初心者

大学の課題にC言語でスロットマシンを実装せよとの課題が出たので, これはキーボード入力を受け付けながらスロットのリールが動くのを出力しないといけないのではと思ってちょっと調べてみました.

実行環境

OS: Ubuntu 20.04.3 LTS(WSL)
コンパイラ: gcc version 9.3.0

どうやって実装するか

pthreadを使います(直球)
pthreadはPOSIX threadの略で, UNIX系OSでスレッドプログラミングをする際に使用されるらしいです.
threadをいくつか作ってそれを同時に実行させるような処理を行います.

pthreadの使い方

pthreadは, 次のような感じで書きます. これがC言語にしては割と便利で, そんなに難しくないです.
以下のsample.cはENTERキーを押した回数を出力しつつ, そのENTERキー入力も同時に行うプログラムです.

sample.c
# include<pthread.h>
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h> // for usleep func

# define NUM_KBHITS_DONE 5
# define ASCII_ENTER 10
# define WAIT_MILSEC 1000*1000 //thread2のループ時に1秒待つ

typedef struct{
  int isHit; //0->false, else->true
  int num_kbHits;
  int hogehoge;
}ArgForStruct;

ArgForStruct *createStruct(void);
void* thread1(void *);
void* thread2(void *);  //引数は1つしか渡せない. 2つ以上渡したいときは構造体を使います.

int main(){
  ArgForStruct *myStruct = createStruct();
  //スレッド生成
  pthread_t inputThread;
  pthread_t showingThread;
  //スレッド開始
  pthread_create(&inputThread, NULL, thread1, myStruct);  //4つ目の引数がスレッドへの
  pthread_create(&showingThread, NULL, thread2, myStruct);//引数になります
  //スレッド終了待ち
  pthread_join(inputThread, NULL);
  pthread_join(showingThread, NULL);
  return 0;
}

ArgForStruct *createStruct(){
  ArgForStruct *myStruct = malloc(sizeof(ArgForStruct));
  myStruct->num_kbHits = 0;
  myStruct->hogehoge = 123;
  return myStruct;
}

//wait input
void* thread1(void *argStruct){
  ArgForStruct *myStruct = (ArgForStruct *)argStruct; //cast
  for(;;){
    if(myStruct->num_kbHits == NUM_KBHITS_DONE){
      myStruct->isHit = 1;
      pthread_exit(NULL);   //スレッド終了
    }

    //キーボード入力待ち
    int temp = getchar();
    if(temp == ASCII_ENTER){
      printf("ENTER HIT\n");
      myStruct->num_kbHits++;
    }
  }
}

//showing argStruct->num_kbHits
void* thread2(void *argStruct){
  ArgForStruct *myStruct = (ArgForStruct *)argStruct; //cast
  for(;;){
    printf("current kbHits: %d\n", myStruct->num_kbHits);
    usleep(WAIT_MILSEC); //1秒待つ
    
    //スレッド1で構造体のisHitが書き換えられたらスレッドを抜ける
    if(myStruct->isHit != 0){
      printf("keyboard Hits Done!: %d\n", myStruct->num_kbHits);
      pthread_exit(NULL);
    }
  }
}

実行結果

コンパイルは, オプションに "-pthread" をつける必要があります.

$gcc -pthread main.c
$./a.out
current kbHits: 0
current kbHits: 0
current kbHits: 0
current kbHits: 0

ENTER HIT
current kbHits: 1
current kbHits: 1
current kbHits: 1

ENTER HIT

ENTER HIT
current kbHits: 3
current kbHits: 3
current kbHits: 3

ENTER HIT
current kbHits: 4
current kbHits: 4

ENTER HIT
keyboard Hits Done!: 5

あとがき

面白かった(小並感)
(追記) 講義はプロセス(forkとか)使って解説されててちょっと悲しかった

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?