Ex13Ans

From Prog0

Jump to: navigation, search

演習第13回

Contents

解答例

A問題

A-1 外部変数の利用

ファイル名: ex13a1.c

#include <stdio.h>

void function1(void);
void function2(void);

int count1, count2, countTotal;

int main() {
    int n;
    while(1) {
        printf("Which function will you call? [1 or 2 (0: Stop)]: ");
        scanf("%d", &n);
        if ( n == 0 ) break;
        switch(n) {
            case 1:
                function1();
                break;
            case 2:
                function2();
                break;
            default:
                break;
        }
  }
  printf("Function 1 was called %d times.\n", count1);
  printf("Function 2 was called %d times.\n", count2);
  printf("Functions 1 and 2 were called %d times in total.\n", countTotal);
  
  return 0;
}

void function1(void) {
    printf("Function 1 was called.\n");
    count1++;
    countTotal++;
}

void function2(void) {
    printf("Function 2 was called.\n");
    count2++;
    countTotal++;
}

A-2 リングバッファを用いたキューのプログラム

ファイル名: ex13a2.c

  • 赤字が、lec13-2b.cからの変更点です。

#include <stdio.h>
#include <stdlib.h>

#define QSIZE 5

void enqueue(int);
int dequeue(void);
int isFull(void);   /* プロトタイプ宣言 */
int isEmpty(void);

int queue[QSIZE];
int head = 0;
int tail = 0;

int main(){
  int data, status, i;

  while (1) {
    printf("input>> ");
    status = scanf("%d", &data);
    if (status != 1) break;
    /* 入力値が0の場合はデータ取り出し、それ以外ならデータを
       キューに追加する */
    if (data == 0) printf("Data: %d\n", dequeue() );
    else enqueue(data);

    printf("  [Queue] ");   /* 処理後にキューの内容を表示してみる */
    for ( i=head; i!=tail; i=(i+1)%QSIZE ) printf("%d ", queue[i]);
    printf("\n");
  }
   
  return 0;
}

void enqueue(int num){
    int next = (tail+1);
    if (next == QSIZE) next = 0;
    
    if (isFull() == 1) {   /* isFull() のみでもよい */
    /* キューがいっぱいの場合のエラー処理 */
    printf("Queue overflow!\n");
    exit (2);
    }
    queue[tail] = num;
    tail = next;
}

int dequeue(void){
    int val;
    
    if (isEmpty() == 1) {   /* isEmpty() のみでもよい */
    /* キューが空の場合のエラー処理 */
    printf("Queue is empty!\n");
    exit (3);
    }
    val = queue[head++];
    if (head == QSIZE) head = 0;
    return val;
}

/* isFull関数:キューがいっぱいなら1を返し、そうでなければ0を返す */
int isFull(void){
     if ( (tail+1)%QSIZE == head ) return 1;
     else return 0;
     /* if-else文を使わず「return ((tail+1)%QSIZE == head);」とするのでもOK */
}

/* isEmpty関数:キューが空なら1を返し、そうでなければ0を返す */
int isEmpty(void){ 
    if ( head == tail ) return 1;
    else return 0;
    /* if-else文を使わず「return (head == tail);」とするのでもOK */ 
}

B問題

B-1 検索機能つきスタックのプログラム

ファイル名: ex13b1.c


/* スタック(検索機能追加)(lec13-1b.c をもとに改変)*/

#include <stdio.h>
#include <stdlib.h>

#define STSIZE 100

void push(int);
int pop(void);
void detect(void);

int stack[STSIZE];
int top = 0;

int main(){
  int data, status, i, n;

  while (1) {
   printf("\n--- Input [+] to push, [-] to pop, [0] to detect --- >> ");
    
    status = scanf("%d", &data);
    if (status != 1) break; // Control + d で抜ける
    
    /* 入力値が正の場合はそのデータをpush, 
       負の場合はpop, 
       0の場合はさらに値の入力を促し、スタック中を検索 */
    if (data > 0) push(data);
    if (data < 0) printf("Data: %d\n", pop() );
    if (data == 0) detect();
    
    /* 処理後にスタックの内容を表示 */
    printf("  [Stack] ");   
    for ( i=0; i<top; i++ ) printf("%d ", stack[i]);
    printf("\n");
  }

  return 0;
}


/* 関数群 */

void push(int num){
  if (top == STSIZE) {
    /* スタックがいっぱいの場合、エラー処理を行う */
    printf("Stack overflow!\n");
    exit (2);
  }
  stack[top] = num;
  top++;
}

int pop(void){
  /* スタックが空の場合、エラー処理を行う */
  if (top == 0) {
    printf("Stack is empty!\n");
    exit (3);
  }
  top--;
  return stack[top];
}

void detect(void) {
  int i, num;
  
  /* スタックが空の場合、エラー処理を行う */
  if (top == 0) {
    printf("Stack is empty!\n");
    exit (3);
  }
  
  /* 検索すべき数字を入力させる */
  printf("Detect what ? :");
  scanf("%d", &num);

  /* 検索 */
  for(i = 0; i<top; i++){
   if(stack[i] == num){
     printf("%d exists at stack[%d] \n", num, i);
     break;
   }
  }
  /* スタック中に検索値が存在しない場合、エラー処理を行う */
  if(i == top) {
   printf("%d not in stack! \n", num);
   exit (4);
  }
}

B-2 キュー:別の実装法

ファイル名: ex13b2.c

#include <stdio.h>
#include <stdlib.h>

#define QSIZE 5

void enqueue(int);
int dequeue(void);

int queue[QSIZE];
int head = 0;
int dnum = 0;   /* データ数 */

int main(){
  int data, status, i;

  while (1) {
    printf("input>> ");
    status = scanf("%d", &data);
    if (status != 1) break;
    /* 入力値が0の場合はデータ取り出し、それ以外ならデータを
       キューに追加する */
    if (data == 0) printf("  Data: %d\n", dequeue() );
    else enqueue(data);

    printf("  [Queue] ");   /* 処理後にキューの内容を表示してみる */
    for ( i=0; i<dnum; i++ ) printf("%d ", queue[(head+i)%QSIZE]);
    printf("\n");
  }

  return 0;
}

void enqueue(int num){

  if (dnum >= QSIZE) {
    /* キューがいっぱいの場合のエラー処理 */
    printf("Queue overflow!\n");
    exit (2);
  }

  queue[(head+dnum++)%QSIZE] = num;
}

int dequeue(void){
  int val;

  if (dnum == 0) {
    /* キューが空の場合のエラー処理 */
    printf("Queue is empty!\n");
    exit (3);
  }

  val = queue[head];
  head = (head+1)%QSIZE;
  dnum--;
  return val;
}

% 演算子を使わず if 文で添字を計算する場合の例(プログラムの一部のみ)
main関数のキュー表示部分(int ih;を前もって宣言しておく)

    printf("  [Queue] ");   /* 処理後にキューの内容を表示してみる */
    for ( i=0; i<dnum; i++ ){
      ih = head+i;
      if (ih >= QSIZE) ih = ih - QSIZE;
      printf("%d ", queue[ih]);
    }
    printf("\n");

enqueue関数のうちデータ挿入部(int ih;を前もって宣言しておく)

  ih = head+dnum;
  if (ih >= QSIZE) ih = ih - QSIZE;
  queue[ih] = num;
  dnum++;

dequeue関数のうちデータ取り出し部

  val = queue[head];
  head++;
  if (head == QSIZE) head = 0;
  dnum--;

Extra問題

E-1 空気抵抗を考慮した落下運動

ファイル名: ex13e1.c

#include <stdio.h>

#define G  9.80     /* 重力加速度 */
#define VISC 1.8e-5 /* 空気の粘性係数 */

int main (){
  double v, x, t=0.0, tmax, a, m, c_m;
  double dt=0.00001;     /* タイムステップの値(十分小さくとること) */
  double dtp, tp=0.0;   /* 出力タイミング調整用 */
  double pi = 3.14159265358979; /* 円周率 */


  printf("初期状態の速度、位置と、計算する時間を入力してください\n");
  scanf( "%lg%lg%lg", &v, &x, &tmax );
  printf("物体の半径と質量を入力してください\n");
  scanf( "%lg%lg", &a, &m );

  /* Stokesの抵抗法則:F = 6 * pi * a * viscosity * v
    c_m * v = 粘性による加速度 となるように c_m を定める */
  c_m = 6 * pi * a * VISC / m;

  printf("出力の間隔を入力してください: ");
  scanf("%lg", &dtp);
  if (dtp < dt) dtp = dt; /* おかしな入力は修正 */


  /* 最初の出力 */
  printf( "    時間     位置     速度  \n" );
  printf( "%8.4f %8.4f %8.4f\n", t, x, v );

  /* 粘性抵抗がある場合の落下の計算 */
  while (t < tmax-dt/10.0){ /* tmax秒になったら終了(少し余裕を持たせる) */
    t += dt;
    x += v * dt;    /* 位置を更新 */
    v += (-G -c_m*v) * dt;   /* 速度を更新 */

    tp += dt;   /* 一つ前の出力からの時間をカウント */
    if (tp > dtp-dt/10.0) { /* 指定した時間が経過したら結果を出力 */
      printf( "%8.4f %8.4f %8.4f\n", t, x, v );
      tp = 0.0;   /* 出力用時間カウンタをリセット */
    }
  }

  return 0;
}
Personal tools