/*
* 20150605-02-QQQQ.c
*
* 自然数の階乗を返す関数
*
* コンパイル :
* cc -I../include -c 20150605-02-QQQQ.c
* cc -o 20150605-02-QQQQ.exe 20150605-02-QQQQ.o
* 実行 :
* ./20150605-02-QQQQ.exe
*
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
/*
* int factrial ( int n )
* int n : 階乗を計算する自然数
* 返り値 : n! ( n の階乗 )
*/
int factrial ( int n ) {
if ( n <= 0 ) { /* 0!, 負の数の階乗は、取り敢えず 1 にする */
return 1; /* 特に 「0! = 1」に注意 */
} else { /* n が正の時は、「n! = n * (n-1)!」となるので.. */
return n * factrial ( n - 1 ); /* 再帰呼び出し */
/*
自然数の階乗を返す関数
n! = n * (n-1) * ... * 2 * 1 曖昧なのでだめ
n! = if ( n > 0 ) { 厳密な「再帰」の考えを使う方法
n * ((n-1)!)
} else {
1
}
*/
}
}
/*
* main
*/
int main( void )
{
s_print_int ( 3 );
s_print_string ( " の階乗の値は " );
s_print_int ( factrial ( 3 ) );
s_print_string ( " になります。\n" );
s_print_int ( 5 );
s_print_string ( " の階乗の値は " );
s_print_int ( factrial ( 5 ) );
s_print_string ( " になります。\n" );
return 0;
}
/*
m,n 非負の整数とする
m,n の最大公約数を d=(m,n) で表現する
数学的な性質
m >= n の時、(m,n) = (m-n,n) (@)
(m,n) = (n.m)
(m,0) = m 停止条件として利用
(0,n) = n 停止条件として利用
(m,n)=(n,(m%n)) (@) を繰り返し適用する
ユークリッドの互除法は、上の性質を利用する
(m,n) =
if ( m == 0 ) { 停止条件
n
} else if ( n == 0 ) { 停止条件
m
} else if ( m >= n ) {
(m-n,n)
} else {
(n-m,m)
}
*/
/*
* 20150605-03-QQQQ.c
*
* 二つの整数の最大公約数を返す
*
* コンパイル :
* cc -I../include -c 20150605-03-QQQQ.c
* cc -o 20150605-03-QQQQ.exe 20150605-03-QQQQ.o
* 実行 :
* ./20150605-03-QQQQ.exe
*
*
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
/*
* int euclid ( int a, int b )
* int a : 非負の整数
* int b : 非負の整数
* 返り値 : a と b の最大公約数を返す
*/
int euclid ( int a, int b ) {
if ( b == 0 ) { /* 任意の数 a と 0 の最大公約数 (a,0) は a となる */
return a;
} else { /* b が 0 でない時 (a,b) = (b,a%b) となる */
return euclid ( b, (a%b) );
/*
b > 0 -> b > (a%b)
一番最初に a < b
euclid ( a, b )
a % b -> a
-> euclid ( b, a ) になる
*/
/*
** この部分を完成させなさい
*/
}
}
/*
* main
*/
int main( void )
{
s_print_int ( 12 );
s_print_string ( " と、 " );
s_print_int ( 18 );
s_print_string ( " の最大公約数は " );
s_print_int ( euclid( 12, 18 ) );
s_print_string ( " です。\n" );
s_print_int ( 1111 );
s_print_string ( " と、 " );
s_print_int ( 111111 );
s_print_string ( " の最大公約数は " );
s_print_int ( euclid( 1111, 111111 ) );
s_print_string ( " です。\n" );
return 0;
}
/*
* CDATE FILENAME
*
* 数当てを行う
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
#include "s_input.h" /* s_input_int を利用するので.. */
/*
* prompt
* メッセージを出力し、キーボードから整数値を読み込んで、
* その値を返す関数
*/
int prompt(void) {
s_print_string ( "私が選んだ数を予想して入力してください : " );
return s_input_int();
}
/*
*/
void game ( int input, int answer ) {
if ( input == answer ) { /* 入力と答えが一致した */
s_print_string ( "お見事です。あたりました。\n" );
} else {
if ( input > answer ) { /* 入力が、答えより大きい */
s_print_string ( "その数は大きすぎます。\n" );
} else { /* 入力が、答えより小さい */
s_print_string ( "その数は小さすぎます。\n" );
}
/* 未だ、答えが、当っていないので、ゲームを続ける.. */
game ( prompt(), answer );
}
}
/*
* main
*/
int main( void )
{
s_print_string ( "乱数を初期化しますので、整数を一つ入力してください : " );
srand ( s_input_int() ); /* 乱数の初期化 */
s_print_string ( "私が考えた 1 〜 100 の数を予想して当ててみてください。\n" );
game ( prompt(), (rand()%100) + 1 );
return 0;
}
#include <stdio.h>
/*
* 偶数奇数を判定して、答える
*/
void parity ( int number ) {
if ( number % 2 == 0 ) {
/* number を 2 割った余り ( A % B ... A を B 割った余り ) が 0 */
/* <-> number が偶数 */
printf ( "偶数\n" );
} else { /* 余りはおそらく 1 だろうが.. いずれにせよ .. */
printf ( "奇数\n" );
}
}
int main(int argc, char *argv[] ) {
parity ( 2 ); /* 2 は、偶数なので、「偶数」と表示される */
parity ( 7 ); /* 7 は、奇数なので、「奇数」と表示される */
return 0;
}
#include <stdio.h>
/*
再起の考え方
「再起呼び出し」そのものは、
関数を定義するときに、その本体に、自分自身を呼び出す
単純に、自分を呼び出すと、とまらなくなる
*/
void infinity() {
printf ( "Hello, World\n" );
infinity(); /* 何も考えずに、再起呼び出しをする */
}
int main(int argc, char *argv[] ) {
printf ( "はじめます。何か入力してください " );
getchar(); /* まつ */
infinity(); /* やってしまった... */
printf ( "もどってきました.. ?\n" );
return 0;
}
#include <stdio.h>
/*
再起の考え方
「再起呼び出し」そのものは、
関数を定義するときに、その本体に、自分自身を呼び出す
単純に、自分を呼び出すと、とまらなくなる
繰り返し回数を有限にするには、
続けるかどうかを判断する if 文と組み合わせる
「状態:引数」を持つ必要がある
「状態」は、必ず、終わりに「近づける」必要がある
*/
void finit( int times ) {
/*
引数 times は、繰り返す回数(状態)を表現している
*/
if ( times == 0 ) { /* やめる条件 */
/* もう何もしない */
} else {
/* まだ、続ける */
printf ( "Hello, World\n" );
finit( times - 1 ); /* 考えて、再起呼び出しをする */
}
}
int main(int argc, char *argv[] ) {
printf ( "はじめます。何か入力してください " );
getchar(); /* まつ */
finit( 10 ); /* 安心して、呼べる */
printf ( "もどってきました.. ?\n" );
return 0;
}
#include <stdio.h>
/*
再起の考え方
「再起呼び出し」そのものは、
関数を定義するときに、その本体に、自分自身を呼び出す
単純に、自分を呼び出すと、とまらなくなる
繰り返し回数を有限にするには、
続けるかどうかを判断する if 文と組み合わせる
「状態:引数」を持つ必要がある
「状態」は、必ず、終わりに「近づける」必要がある
*/
void finit( int times ) {
/*
引数 times は、繰り返す回数(状態)を表現している
*/
if ( times == 0 ) { /* やめる条件 */
/* もう何もしない */
} else {
/* まだ、続ける */
printf ( "Hello, World\n" + times );
finit( times - 1 ); /* 考えて、再起呼び出しをする */
}
}
int main(int argc, char *argv[] ) {
printf ( "はじめます。何か入力してください " );
getchar(); /* まつ */
finit( 10 ); /* 安心して、呼べる */
printf ( "もどってきました.. ?\n" );
return 0;
}
#include <stdio.h>
/*
再起の考え方
「再起呼び出し」そのものは、
関数を定義するときに、その本体に、自分自身を呼び出す
単純に、自分を呼び出すと、とまらなくなる
繰り返し回数を有限にするには、
続けるかどうかを判断する if 文と組み合わせる
「状態:引数」を持つ必要がある
「状態」は、必ず、終わりに「近づける」必要がある
*/
void finit( int times ) {
/*
引数 times は、繰り返す回数(状態)を表現している
*/
if ( times == 0 ) { /* やめる条件 */
/* もう何もしない */
} else {
/* まだ、続ける */
if ( times == 1 ) { /* times の値に基づいて色々 */
printf ( "こんにちわ\n" );
} else if ( times == 2 ) {
printf ( "Hello\n" );
} else if ( times == 3 ) {
printf ( "こんばんわ\n" );
} else if ( times == 4 ) {
printf ( "Good bye\n" );
} else {
if ( times % 2 == 0 ) {
printf ( "ありがとう\n" );
} else {
printf ( "ごちそうさま\n" );
}
}
finit( times - 1 ); /* 考えて、再起呼び出しをする */
}
}
int main(int argc, char *argv[] ) {
printf ( "はじめます。何か入力してください " );
getchar(); /* まつ */
finit( 10 ); /* 安心して、呼べる */
printf ( "もどってきました.. ?\n" );
return 0;
}
#include <stdio.h>
/*
再起の考え方
「再起呼び出し」そのものは、
関数を定義するときに、その本体に、自分自身を呼び出す
単純に、自分を呼び出すと、とまらなくなる
繰り返し回数を有限にするには、
続けるかどうかを判断する if 文と組み合わせる
「状態:引数」を持つ必要がある
「状態」は、必ず、終わりに「近づける」必要がある
*/
/*
finit の作り方(パターン) は、
times (非負の整数値を指定する) 回だけ、
(@)
の行の命令を繰り返す
*/
void finit( int times ) {
/*
引数 times は、繰り返す回数(状態)を表現している
*/
if ( times == 0 ) { /* やめる条件 */
/* もう何もしない */
} else {
/* まだ、続ける */
/*printf ( "Hello, World\n" );*/
printf ( "こんにちわ、みなさん\n" ); /* (@) */
finit( times - 1 ); /* 考えて、再起呼び出しをする */
}
}
int main(int argc, char *argv[] ) {
printf ( "はじめます。何か入力してください " );
getchar(); /* まつ */
finit( 10 ); /* 安心して、呼べる */
printf ( "もどってきました.. ?\n" );
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
値を返す関数(先週新しくやった)
関数の前に void ではなく、値の型を書く
「return 式」で、値を計算する「式」を記述し、その
式の値が、関数の値になる
*/
/*
例 :
二つの整数値を引数として、取り
その二つの整数値の「和」を値として返す関数
! 「整数値の和」は、「整数値(int 型)」
*/
int int_add(int a, int b) {
return a + b; /* a と b の和を返す */
/* return の後ろには、「式」がかかれるが
実際に値して返るのは「式」の計算した値
が返る (式が返るわけではない) */
}
int main(int argc, char *argv[] ) {
printf ( "12 と 34 の和は " );
s_print_int ( int_add ( 12, 34 ) );
/* 関数の値は、式の中で利用することができる */
/* ! 関数の引数は、「式」を指定する */
printf ( " です\n" );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
/*
考えてみると...
いきなり出力 -> 変化はない
プログラムを作成した段階で、動作が確定している
入力によって、様々な場合に対する
処理(答え)を得たい
プログラムの基本構造
入力 -> 処理 -> 出力
*/
putchar ( getchar() - 'A' + 'a' );
/* ^^^^^^^ 入力 (一文字:大文字)
^^^^^^^^^^^^^^^^^^^^^^ 処理 (大文字を小文字)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 出力
*/
putchar ( '\n' ); /* 改行 (出力) */
/*
入力が大文字以外だと、ちゃんと動かない
-'A'+'a'が意味を持つのは、大文字の時のみ
本来なら、大文字か小文字かを判定して、処理をすべき
<<入力>>
入力は、関数呼び出しをしているので、「直接」には、
「その値が、一度しか利用」できない
入力した、結果を関数の引数として渡す
関数の中では、その値が、変数に入っているので、
その変数を何度でも参照して、(入力された)情報を、
複数回、利用できる。
*/
return 0;
}
#include <stdio.h>
/*
関数:
引数として、文字を入力とし、
それが大文字なら、小文字にして返す
そうでなければ、そのまま返す関数
*/
char to_lower ( char ch ) {
if ( 'A' <= ch ) {
if ( ch <= 'Z' ) {
/* 大文字だった */
return ch - 'A' + 'a'; /* 小文字に変換して返す */
} else {
}
} else {
}
return ch; /* 元の文字をそのまま返す */
}
int main(int argc, char *argv[] ) {
putchar ( to_lower ( getchar() ) );
putchar ( '\n' );
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
複数の入力を処理したい
三文字の数字を入力し、数字列が表す数に 1 を加えた数を表示する
例 :
123 -> 124
999 -> 1000
*/
int main(int argc, char *argv[] ) {
printf ( "数字を一文字入力する : " );
s_print_int ( getchar() ); /* 一文字入力して、整数値として出力 */
s_print_newline();
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
複数の入力を処理したい
三文字の数字を入力し、数字列が表す数に 1 を加えた数を表示する
例 :
123 -> 124
999 -> 1000
*/
int main(int argc, char *argv[] ) {
printf ( "数字を一文字入力する : " );
s_print_int ( getchar() - '0' ); /* 一文字入力して、整数値として出力 */
/* n の数字に対応する数値 n が得られる */
s_print_newline();
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
複数の入力を処理したい
三文字の数字を入力し、数字列が表す数に 1 を加えた数を表示する
例 :
123 -> 124
999 -> 1000
*/
int main(int argc, char *argv[] ) {
printf ( "数字を一文字入力する : " );
s_print_int ( getchar() - '0' + 1 ); /* 一文字入力して、整数値として出力 */
/* n の数字に対応する数値 n が得られる */
s_print_newline();
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
複数の入力を処理したい
三文字の数字を入力し、数字列が表す数に 1 を加えた数を表示する
例 :
123 -> 124
999 -> 1000
*/
int main(int argc, char *argv[] ) {
printf ( "数字を三文字入力する : " );
s_print_int (((getchar() - '0')*100 + (getchar() - '0') * 10 + getchar() - '0') + 1 );
/* 「三文字」という入力の長さがわかっているからできる */
/* 長さがわからない
何回読むかも分からない
何回 getchar() を呼ぶかもわからない
プログラムの命令の実行回数が変化する
再帰を利用すればよい
*/
s_print_newline();
return 0;
}
#include <stdio.h>
#include "s_print.h"
/*
数字列を入力する
最後に改行をいれることにより、数字列も終わると考える
数字列をキーボードから入力して、その数字列が表す、
整数値を返す関数を考える
"123\n" -> 123
'1' 続きがあるかもしれない。
すぐに、\n くるかもしれない
とりあえず、ここまでの結果を num にいれる
num <- 1
num <- ch - '0'
'2' 続きがあるかもしれない。
すぐに、\n くるかもしれない
とりあえず、ここまでの結果を num にいれる
num <- 12 ... 1 * 10 + 2
num <- num * 10 + ch - '0'
*/
int input_int ( char ch, int num ) { /* 入力した結果を何度も利用するので、
先読みをする */
if ( ch == '\n' ) {
return num; /* ch == '\n' num が結果 */
} else {
return input_int ( getchar(), num * 10 + ch - '0' );
}
}
int main(int argc, char *argv[] ) {
s_print_string ( "数字列を入力し、最後に[Enter]する : " );
s_print_int ( input_int( getchar(), 0 ) );
s_print_newline();
return 0;
}
#include <stdio.h>
#include <stdlib.h> /* rand 関数を利用するので、その宣言を読み込む */
#include "s_print.h"
#include "s_input.h"
/*
rand()
呼び出すたびに、異なる数値を返す「乱数関数」である。
これを利用して...
ゲームを作ったり
シミュレーションを行ったりする
[注意]
ただし、毎回、同じ数列なので、それがいやなら、
srand を使って、乱数列を変更すればよい
*/
int main(int argc, char *argv[] ) {
s_print_string ( "何か数値を入力してください(乱数初期化に使います) : " );
srand ( s_input_int() ); /* 入力した数値で、乱数を初期化 */
/* よくあるのは、時刻を利用する方法 */
s_print_int ( rand() ); /* 同じことを三回してるだけだが... */
s_print_newline();
s_print_int ( rand() );
s_print_newline();
s_print_int ( rand() );
s_print_newline();
return 0;
}
Download : 20160701-01.c ( utf8 版 )
/*
* CDATE FILENAME
*
* 数当てを行う
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
#include "s_input.h" /* s_input_int を利用するので.. */
/*
* prompt
* メッセージを出力し、キーボードから整数値を読み込んで、
* その値を返す関数
*/
int prompt(void) {
s_print_string ( "私が選んだ数を予想して入力してください : " );
return s_input_int();
}
/*
*/
void game ( int input, int answer ) {
if ( input == answer ) { /* 入力と答えが一致した */
s_print_string ( "お見事です。あたりました。\n" );
} else {
if ( input > answer ) { /* 入力が、答えより大きい */
/*
** この部分を完成させなさい
*/
} else { /* 入力が、答えより小さい */
s_print_string ( "その数は小さすぎます。\n" );
}
/* 未だ、答えが、当っていないので、ゲームを続ける.. */
/*
** この部分を完成させなさい
*/
}
}
/*
* main
*/
int main( void )
{
s_print_string ( "私が考えた 1 〜 100 数を予想して当ててみてください。\n" );
game ( prompt(), (rand()%100) + 1 );
return 0;
}
50 75 83 90 85 84
$ ./20160701-01-QQQQ.exe 私が考えた 1 〜 100 数を予想して当ててみてください。 私が選んだ数を予想して入力してください : 50 その数は小さすぎます。 私が選んだ数を予想して入力してください : 75 その数は小さすぎます。 私が選んだ数を予想して入力してください : 83 その数は小さすぎます。 私が選んだ数を予想して入力してください : 90 その数は大きすぎます。 私が選んだ数を予想して入力してください : 85 その数は大きすぎます。 私が選んだ数を予想して入力してください : 84 お見事です。あたりました。 $
Download : 20160701-02.c ( utf8 版 )
/*
* CDATE FILENAME
*
* 与えられた自然数の素因数を出力する
*
* 12 は..
*
*
*
*
*
*
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
/*
* void print_prime_factor_sequence ( int n, int p )
* 機能 : p 以上の n の素因数を小さい順に並べで表示する
* 条件 : n には p 未満の素因数を含まれていないものとする
* int n : p 未満の素因数を含まれていない自然数
* 返り値 : なし
*/
void print_prime_factor_sequence ( int n, int p ) {
if ( p > n ) { /* もう n には p 以上の素因数を含まない */
/* 何もしなくてよい */
/* 本来、ここにくるのは n = 1 の時だが、念の為 */
} else if ( n % p == 0 ) { /* n が p を素因数として含む */
s_print_char ( ' ' ); /* 隙間を空け */
s_print_int ( p ); /* 素因数を表示し */
/* もう一度 p の要素があるかもしれないので、そこから試す [再帰] */
/*
** この部分を完成させなさい
*/
} else { /* n が p を素因数として含まない */
/* 本来は p の次の素数を試すべきだが.. */
/* その代りに p + 1 を試す (のは無駄だが、正く動く) [再帰] */
/*
** この部分を完成させなさい
*/
}
}
/*
* void print_prime_factor_of ( int n )
* 機能 : n の素因数を出力する
* int n : 素因数を表示したい自然数
* 返り値 : なし
*/
void print_prime_factor_of ( int n ) {
if ( n < 1 ) { /* 与えらた数が自然数ではない */
s_print_int ( n );
s_print_string ( "は、自然数ではありません\n" );
} else if ( n == 1 ) { /* 与えられた数が 1 の場合 */
s_print_int ( n );
s_print_string ( "の素因数はありません\n" );
} else {
s_print_int ( n );
s_print_string ( "の素因数分解は" );
/*
** この部分を完成させなさい
*/
s_print_string ( " となります。\n" );
}
}
/*
* main
*/
int main( void )
{
print_prime_factor_of ( 12 );
return 0;
}
$ ./20160701-02-QQQQ.exe 12の素因数分解は 2 2 3 となります。 $