Download : sample-001.c
/* * 2017/06/23 sample-001.c */ /* * 最初は取り敢えず「Hello, World」 */ #include <stdio.h> int main ( void ) { printf ( "Hello, World\n" ); /* "Hello, World" を出力 */ return 0; }
$ ./sample-001.exe Hello, World $
Download : sample-002.c
/* * 2017/06/23 sample-002.c */ /* * 順接 : 「Hello, World」を二度出す */ #include <stdio.h> int main ( void ) { printf ( "Hello, World\n" ); /* "Hello, World" を出力 */ printf ( "Hello, World\n" ); /* 命令を並べれば、並べた通りに実行 */ return 0; }
$ ./sample-002.exe Hello, World Hello, World $
Download : sample-003.c
/* * 2017/06/23 sample-003.c */ /* * 異る命令の実行 */ #include <stdio.h> int main ( void ) { printf ( "1 : Hello, World\n" ); /* 一度目の "Hello, World" を出力 */ printf ( "2 : Hello, World\n" ); /* ニ度目、「並べた順」に実行される */ return 0; }
$ ./sample-003.exe 1 : Hello, World 2 : Hello, World $
Download : sample-004.c
/* * 2017/06/23 sample-004.c */ /* * 「順接」の繰返し * A,B,C,D,E,F = (((((A,B),C),D),E),F) * 6 行の命令は、順接を 5 回行ったと考える */ #include <stdio.h> int main ( void ) { printf ( "1 : Hello, World\n" ); printf ( "2 : Hello, World\n" ); printf ( "3 : Hello, World\n" ); printf ( "4 : Hello, World\n" ); printf ( "5 : Hello, World\n" ); printf ( "6 : Hello, World\n" ); return 0; }
$ ./sample-004.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-005.c
/* * 2017/06/23 sample-005.c */ /* * 「順接」の繰返し * ブロック( {, } ) を利用して明示的に記述 */ #include <stdio.h> int main ( void ) { { { { { printf ( "1 : Hello, World\n" ); printf ( "2 : Hello, World\n" ); } printf ( "3 : Hello, World\n" ); } printf ( "4 : Hello, World\n" ); } printf ( "5 : Hello, World\n" ); } printf ( "6 : Hello, World\n" ); return 0; }
$ ./sample-005.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-006.c
/* * 2017/06/23 sample-006.c */ /* * 「順接」の繰返し * 同じ命令の繰返し */ #include <stdio.h> int main ( void ) { printf ( "Hello, World\n" ); /* 「Hello, World」を 6 度 */ printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); return 0; }
$ ./sample-006.exe Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-007.c
/* * 2017/06/23 sample-007.c */ /* * 命令列に名前を付ける (関数の作成) */ #include <stdio.h> /* 命令の断片「printf ( "Hello, World\n" );」に printHello という名前を付ける */ void printHello(void) { /* 関数の定義 */ printf ( "Hello, World\n" ); /* 「Hello, World」を出力する関数 */ } int main ( void ) { printHello(); /* 元々あったものと同じ */ /* 命令は、「関数名」で「呼出し」可能 */ /* 表現が「短く」なった */ printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); printf ( "Hello, World\n" ); return 0; }
$ ./sample-007.exe Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-008.c
/* * 2017/06/23 sample-008.c */ /* * 「関数の呼出し」の繰返し */ #include <stdio.h> void printHello(void) { printf ( "Hello, World\n" ); } int main ( void ) { printHello(); /* 一度定義した関数は何度でも呼出し可能 */ printHello(); printHello(); printHello(); printHello(); printHello(); return 0; }
$ ./sample-008.exe Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-009.c
/* * 2017/06/23 sample-009.c */ /* * 関数の本体には「命令列」が記述できる */ #include <stdio.h> void printHello(void) { printf ( "Hello, World\n" ); /* 「Hello, World」を出力する関数 */ } void printTwoHello(void) { /* printHello を二度呼ぶ */ printHello(); /* 本体には、「命令列」でもよい */ printHello(); } int main ( void ) { printTwoHello(); /* printTwoHello() を三度呼ぶ */ printTwoHello(); /* 結果的に printHello() が六度呼ばれる */ printTwoHello(); /* 最終的に 「Hello, World」が六行出力される */ return 0; }
A
$ ./sample-009.exe < sample-009.in Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-010.c
/* * 2017/06/23 sample-010.c */ /* * 似た命令の関数化 [1] */ #include <stdio.h> int main ( void ) { printf ( "1 : Hello, World\n" ); /* 命令が異っている場合は.. */ printf ( "2 : Hello, World\n" ); printf ( "3 : Hello, World\n" ); printf ( "4 : Hello, World\n" ); printf ( "5 : Hello, World\n" ); printf ( "6 : Hello, World\n" ); return 0; }
$ ./sample-010.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-011.c
/* * 2017/06/23 sample-011.c */ /* * 似た命令の関数化 [2] : 異る部分と同じ部分にわける */ #include <stdio.h> int main ( void ) { printf ( "1" ); /* 異る部分 */ printf ( " : Hello, World\n" ); /* 同じ部分 */ printf ( "2" ); printf ( " : Hello, World\n" ); printf ( "3" ); printf ( " : Hello, World\n" ); printf ( "4" ); printf ( " : Hello, World\n" ); printf ( "5" ); printf ( " : Hello, World\n" ); printf ( "6" ); printf ( " : Hello, World\n" ); return 0; }
$ ./sample-011.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-012.c
/* * 2017/06/23 sample-012.c */ /* * 似た命令の関数化 [3] : 異る部分を「変数化」する事により、関数に出来る */ #include <stdio.h> void printStringHello ( char *X ) { printf ( X ); /* 異る部分が変数(X:仮引数)で共通化 */ /* 仮引数 X (の「値」)は、実引数置き変る */ printf ( " : Hello, World\n" ); /* 同じ部分 */ } int main ( void ) { printStringHello ( "1" ); /* 異る部分を「実引数」として指定 */ /* 呼び出された関数の中の仮引数の値を 関数の呼出し元で指定できる */ printStringHello ( "2" ); printStringHello ( "3" ); printStringHello ( "4" ); printStringHello ( "5" ); printStringHello ( "6" ); return 0; }
$ ./sample-012.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-013.c
/* * 2017/06/23 sample-013.c */ /* * 似た命令の関数化 [4] : 引数の型 */ #include <stdio.h> void printCharHello ( char X ) { /* 変数の型を char 型に変更 */ putchar ( X ); /* X を「文字」出力 */ printf ( " : Hello, World\n" ); /* 同じ部分 */ } void printCharHello ( char X ) { /* 変数の型を char 型に変更 */ int main ( void ) { printCharHello ( '1' ); /* 引数も「文字」にする必要がある */ printCharHello ( '2' ); printCharHello ( '3' ); printCharHello ( '4' ); printCharHello ( '5' ); printCharHello ( '6' ); return 0; }
$ ./sample-013.exe 1 : Hello, World 2 : Hello, World 3 : Hello, World 4 : Hello, World 5 : Hello, World 6 : Hello, World $
Download : sample-014.c
/* * 2017/06/23 sample-014.c */ /* * 似た命令の関数化 [5] : 引数の計算 */ #include <stdio.h> void printCharHello ( char X ) { /* 変数の型を char 型に変更 */ putchar ( X ); /* X を「文字」出力 */ printf ( " : Hello, World\n" ); /* 同じ部分 */ } void printTwoCharHello ( char X ) { printCharHello ( X ); /* 一度目は、引数をそのまま */ printCharHello ( X + 1 ); /* ニ度目は、引数の値の次の値を利用 */ /* '1' + 1 -> '2' */ /* '3' + 1 -> '4' */ /* '5' + 1 -> '6' */ } int main ( void ) { printCharTwoHello ( '1' ); /* 三度呼ぶと.. */ printCharTwoHello ( '3' ); printCharTwoHello ( '5' ); /* 六行.. */ return 0; }
$ ./sample-014.exe $
Download : sample-015.c
/* * 2017/06/23 sample-015.c */ #include <stdio.h> /* * check_star_char */ void check_star_char ( char ch ) { if ( ch == '*' ) { /* ch の中身が '*' かどうかをチェック */ printf ( "これは「*」です\n" ); } else { printf ( "これは「*」ではありません\n" ); } } /* * main */ int main(void) { check_star_char ( getchar() ); /* getchar() で文字を読込み、それを出力 */ return 0; }
A
$ ./sample-015.exe < sample-015.in A これは「*」ではありません $
Download : sample-016.c
/* * 2017/06/23 sample-016.c */ /* * s_print.h の利用法 * * 利用方法 * コンパイル * cc -I ~/c/include sample-016.c * cc -I ~/c/include -o sample-016.exe sample-016.o * 実行 * ./sample-016.exe */ #include <stdio.h> #include "s_print.h" /* s_print.h を利用する */ /* */ int main ( void ) { printf ( "s_print_string で「文字列」を出力「" ); s_print_string ( "1" ); /* 文字列「1」を出力 */ printf ( "」\n" ); printf ( "s_print_int で「整数値」を出力「" ); s_print_int ( 1 ); /* 整数値「1」を出力 */ printf ( "」\n" ); printf ( "s_print_char で「文字」を出力「" ); s_print_char ( '1' ); /* 文字「1」を出力 */ printf ( "」\n" ); return 0; }
$ ./sample-016.exe s_print_string で「文字列」を出力「1」 s_print_int で「整数値」を出力「1」 s_print_char で「文字」を出力「1」 $
Download : sample-017.c
/* * 2017/06/23 sample-017.c */ /* * s_input.h の利用法 (1) * * 利用方法 * コンパイル * cc -I ~/c/include sample-017.c * cc -I ~/c/include -o sample-017.exe sample-017.o * 実行 * ./sample-017.exe */ #include <stdio.h> #include "s_print.h" /* s_print.h を利用する */ #include "s_input.h" /* s_input.h を利用する */ /* */ int main ( void ) { printf ( "文字列を入力して改行してください : " ); s_print_string ( s_input_string() ); printf ( "\n--------------------\n" ); printf ( "整数値を入力して改行してください : " ); s_print_int ( s_input_int() ); printf ( "\n--------------------\n" ); printf ( "文字を一文字入力して改行してください : " ); s_print_char ( s_input_char() ); printf ( "\n--------------------\n" ); return 0; }
abc 123 X
$ ./sample-017.exe < sample-017.in 文字列を入力して改行してください : abc abc -------------------- 整数値を入力して改行してください : 123 123 -------------------- 文字を一文字入力して改行してください : X X -------------------- $
Download : sample-018.c
/* * 2017/06/23 sample-018.c */ /* * s_input.h の利用法 (2) * * 利用方法 * コンパイル * cc -I ~/c/include sample-018.c * cc -I ~/c/include -o sample-018.exe sample-018.o * 実行 * ./sample-018.exe */ #include <stdio.h> #include "s_print.h" /* s_print.h を利用する */ #include "s_input.h" /* s_input.h を利用する */ /* * +1 した結果は、型によって異る。 */ int main ( void ) { printf ( "文字列を入力して改行してください。+1 した結果を出力します。: " ); s_print_string ( s_input_string() + 1 ); printf ( "\n--------------------\n" ); printf ( "整数値を入力して改行してください。+1 した結果を出力します。 : " ); s_print_int ( s_input_int() + 1 ); printf ( "\n--------------------\n" ); printf ( "文字を一文字入力して改行してください。+1 した結果を出力します。 : " ); s_print_char ( s_input_char() + 1 ); printf ( "\n--------------------\n" ); return 0; }
abc 123 X
$ ./sample-018.exe < sample-018.in 文字列を入力して改行してください。+1 した結果を出力します。: abc bc -------------------- 整数値を入力して改行してください。+1 した結果を出力します。 : 123 124 -------------------- 文字を一文字入力して改行してください。+1 した結果を出力します。 : X Y -------------------- $
Download : sample-019.c
/* * 2017/06/23 sample-019.c */ /* * 型の違い * * 利用方法 * コンパイル * cc -I ~/c/include sample-019.c * cc -I ~/c/include -o sample-019.exe sample-019.o * 実行 * ./sample-019.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( void ) { /* * 型が違っても表示は同じ */ s_print_string ( "整数 : " ); s_print_int ( 9 ); s_print_newline(); s_print_string ( "文字 : " ); s_print_char ( '9' ); s_print_newline(); s_print_string ( "文字列 : " ); s_print_string ( "9" ); s_print_newline(); /* * 整数の場合の +1 */ s_print_string ( "整数の計算 : 9 + 1 = " ); s_print_int ( 9 + 1 ); s_print_newline(); /* * 文字の場合の +1 */ s_print_string ( "文字の計算 : '9' + 1 = " ); s_print_char ( '9' + 1 ); s_print_newline(); /* * 文字列の場合の +1 */ s_print_string ( "文字の計算 : \"9\" + 1 = " ); s_print_string ( "9" + 1 ); s_print_newline(); /* * 型によって、計算結果が異る */ return 0; }
$ ./sample-019.exe 整数 : 9 文字 : 9 文字列 : 9 整数の計算 : 9 + 1 = 10 文字の計算 : '9' + 1 = : 文字の計算 : "9" + 1 = $
Download : sample-020.c
/* * 2017/06/23 sample-020.c */ /* * 整数の四則計算式 * * 利用方法 * コンパイル * cc -I ~/c/include sample-020.c * cc -I ~/c/include -o sample-020.exe sample-020.o * 実行 * ./sample-020.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( void ) { /* * 加法(足し算) */ s_print_string ( "12 + 5 = " ); s_print_int ( 12 + 5 ); /* 整数の 12 と 5 を加える */ s_print_newline(); /* * 減法(引き算) */ s_print_string ( "12 - 5 = " ); s_print_int ( 12 - 5 ); /* 整数の 12 から 5 を引く */ s_print_newline(); /* * 乗法(かけ算) */ s_print_string ( "12 * 5 = " ); s_print_int ( 12 * 5 ); /* 整数の 12 に 5 をかける */ s_print_newline(); /* * 商法(割り算) */ s_print_string ( "12 / 5 = " ); s_print_int ( 12 / 5 ); /* 整数の 12 を 5 で割る */ s_print_newline(); /* * 式の優先順位やかっこも利用可能 */ s_print_string ( "1 + 2 * 3 = " ); s_print_int ( 1 + 2 * 3 ); /* かけ算が優先される */ s_print_newline(); s_print_string ( "(1 + 2) * 3 = " ); s_print_int ( (1 + 2) * 3 ); /* かっこの中の計算が優先される */ s_print_newline(); return 0; }
$ ./sample-020.exe 12 + 5 = 17 12 - 5 = 7 12 * 5 = 60 12 / 5 = 2 1 + 2 * 3 = 7 (1 + 2) * 3 = 9 $
Download : sample-021.c
/* * 2017/06/23 sample-021.c */ /* * 文字列の演算式 * * 利用方法 * コンパイル * cc -I ~/c/include sample-021.c * cc -I ~/c/include -o sample-021.exe sample-021.o * 実行 * ./sample-021.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( void ) { /* * 文字列への加法 */ s_print_string ( "\"abc\" + 1 = " ); s_print_string ( "abc" + 1 ); /* 文字列が短くなる */ s_print_newline(); /* * 先頭の文字の取出し */ s_print_string ( "*\"abc\" = " ); s_print_char ( *"abc" ); /* 先頭の文字が出て来る */ s_print_newline(); return 0; }
$ ./sample-021.exe "abc" + 1 = bc *"abc" = a $
Download : sample-022.c
/* * 2017/06/23 sample-022.c */ /* * 関数呼出しを含む形の「式」 * * 利用方法 * コンパイル * cc -I ~/c/include sample-022.c * cc -I ~/c/include -o sample-022.exe sample-022.o * 実行 * ./sample-022.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( void ) { /* * 加法(足し算) */ s_print_string ( "12 + 5 = " ); s_print_int ( 12 + 5 ); /* 整数の 12 と 5 を加える */ s_print_newline(); /* * 減法(引き算) */ s_print_string ( "12 - 5 = " ); s_print_int ( 12 - 5 ); /* 整数の 12 から 5 を引く */ s_print_newline(); /* * 乗法(かけ算) */ s_print_string ( "12 * 5 = " ); s_print_int ( 12 * 5 ); /* 整数の 12 に 5 をかける */ s_print_newline(); /* * 商法(割り算) */ s_print_string ( "12 / 5 = " ); s_print_int ( 12 / 5 ); /* 整数の 12 を 5 で割る */ s_print_newline(); return 0; }
$ ./sample-022.exe 12 + 5 = 17 12 - 5 = 7 12 * 5 = 60 12 / 5 = 2 $
Download : sample-023.c
/* * 2017/06/23 sample-023.c */ /* * 関数の値 [1] * * 利用方法 * コンパイル * cc -I ~/c/include sample-023.c * cc -I ~/c/include -o sample-023.exe sample-023.o * 実行 * ./sample-023.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int zero(void) * 常に整数値「0」を返す定数関数 */ int zero(void) { return 0; /* 返す値(0)を return 命令で返す */ /* 関数は return 命令を実行すると、その時点で終了する */ /* もし、この部分に命令があったとしても、それは実行されない */ } /* * main 関数 */ int main ( void ) { /* * 返り値を持つ関数の呼出し */ s_print_string ( "関数 zero() の呼出し\n" ); s_print_string ( "zero() = " ); s_print_int ( zero() ); /* 関数 zero() を呼出し、その値を出力 */ s_print_newline(); /* * 返り値を式の一部として利用できる */ s_print_string ( "関数 zero() を二度呼出す\n" ); s_print_string ( "zero() + zero() = " ); s_print_int ( zero() + zero() ); /* 0+0 = 0 なので結果は変らず */ s_print_newline(); return 0; }
$ ./sample-023.exe 関数 zero() の呼出し zero() = 0 関数 zero() を二度呼出す zero() + zero() = 0 $
Download : sample-024.c
/* * 2017/06/23 sample-024.c */ /* * 関数の値 [2] * * 利用方法 * コンパイル * cc -I ~/c/include sample-024.c * cc -I ~/c/include -o sample-024.exe sample-024.o * 実行 * ./sample-024.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int inc ( int number ) * 引数で指定された整数値に 1 を加えた値を返す */ int inc( int number ) { return number + 1; /* return 命令の後の式は計算され、その結果が返る */ } /* * main 関数 */ int main ( void ) { /* * 値を持つ関数の呼出し */ s_print_string ( "関数 inc( 3 ) の呼出し\n" ); s_print_string ( "inc ( 3 ) = " ); s_print_int ( inc( 3 ) ); /* 関数 inc に実引数 3 を与えて呼出し、その値を出力 */ s_print_newline(); s_print_string ( "関数 inc( -123 ) の呼出し\n" ); s_print_string ( "inc ( -123 ) = " ); s_print_int ( inc( -123 ) ); s_print_newline(); return 0; }
$ ./sample-024.exe 関数 inc( 3 ) の呼出し inc ( 3 ) = 4 関数 inc( -123 ) の呼出し inc ( -123 ) = -122 $
Download : sample-025.c
/* * 2017/06/23 sample-025.c */ /* * 関数の値 [3] * * 利用方法 * コンパイル * cc -I ~/c/include sample-025.c * cc -I ~/c/include -o sample-025.exe sample-025.o * 実行 * ./sample-025.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int add ( int a, int b ) * 引数で指定された二つの整数値の値の和を返す関数 */ int add( int a, int b ) { return a + b; } /* * main 関数 */ int main ( void ) { /* * 値を持つ関数の呼出し */ s_print_string ( "関数 add( 3, 8 ) の呼出し\n" ); s_print_string ( "add ( 3, 8 ) = " ); s_print_int ( add( 3, 8 ) ); /* 関数 add に二つの実引数 3 と 8 を与えて呼出し、その値を出力 */ s_print_newline(); s_print_string ( "関数 add( 256, -123 ) の呼出し\n" ); s_print_string ( "add ( 256, -123 ) = " ); s_print_int ( add( 256, -123 ) ); s_print_newline(); return 0; }
$ ./sample-025.exe 関数 add( 3, 8 ) の呼出し add ( 3, 8 ) = 11 関数 add( 256, -123 ) の呼出し add ( 256, -123 ) = 133 $
Download : sample-026.c
/* * 2017/06/23 sample-026.c */ /* * 関数の値 [4] * * 利用方法 * コンパイル * cc -I ~/c/include sample-026.c * cc -I ~/c/include -o sample-026.exe sample-026.o * 実行 * ./sample-026.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int myabs ( int number ) * 引数で指定された整数値の絶対値を返す */ int myabs ( int number ) { /* 条件分岐 ( if 文 ) を利用して、返す値を変更する事ができる */ if ( number >= 0 ) { /* 引数の値が非負であれば.. */ return number; /* その値をそのまま返す */ } else { /* そうでなければ (負なので..) 符号を変更して返す */ return number * (-1); /* 実は、「 - number 」と書いても良い */ } /* ここには何もいらない ( if でどちらに行っても return 文に当る ) */ } /* * main 関数 */ int main ( void ) { /* * 条件判断をする関数 */ s_print_string ( "整数値を入力してください。その絶対値を表示します : " ); s_print_int ( myabs ( s_input_int() ) ); s_print_newline(); return 0; }
-12 89
$ ./sample-026.exe < sample-026.in 整数値を入力してください。その絶対値を表示します : -12 12 $
Download : sample-027.c
/* * 2017/06/23 sample-027.c */ /* * 関数の値 [5] * * 利用方法 * コンパイル * cc -I ~/c/include sample-027.c * cc -I ~/c/include -o sample-027.exe sample-027.o * 実行 * ./sample-027.exe */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int sum ( int number ) * 1 から、引数で指定された整数値迄の総和 : 1 + 2 + .. + number を返す */ int sum ( int number ) { if ( number <= 0 ) { /* number が 0 の値は.. */ return 0; /* 0 を返す */ /* 「number == 0」でなく「number <= 0」なのは 予防的(危険を予め避ける)なプログラミング */ } else { /* そうでなければ.. */ return number + sum ( number - 1 ); /* 再帰呼出しで計算 */ } /* * もちろん、再帰呼出しを利用せず、 * いきなり return number * (number+1) / 2 でも良いが.. */ } /* * main 関数 */ int main ( void ) { /* * 再帰呼出しをする計算 */ s_print_string ( "整数値を入力してください。\n" ); s_print_string ( "1 からその数までの総和を計算します : " ); s_print_int ( sum ( s_input_int() ) ); s_print_newline(); s_print_string ( "\n--------------------------------------------\n\n" ); s_print_string ( "もう一つ整数値を入力してください。\n" ); s_print_string ( "1 からその数までの総和を計算します : " ); s_print_int ( sum ( s_input_int() ) ); s_print_newline(); return 0; }
10 100
$ ./sample-027.exe < sample-027.in 整数値を入力してください。 1 からその数までの総和を計算します : 10 55 -------------------------------------------- もう一つ整数値を入力してください。 1 からその数までの総和を計算します : 100 5050 $
/* * 20170623-01-QQQQ.c * * 二つの整数の積を返す関数 * * コンパイル : * cc -I../include -c 20170623-01-QQQQ.c * cc -o 20170623-01-QQQQ.exe 20170623-01-QQQQ.o * 実行 : * ./20170623-01-QQQQ.exe * */ #include <stdio.h> #include "s_print.h" /* s_print_int を利用するので.. */ /* * int imul ( int a, int b ) * int a : かけられる数 * int b : かける数 * 返り値 : a と b の積 */ int imul ( int a, int b ) { return a * b; /* 返値は、return 命令の後ろに式を書いて指定 */ } /* * main */ int main( void ) { s_print_int ( 2 ); s_print_string ( " と、 " ); s_print_int ( 3 ); s_print_string ( " の積は " ); s_print_int ( imul( 2, 3 ) ); s_print_string ( " です。\n" ); s_print_int ( 12 ); s_print_string ( " と、 " ); s_print_int ( 78 ); s_print_string ( " の積は " ); s_print_int ( imul( 12, 78 ) ); s_print_string ( " です。\n" ); return 0; }
/* * 20170623-02-QQQQ.c * * 自然数の階乗を返す関数 * * コンパイル : * cc -I../include -c 20170623-02-QQQQ.c * cc -o 20170623-02-QQQQ.exe 20170623-02-QQQQ.o * 実行 : * ./20170623-02-QQQQ.exe * */ #include <stdio.h> #include "s_print.h" /* s_print_int を利用するので.. */ /* * int factrial ( int n ) * int n : 階乗を計算する自然数 * 返り値 : n! ( n の階乗 ) * * 1 (n==0) * f (n) = { * n * f(n-1) (n>0) */ int factrial ( int n ) { if ( n <= 0 ) { /* 0!, 負の数の階乗は、取り敢えず 1 にする */ return 1; /* 特に 「0! = 1」に注意 */ } else { /* n が正の時は、「n! = n * (n-1)!」となるので.. */ return n * factrial ( n - 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" ); s_print_int ( 20 ); s_print_string ( " の階乗の値は " ); s_print_int ( factrial ( 20 ) ); s_print_string ( " になります。\n" ); return 0; }
#include <stdio.h> /* * 値を返す関数 * * 文字列を2文字短くする関数 */ char *short_two_char ( char *string ) { /* 関数の前に「char *」がついている 以前は「void」だった これは、実は、「値を返さない」という意味の宣言 「char *」は、「文字列を返す」という意味(だと思う事にする) */ return string + 2; /* return 命令によって、関数の値を指定する事ができる */ } int main(int argc, char *argv[]) { printf ( short_two_char ( "abcdefg" ) + 1 ); /* 値を返す関数は、「式」の中で利用可能 「式」を評価する時に、計算された「値」に 置き換わる 「式」は、関数の実引数に指定すると、 値が計算されたから、関数に渡される cf. f, g が 1 変数関数の時 f(x)=x*x g(x)=x+1 の時、この二つ関数の合成関数 h を h(x)=f(g(x)) とすると、 h(x)=f(x+1)=(x+1)*(x+1) となる。 h(1)=(1+1)*(1+1)=2*2=4 h(1)=f(g(1))=f(1+1)=f(2)=2*2=4 一般には、内側から計算した方が、計算回数が減るので速い それならいつでも内側から計算すれば... -> C 言語はそうなっている ところが、内側から計算すると、計算できんないが、外からなら計算できる例がある j(x,y)=x/y j(g(x),g(x))=g(x)/g(x)=1 外から計算 j(g(-1),g(-1))=j(-1+1,-1+1)=j(0,0)=0/0 計算ができない !! */ printf ( "\n" ); return 0; }
#include <stdio.h> /* * シーザ暗号の文字を行う関数 * abcdef..wxyz * def.. zabc */ char encode( char ch ) { if ( 'a' <= ch ) { if ( ch <= 'w' ) { /* 'a' <= ch <= 'w' */ return ch + 3; /* a-w -> d-z */ } else if ( ch <= 'z' ) { /* 'x' <= ch <= 'z' */ return ch - 'w' + 'a'; /* x-z -> a-c */ } /* else{} */ } /* else {} */ return ch; /* 小文字でない場合はそのまま */ } /* 渡された、文字列をシーザ暗号に変換して、出力する */ void encode_string ( char *str ) { if ( *str == '\0' ) { /* EOS なら.. */ /* 何もしない */ } else { putchar ( encode ( *str ) ); /* 一文字だけ変換して出力 */ encode_string ( str + 1 ); /* 残りは再帰呼び出しで.. */ } } void main(int argc, char *argv[] ) { printf ( "Hello, World\n" ); encode_string ( "Hello, World\n" ); return 0; }
#include <stdio.h> /* * シーザ暗号の文字変換の逆変換を行う関数 * def.. zabc * abcdef..wxyz */ char decode( char ch ) { if ( ch <= 'z' ) { if ( 'd' <= ch ) { /* 'd' <= ch <= 'z' */ return ch - 3; /* d-z -> a-w */ } else if ( 'a' <= ch ) { /* 'a' <= ch <= 'c' */ return ch - 'a' + 'w'; /* a-c -> x-z */ } /* else{} */ } /* else {} */ return ch; /* 小文字でない場合はそのまま */ } /* 渡された、文字列をシーザ暗号に変換して、出力する */ void decode_string ( char *str ) { if ( *str == '\0' ) { /* EOS なら.. */ /* 何もしない */ } else { putchar ( decode ( *str ) ); /* 一文字だけ変換して出力 */ decode_string ( str + 1 ); /* 残りは再帰呼び出しで.. */ } } int main(int argc, char *argv[] ) { printf ( "Hhoor, Wruog\n" ); decode_string ( "Hhoor, Wruog\n" ); return 0; }
#include <stdio.h> #include "s_print.h" #include "s_input.h" /* ソースプログラムの中で、#include する 「<>」ではなく、「""」を利用する 「<>」: /usr/include の下の共通のヘッダファイルを利用 「""」: 自分の好きな場所のヘッダーを利用する 「自分の好きな場所」: コンパイル時に cc に -I で場所を指定する 特に、-I で指定しない場合(指定しても..) .c と同じ所にある .h は、自動的に探してくれる s_print.h/s_input,h は ~/c/include にあるので、 利用する場合は -I ~/c/include が必要 */ int main( int argc, char *argv[] ) { s_print_string ( "整数値を入力してください(10 倍して出力します) : " ); /* printf と同じで文字列を出力しているだけ */ s_print_int ( s_input_int() * 10 ); /* s_input_int() を利用して、整数値を読み込み、 その値を 10 倍して、s_print_int で出力 */ s_print_newline(); /* 改行するだけ */ return 0; }
#include <stdio.h> /* what : /usr/include/stdio.h をここに読み込んでいる */ /* why : printf などの標準入出力関数を利用する場合に必要 */ int main(int argc, char *argv[] ) { /* int と宣言 : 値を返す関数で システムにエラーコードを返す */ /* argc, argv : コマンドライン引数を取り出す */ printf ( "Hello, World\n" ); /* ここで「Hello, World」と出力する */ return 0; /* 正常終了 ( 0 : は、「正常」を表す値 ) を意味する */ }
#include <stdio.h> /* helloworld プログラムで、printf の処に名前を付けたい 1. 名前つける範囲を決める 「printf ( "Hello, World\n" );」の部分 名前をつけるのは、何行でも構わない 2. 名前を決める hello_world 名前は、英文字が「_」から始まり、英文字と数字と「_」からなる # 関数名の中に「_」以外の記号や、空白などは含められない 3. 関数の定義の作成 3.1 関数名を書き、その前後に以下の情報を書く a) 関数名の前に関数が返す値の型名 ( 返値がない場合は void ) 今回は、返値がないので「void」にする b) 関数名の後に、仮引数変数宣言を行う ( + 仮引数宣言のリスト + ) 今回は引数がないので、「()」か、「(void)」にする 3.2 { と } で、名前をつけたい命令列を挟む 今回は、printf の部分 4. 関数の利用(関数呼び出し) 関数名 + 実引数 + ; 実引数は、( + 引数並び + ) 今回は、引数がないので () だけ */ void hello_world ( void ) { printf ( "Hello, World\n" ); } int main(int argc, char *argv[]) { hello_world(); /* 関数を呼び出す / 名前を付けた命令が実行される */ /* 式の後ろに ';' で文になる */ /* cf. 「1;」も正しい C 言語の命令 */ return 0; }
/* 引数付き関数 関数のふるまいを動的変更できる */ void func ( char *x ) { printf ( "前 : " ); printf ( x ); /* 仮引数変数で指定された部分は 後(関数呼び出しの時点)で.. 値が確定し、それが利用される */ printf ( " : 後\n" ); /* 引数を利用する事により、 プログラムの一部を動的に変更可能 「動的」プログラムの実行時に */ } int main( int argc, char *argv[] ) { func ( "abc" ); /* 関数呼び出しの度に */ func ( "123" ); /* 仮引数変数に入る値である実引数を与える */ /* 呼び出された関数の中で、 */ /* 仮引数変数の現れる場所に、 */ /* 実引数の値が入る */ if ( argc > 1 ) { /* コマンドライン引数が指定されていたら */ func ( argv[1] ); /* それも利用する */ } return 0; }
#include <stdio.h> #include "s_print.h" #include "s_input.h" /* 引数の値によって、条件判断を行い、振る舞いを変える */ /* 整数値の与えて、その絶対値を返す関数 int_abs を考える int_abs( -10 ) -> 10 int_abs( 0 ) -> 0 int_abs( 7 ) -> 7 これは、整数値を入力し、整数値を返値とするので、宣言は int int_abs( int num ) ^^^ ^^^ 返値の型 引数の型 になる。 プログラムの振る舞い num が非負ならば、そのままの値 負の場合は、符号を変更すればよい 符号を変更するには、(-1) を掛ければよい if 文 ( 条件判断 ) を利用する事により、 まったく異なる二つの振る舞いを、 実行時に選択できる 引数の型と、返値の型 扱うデータの種類によって、型の宣言を適切に行う必要がある */ int int_abs ( int num ) { if ( num < 0 ) { /* 引数が負の数 */ return num * (-1); /* (-1) を掛けて、符号を反転する */ /* 「- num」と書いてもよい */ } else { /* そうでない場合(非負)の場合 */ return num; /* 引数の値をそのまま返値にしてよい */ } /* ここに来ることはないので、ここには reutrn 命令は不要 */ } int main(int argc, char *argv[]) { s_print_string ( "整数を入力してください(絶対値を表示します) : " ); s_print_int ( int_abs ( s_input_int() ) ); s_print_newline(); /* int_abs は引数として整数値(int 型)を期待している それとは違うものを指定すと... ? */ /* int_abs( "123" ); */ /* 文字列が指定されている */ /* これは、「引数の型」が違うのでコンパイル時にエラーになる */ /* 「コンパイル時」の事を「静的(<-> 動的:実行時)」と呼ぶ */ /* 型を合わせないとダメ */ return 0; }
/* 引数付き関数 関数のふるまいを動的変更できる */ void func ( char *x ) { /* 変数 x にはデータ (型:char *)が入る */ printf ( "前 : " ); printf ( x ); /* printf の引数もデータ : (型:char *) */ printf ( " : 後\n" ); } int main( int argc, char *argv[] ) { func ( "abc" ); /* "abc" : データ (型:char *) */ func ( "123" ); /* "123" : データ (型:char *) */ return 0; }
/* 引数付き関数 関数のふるまいを動的変更できる */ void func ( x ) { /* 変数 x にはデータ (型:char *)が入る */ printf ( "前 : " ); x; printf ( " : 後\n" ); } int main( int argc, char *argv[] ) { func ( printf ( "abc" ) ); /* プログラムの一部を渡す */ func ( printf ( "123" ) ); /* という考え方は「賢い」が 残念な事に C ではできない */ /* (近い事はできるが..) */ return 0; }
#include <stdio.h> #include "s_print.h" /* 再帰呼び出しの話 再帰的な構造を持つデータの処理には、再帰が必要 再帰的な構造 ( 数学的帰納法に対応している ) ある「モノ」を定義する時に、その定義内容に、自分自身が含まれている場合が再帰的定義 例: 自然数(ペアノの公理) 0) 0 は自然数 1) x が自然数ならば、x の後者(x+1 事)も自然数 2) 上記の 0), 1) のルールからのみ作られるのが自然数 例えば... 0 は自然数 : ルール 0 から 1 は自然数 1 = 0 + 1 => 自然数 + 1 => 自然数 2 は自然数 2 = 1 + 1 => 自然数 + 1 => 自然数 数学的帰納法と同じ 自然数(k+1) を示すには、 自然数(k) を示せばよい 自然数(0) は常に成立 C 言語の文字列 0) "" は文字列 1) X が文字列で a が文字なら、 X の前に a を付けたものも文字列 2) 上記の 0), 1) のルールからのみ作られるのが文字列 例えば... "" は文字列 : ルール 0 から "a" は文字列 "a" = 'a' + "" <-> *"a" = 'a' "a" + 1 = "" => 文字列に文字を追加したもの => 文字列 */ void myprintf ( char *str ) { /* 文字列を指定して、それを出力する */ if ( *str == '\0' ) { /* str == "" の時 */ /* なにもしなくてもよい : 空文字列は出力しても何もおきない */ } else { putchar ( *str ); /* 先頭の文字だけを処理 */ myprintf ( str + 1 ); /* 残りは、再帰呼び出しで.. */ } } /* 1 から n までの総和計算する関数 sum(n) sum(n) = n * ( n + 1 ) / 2 sum(n) = { 0 (n=0) n + sum(n-1) (n>0) と再帰的に考えて見る */ int sum(int n) { if ( n == 0 ) { return 0; } else { return n + sum(n-1); } } int main(int argc, char *argv[]) { myprintf ( "1 から 10 の和を計算します : " ); s_print_int ( sum ( 10 ) ); s_print_newline(); return 0; }
式「x + 1」という「表現」の「意味」は ? cf. "abc" + 1 -> "bc" 'a' + 1 -> 'b' 123 + 1 -> 124 「x」という変数に何が入っているかによって異なる あらかじめ x に何が入るか予想できるか ? !! なぜ、変数 x を利用するかといえば、 !! x の値を実行時に決めたいから !! x の型を決める事により !! -> 値は後から決められるが !! -> 何をするかは今決められる !! 「型」宣言の重要性 式「x + 1」という「表現」の「意味」は ? 答え もし、 char *x という x の型宣言があれば、 x には、文字列が入っているので、先頭の文字を削る そうでなくて、もし char x という型宣言があれば、 x には、文字が入っているので、次の文字 そうでなくて、もし int x という型宣言があれば x には、整数値が入っているので足し算すればよい # x の型宣言に応じて、やることを決めればよい
Download : 20170623-01.c
/* * 20170623-01-QQQQ.c * * 二つの整数の積を返す関数 * * コンパイル : * cc -I../include -c 20170623-01-QQQQ.c * cc -o 20170623-01-QQQQ.exe 20170623-01-QQQQ.o * 実行 : * ./20170623-01-QQQQ.exe * */ #include <stdio.h> #include "s_print.h" /* s_print_int を利用するので.. */ /* * int imul ( int a, int b ) * int a : かけられる数 * int b : かける数 * 返り値 : a と b の積 */ int imul ( int a, int b ) { /* ** この部分を完成させなさい */ } /* * main */ int main( void ) { s_print_int ( 2 ); s_print_string ( " と、 " ); s_print_int ( 3 ); s_print_string ( " の積は " ); s_print_int ( imul( 2, 3 ) ); s_print_string ( " です。\n" ); s_print_int ( 12 ); s_print_string ( " と、 " ); s_print_int ( 78 ); s_print_string ( " の積は " ); s_print_int ( imul( 12, 78 ) ); s_print_string ( " です。\n" ); return 0; }
$ ./20170623-01-QQQQ.exe 2 と、 3 の積は 6 です。 12 と、 78 の積は 936 です。 $
Download : 20170623-02.c
/* * 20170623-02-QQQQ.c * * 自然数の階乗を返す関数 * * コンパイル : * cc -I../include -c 20170623-02-QQQQ.c * cc -o 20170623-02-QQQQ.exe 20170623-02-QQQQ.o * 実行 : * ./20170623-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)!」となるので.. */ /* ** この部分を完成させなさい */ } } /* * 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; }
$ ./20170623-02-QQQQ.exe 3 の階乗の値は 6 になります。 5 の階乗の値は 120 になります。 $
Download : 20170623-03.c
/* * 20170623-03-QQQQ.c * * 二つの整数の最大公約数を返す * * コンパイル : * cc -I../include -c 20170623-03-QQQQ.c * cc -o 20170623-03-QQQQ.exe 20170623-03-QQQQ.o * 実行 : * ./20170623-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) となる */ /* ** この部分を完成させなさい */ } } /* * 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; }
$ ./20170623-03-QQQQ.exe 12 と、 18 の最大公約数は 6 です。 1111 と、 111111 の最大公約数は 11 です。 $