Ex13Ans
From Prog0
演習第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;
}
