#include <stdio.h>
/*
あること(命令)を繰り返したい
=> 「Hello, World」を出力
繰り返し : 同じ事を k 回数行う
=> k をどうするか ?
例: 繰り返す回数を 3 とした場合... ??
ここでは、
1. 文字列には長さがある
例 : "abc" => 長さ 3
2. (原理は不明だが..) 文字列に +1 すると、文字列の長さは
短くなる
3. 文字列を、短くしてゆく(+1 する)と、最後に "" 空文字列になる
=> 条件判定で、判断(チェック)できる
という文字列の性質を利用し
繰り返し回数を文字列(の長さ)で表現する
例 : 3 という回数を示すのに、"abc" 長さ 3 の文字列を利用する
times_hello ( "abc" );
=> 3 回、「Hello, World」を表示する
*/
void times_hello (char *n ) {
/* 引数 n は、文字列だが、中身はどうでもよくて、長さだけが重要 */
/* 繰り返しのパターン[再帰] */
if ( !strcmp ( n, "" ) ) {
/* 空文字列 : 長さが 0 ということ... */
/* 繰り返しの回数が、0 なので、なにもしないで「終わり」にしてよい */
} else {
/* 少なくても、一度は、Hello World を出す必要がある */
/* 繰り返したい命令 */
printf ( "Hello, World\n" );
/* 残りは ? ( やりたい目的の回数 - 1 回 )*/
times_hello ( n + 1 );
/* 残りは、再帰呼び出しにする */
/* ポイントは、引数の文字列に +1 する事により、
長さを 1 つだけ、短くする(繰り返し回数が 1 減る ) */
}
}
int main(void) {
printf ( "3 回数出力\n" );
times_hello ( "123" );
printf ( "10 回数出力\n" );
times_hello ( "1234567890" );
return 0;
}
#include <stdio.h>
int main(void) {
putchar ( 'A' ); /* 画面に「A」という文字を出力する */
/* 「文字」を出すので「'A'」という形 */
/* 「文字」を扱うので putchar を利用している */
/* cf.
printf ( "A" );
*/
putchar ( '\n' ); /* 「\n」は「改行」を表す「文字」 */
return 0;
}
#include <stdio.h>
int main(void) {
putchar ( getchar() ); /* キーボードから一文字読み込む(getchar)
その文字を画面に出す(putchar) */
putchar ( '\n' ); /* 「\n」は「改行」を表す「文字」 */
return 0;
}
#include <stdio.h>
/*
三文字入力して、三文字出力する
*/
int main(void) {
putchar ( getchar() );
putchar ( getchar() );
putchar ( getchar() );
/* 関数合成を行っている事に注意 */
/* 順接のもう一つの形 */
/* getchar() => putchar() : 二つの関数を順序付けている */
putchar ( '\n' ); /* 「\n」は「改行」を表す「文字」 */
return 0;
}
#include <stdio.h>
/*
入力が、毎回、1 文字 + 改行になる事を想定して、画面に出す
*/
int main(void) {
putchar ( getchar() ); /* 入力された文字列 */
getchar(); /* 次に「改行」が来るはずだが、読み飛ばす */
putchar ( '?' );
putchar ( '\n' );
putchar ( getchar() ); /* 入力された文字列 */
getchar(); /* 次に「改行」が来るはずだが、読み飛ばす */
putchar ( '?' );
putchar ( '\n' );
putchar ( getchar() ); /* 入力された文字列 */
getchar(); /* 次に「改行」が来るはずだが、読み飛ばす */
putchar ( '?' );
putchar ( '\n' );
putchar ( '\n' ); /* 「\n」は「改行」を表す「文字」 */
return 0;
}
#include <stdio.h>
/*
目的
Turtle Grapics をしたい
プログラム作成上の注意
#include "s_turtle.h"
を冒頭にいれる
プログラムを実行する場合は、
make test BASE=ファイルのベース名とする
例: p-006.c を実行するには、
make test BASE=p-006
とする。
# getchar() が最後にあるので、[Enter] キーを
# 押さないと、プログラムが終了しない事に注意
*/
#include "s_turtle.h" /* turtle graphics をする場合の追加のおまじない */
/*
命令
Turtle Graphics で利用できる命令
s_turtle_move(); : 現在の位置に足跡を残し、現在の方向に一歩進みます
s_turtle_jump(); : 現在の位置に足跡を残さず、現在の方向に一歩進みます
s_turtle_turn(); : 現在の方向を時計回りに 45 度変更します
s_turtle_stop(); : 亀プログラムの終了 (「return 0;」の直前に実行)
*/
int main(void) {
/* Turtle Graphics の命令を書く */
s_turtle_move(); /* 亀への命令をする */
/* 亀は、今いる場所に、足跡を残し、
自分が向いている方向に一歩進む */
/* 結果的に、画面に「足跡」が一歩(一点)だけ残る */
getchar(); /* いきなり終了せず、いったん改行を待つ */
s_turtle_stop();
return 0;
}
#include <stdio.h>
#include "s_turtle.h"
int main(void) {
/* Turtle Graphics の命令を書く */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
getchar();
s_turtle_stop();
return 0;
}
#include <stdio.h>
#include "s_turtle.h"
/* 一辺の長さが 10 である正方形を書くプログラム */
/*
+---+
| | 一辺の長さが 10
+---+
1) 10 回 move すれば、長さ 10 直線がかける
2) 2 回 turn すれば、90 度(直角)の向きがかえられる
3) 正方形は、直角に交わる 4 辺からなる
*/
int main(void) {
/* Turtle Graphics の命令を書く */
/* 左辺 */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
/* 上辺 */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
/* 右辺 */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
/* 下辺 */
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
getchar();
s_turtle_stop();
return 0;
}
#include <stdio.h>
#include "s_turtle.h"
/* 一辺の長さが 10 である正方形を書くプログラム */
/*
関数を利用して、プログラムを整理しよう..
*/
/*
move_ten()
10 歩進む
*/
void move_ten(void) {
s_turtle_move(); /* 10歩,歩きながら、足跡を残す */
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
s_turtle_move();
}
/*
turn_R()
90 度向き変える
*/
void turn_R(void) {
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
}
int main(void) {
/* Turtle Graphics の命令を書く */
/* 左辺 */
move_ten();
turn_R();
/* 上辺 */
move_ten();
turn_R();
/* 右辺 */
move_ten();
turn_R();
/* 下辺 */
move_ten();
getchar();
s_turtle_stop();
return 0;
}
#include <stdio.h>
#include "s_turtle.h"
/* 一辺の長さが 10 である正方形を書くプログラム */
/*
関数を利用して、プログラムを整理しよう..
*/
/*
move_n
n 歩 move する(n は引数で、繰り返し回数を指定する )
=> 引数に文字列を指定して、その長さだけ繰り返す
*/
void move_n(char *times) {
if ( !strcmp ( times, "" ) ) {
} else {
s_turtle_move();
move_n ( times + 1 );
}
}
/*
move_ten()
10 歩進む
*/
void move_ten(void) {
move_n ( "1234567890" );
}
/*
turn_R()
90 度向き変える
*/
void turn_R(void) {
s_turtle_turn(); /* 亀の向きを 45 度変える */
s_turtle_turn(); /* 亀の向きを 45 度変える */
}
/*
辺の長さが 10 を書く
rect_ten
*/
void rect_ten(void) {
/* 左辺 */
move_ten();
turn_R();
/* 上辺 */
move_ten();
turn_R();
/* 右辺 */
move_ten();
turn_R();
/* 下辺 */
move_ten();
}
int main(void) {
/* Turtle Graphics の命令を書く */
rect_ten(); /* 辺の長さが 10 の正方形 */
/* さらに、30 の正方形も *
getchar();
s_turtle_stop();
return 0;
}
#include <stdio.h>
#include "s_turtle.h"
/* 一辺の長さが n である正方形を書くプログラム */
/*
move_n
n 歩 move する(n は引数で、繰り返し回数を指定する )
=> 引数に文字列を指定して、その長さだけ繰り返す
*/
void move_n(char *times) {
if ( !strcmp ( times, "" ) ) {
} else {
s_turtle_move();
move_n ( times + 1 );
}
}
void turn_n(char *times) {
if ( !strcmp ( times, "" ) ) {
} else {
s_turtle_turn();
turn_n ( times + 1 );
}
}
/*
turn_R()
90 度向き変える
*/
void turn_R(void) {
turn_n ( "01" );
}
/*
辺の長さが n の正方形を書く
rect_n
*/
void rect_n(char *length) {
/* 左辺 */
move_n(length);
turn_R();
/* 上辺 */
move_n(length);
turn_R();
/* 右辺 */
move_n(length);
turn_R();
/* 下辺 */
move_n(length);
turn_R();
}
int main(void) {
/* Turtle Graphics の命令を書く */
rect_n("1234567890" ); /* 辺の長さが 10 の正方形 */
/* 外側の正方形の書き出し位置と向きを調整すればよい */
/* 今いるところから、左下に 10 歩のところにゆけばよい */
turn_n ( "12345" ); /* 亀の向きを右下に向ける */
move_n ( "1234567890" ); /* 10 歩歩く */
turn_n ( "123" ); /* 亀の向きを上に戻す */
/* さらに、30 の正方形も */
rect_n( "123456789012345678901234567890" ); /* 辺の長さが 10 の正方形 */
getchar();
s_turtle_stop();
return 0;
}
BASE=p-001
all : ${BASE}.exe
${BASE}.exe : ${BASE}.o
cc -o ${BASE}.exe ${BASE}.o
${BASE}.o : ${BASE}.c
cc -c ${BASE}.c
test : ${BASE}.exe
./${BASE}.exe
[復習]
前回、再帰呼び出しを利用した、繰り返し
繰り返しのパターン
k 回、繰り返したい場合
長さ k の文字列 n を引数として指定して、再帰呼び出しをする
1. 関数の名前決める
2. 次のひな型を作る
void 関数名 ( char *n ) {
if ( !strcmp ( n, "" ) ) {
/* なにもしない */
} else {
/* 繰り返したい命令 : 再帰とは無関係でよい */
/* 「ここ」*/
/* 再帰 */
関数名 ( n + 1 );
}
}
3. 繰り返したい命令を「ここ」のところに挿入
4. 繰り返しを実行する場合
関数名 ( 繰り返す回数の長さ文字列 );
[今日の目標]
「繰り返し」に慣れる
命令が「文字列のプリント」だけではつまらないので、
絵を描く事を考える
文字
C 言語では、「文字」を、表すためには、
「'」 + その文字を表す文字(一字) + 「'」
例 : 「'A'」は、「A」という文字を表す C 言語の表現
特殊な例として '\' で始まる二文字で一文字を表す場合もある
例 : '\n' => 改行一文字
'\0' => NUL 文字(空文字) が実は、文字列の最後にある
'\\' => 「\」という文字を表す
# Windows では「\(円マーク)」
# Ubuntu では「\(バックスラッシュ)」になる
cf. 「"A"」は、「A」という文字を一つ含む文字列
文字を出力するときには、
putchar 関数を利用する
例 : 「A」という文字を出力する場合は、
putchar ( 'A' );
とする。
文字を入力するときには、
getchar() 関数が利用できる
getchar() を呼び出すと、キーボードから、一文字
読み込み、その一文字が、「関数の値」となる
例 : キーボードから、一文字入力し、それを画面に出すには、
putchar ( getchar() );
とする。
putchar の引数は、「文字」でなければならないが、
getchar が返す値が「文字」なので、うまくゆく
# 入力は、[Enter] キーが押されるまで、待つ仕組みになっている
# 待つ事を目的として getcharを使う
BASE=p-001
all : ${BASE}.exe
${BASE}.exe : ${BASE}.o
cc -o ${BASE}.exe ${BASE}.o
${BASE}.o : ${BASE}.c
cc -c ${BASE}.c
test : ${BASE}.exe
./${BASE}.exe
Download : 20180601-01.c
/*
* 20180601-01-QQQQ.c
* 与えられた文字列の文字を二度ずつ出力する関数を作成する
*/
#include <stdio.h>
#include <strings.h>
/*
* double_print
* 与えられた文字列(message)の文字を二度ずつ出力する
*/
void double_print ( char *message ) {
if ( !strcmp ( message, "" ) ) { /* 空文字列だった */
/* なにもする必要はない */
} else {
putchar ( *message ); /* 取り敢えず、一つ分は出す */
/*
** この部分を完成させなさい
*/
double_print ( message + 1 ); /* 再帰呼出しをする */
}
}
/*
* main
*/
int main ( void ) {
double_print ( "abc" );
printf ( "\n" );
double_print ( "1234567" );
printf ( "\n" );
return 0;
}
$ ./20180601-01-QQQQ.exe aabbcc 11223344556677 $
Download : 20180601-02.c
/*
* 20180601-02-QQQQ.c
* 与えられた文字列の文字を逆順に出力する関数を作る
*/
#include <stdio.h>
#include <strings.h>
/*
* reverse_print
* 与えられた文字列(message)の文字を逆順に出力する
*/
void reverse_print ( char *message ) {
if ( !strcmp ( message, "" ) ) { /* 空文字列だった */
/* なにもする必要はない */
} else {
/* ここで再帰呼出しを行うのだが... */
/*
** この部分を完成させなさい
*/
}
}
/*
* main
*/
int main ( void ) {
reverse_print ( "abc" );
printf ( "\n" );
reverse_print ( "1234567" );
printf ( "\n" );
return 0;
}
$ ./20180601-02-QQQQ.exe cba 7654321 $