Download : sample-001.c
/*
* CDATE 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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
/*
* 2018/07/13 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 $
/*
* 20180713-01-QQQQ.c
*
* 二つの整数の積を返す関数
*
* コンパイル :
* cc -I ~/c/include -c 20180713-01-QQQQ.c
* cc -o 20180713-01-QQQQ.exe 20180713-01-QQQQ.o
* 実行 :
* ./20180713-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 の積
*/
/*
* 1. この関数が返す値の型
* => 整数値(int 型) の積 => 整数値(int 型)
* => int
* 2. 関数名
* => imul
* 3. 引数
* => 二つの整数値(int 型)
* => 二つの引数に変数名を付ける
* a : 最初の引数
* => int a
* b : 二つ目の引数
* => int b
* 4. 関数本体
*/
int imul ( int a, int b ) {
/* a と b の積を値として返す */
return a * 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;
}
/*
* 20180713-02-QQQQ.c
*
* 自然数の階乗を返す関数
*
* コンパイル :
* cc -I../include -c 20180713-02-QQQQ.c
* cc -o 20180713-02-QQQQ.exe 20180713-02-QQQQ.o
* 実行 :
* ./20180713-02-QQQQ.exe
*
*/
#include <stdio.h>
#include "s_print.h" /* s_print_int を利用するので.. */
/*
* int factrial ( int n )
* int n : 階乗を計算する自然数
* 返り値 : n! ( n の階乗 )
*
* 再帰呼び出しを利用する
* => 繰り返しだから..
* n! = n * (n-1) * (n-2) * ... * 2 * 1
*
* 3! = 3 * 2 * 1
* 5! = 5 * 4 * 3 * 2 * 1
* 1. データによって、命令の個数が違い (命令:*)
* 2. 同じ命令 (*) を繰り返している
* => (順接,条件分岐だけではだめで)繰り返しが必要
*
* => n! の定義が、「帰納的」だから..
* 1 (n=1 の時)
* n! = {
* n * (n-1)! (その他)
* => n! の計算に (n-1)! つまり ! が利用されている
* => 数学的帰納法を利用して、! の存在が保証される
* P(n) : n! が計算できる
* P(1) : 1! が計算できる => 1
* P(k) を仮定して P(k+1) を示す
* n! = (k+1)! が計算できるか ?
* = (k+1) * k!
* => 計算できる
* => 数学的帰納法から、任意の自然数 n に対して、
* この帰納的定義を利用すれば、n! が計算できる
*
* C 言語関数定義で、(数学的に帰納的な定義がされている)関数を表現
* する場合は、再帰呼び出しを利用すればよい
*/
int factrial ( int n ) {
/*.
* 1 (n=1 の時)
* n! = {
* n * (n-1)! (その他)
*/
if ( n <= 0 ) { /* n が 0 以下の時 0!=1 (-1)! も とりあえず 1 */
/* 本来は、n < 1 の時は「未定義」となる */
/* しかし、プログラム上は安全をとって、
適当(必ずしも適切ではない)値にしてしまう */
/* これよって、「変な事がおきないよう」にできる */
return 1; /* 特に 「0! = 1」に注意 */
} else { /* n が正の時は、「n! = n * (n-1)!」となるので.. */
/* return n * (n-1)!; */
return n * factrial(n-1); /* (n-1)! の代わりに 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" );
return 0;
}
/*
* 20180713-03-QQQQ.c
*
* 二つの整数の最大公約数を返す
*
* コンパイル :
* cc -I../include -c 20180713-03-QQQQ.c
* cc -o 20180713-03-QQQQ.exe 20180713-03-QQQQ.o
* 実行 :
* ./20180713-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 の最大公約数を返す
*
* (12,16)
* 12 = 2*2 *3
* 16 = 2*2*2*2
* 2*2 => 4
* 小学生の方法は、素因数分解をしている
* => 素因数分解は時間がかかる
* その数より小さな素数で割る
* 1111111
* ユークリッドの互除法
* m,n の最大公約数を g=(m,n)で表すとすると、
* n が 0 の時には g=m
* m>n => (m.n) = (m-n,n)
* (m,n) = (n,m)
* (12,16) = (16,12)
* = (16-12,12) = (4,12)
* = (12,4) = (12-4,4) = (8,4) = (8-4,4) = (4,4) = (4-4.4) = (0,4)
* => (12%4,4) = (0,4)
* = (4,0)
* = 4
*/
int euclid ( int a, int b ) {
if ( b == 0 ) { /* 任意の数 a と 0 の最大公約数 (a,0) は a となる */
return a;
} else { /* b が 0 でない時 (a,b) = (b,a%b) となる */
/*
(a,b) => (a%b,b) => (b,a%b)
return (b,a%b);
*/
return euclid ( b, a%b );
/*
上記は a>=b の時を想定している
a < b の時は ?
(a,b) => (b, a%b) => (b,a) となり、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;
}
/*
Hello World プログラムは、画面に
「Hello, World」(改行)
を表示する
C 言語の完全で、意味のあるプログラム
*/
#include <stdio.h> /* printf の情報(一部)もっている */
/* printf の型宣言をしている */
/* extern int printf ( const char *, ... ); */
/* で代用可能 */
/* 「stdio.h」のファイルの中身を読みこむ */
int main(int argc, char *argv[]) { /* main 関数の定義 : 必ず必要 */
printf ( "Hello, World\n" ); /* 実際に表示を行う部分 */
return 0;
}
/*
Hello World プログラムは、画面に
「Hello, World」(改行)
を表示する
C 言語の完全で、意味のあるプログラム
*/
#include <stdio.h>
int main(void) {
/* int argc, char *argv[]
=> プログラムを実行するときのコマンドライン引数を
参照するための変数
=> 参照しないのであれば、なくてもよい
=> 「ない」事を示す場合は、void を書く約束
<*> 実は、「()」は「何がはいるかわからない」
「(void)」は、「何も入らない(入ってはいけない)」
関数定義するときには、区別する意味がない
# 「関数宣言」するときに区別する必要がある
*/
printf ( "Hello, World\n" );
return 0;
}
/*
Hello World プログラムは、画面に
「Hello, World」(改行)
を表示する
C 言語の完全で、意味のあるプログラム
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
printf ( "Hello, World\n" );
return 0; /* shell にエラーステータス($?)の値として、
0 (正常値)
を返す
=> return 命令がないと、
何が返るか不明
=> 明示的にかいた方がよい
*/
}
/*
Hello World プログラムは、画面に
「Hello, World」(改行)
を表示する
C 言語の完全で、意味のあるプログラム
*/
#include <stdio.h>
void main(int argc, char *argv[]) {
/* 関数の前の int は、その関数がどの型の値を返すかを示す */
/* void とかいた場合は、「値を返さない」 */
printf ( "Hello, World\n" );
return ; /* void にすると、「値を返さない」という規則 */
/* return 0 <= 0 という値を返すという意味なので矛盾 */
}
/*
*/
#include <stdio.h>
int main(int argc, char *argv[]) { /* main 関数の定義 : 必ず必要 */
printf ( "A: Hello, World\n" ); /* 順接: 二つの命令を並べる */
printf ( "B: Hello, World\n" ); /* => 並べた順に実行される */
printf ( "C: Hello, World\n" ); /* A,B,C => (A,B),C */
return 0;
}
/*
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
if ( argc >= 2 ) { /* コマンドライン引数が与えらえた */
/* argc は、コマンドライン引数の個数 + 1 なので
argc が 2 以上の場合は、引数がある */
printf ( "A: Hello, World\n" );
} else { /* そうでない場合 */
printf ( "B: Hello, World\n" );
}
return 0;
}
/*
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
if ( argc >= 2 ) { /* コマンドライン引数が与えらえた */
/* argc は、コマンドライン引数の個数 + 1 なので
argc が 2 以上の場合は、引数がある */
if ( argc >= 3 ) { /* 引数が 2 個以上 */
printf ( "C: Hello, World\n" );
} else { /* 引数が、ちょうど 1 個の時 */
printf ( "A: Hello, World\n" );
}
} else { /* そうでない場合 */
/* 引数が 0 個 */
printf ( "B: Hello, World\n" );
}
return 0;
}
/*
* 引数の個数だけ、「*」を画面に出す
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
if ( argc > 1 ) { /* argc > 1 : 条件 P */
printf ( "*\n" ); /* 繰り返したい命令を実行 : 命令 A */
main ( argc, argv ); /* 再帰呼び出し : P が変わるように argc を変更している */
/* main 関数の中で、main 関数を呼び出す */
/* 関数 f の中で、fを呼び出す事を f の再帰呼び出し */
} else {
/* なにもしない */
}
return 0;
}
#include <stdio.h>
/*
原理的にどんな関数でも表現できる形式
疑似コード
*/
void anyway ( int status ) {
if ( P(status) ) {
if ( P1(status) ) {
A1;
} else if ( P2(status) ) {
A2;
}
..
} else {
}
anyway ( status の式 );
} else {
}
}
main 関数の引数は、
その引数の値を利用しない限り、なんと宣言してよい
普通は、
int argc, char *argv[]
だが、
void
でもよい
main 関数
C 言語における関数ではあるが、次の点、他異なる
1. 最初に呼び出される関数
2. 必ず必要な関数
3. 呼び出すのは、他の関数ではなく、コマンドライン(shell)から..
=> コマンドライン引数がある (int argc, char *argv[])
=> 引数宣言(関数同士で呼び出すときには双方でそろえる必要がある)
=> main は、関数から呼び出されないので、適当でよい
4. 返す値も、他の関数ではなく、コマンドライン(shell)
==
制御構造
命令を組み合わせる仕方と、その表現
順接
意味:二つ命令 A, B があるときに、それをその順に実行する
表現: 並べるだけ => A B
条件分岐
意味: 二つの命令 A,B と条件 P があるとき
P の成立、不成立によって、A, B のいずれか一方を実行する
表現: if ( P ) { A } else { B }
繰り返し
意味: 一つの命令 A と条件 P が与えらえたとき、
条件 P が成立する限り A を何度も実行する
例: n が与えられたときに、順に n を減らしながら、
P: n が 0 より大きい間
A: n を出力する
表現: 再帰呼び出し
f() {
if ( P ) { <= P は引数の値を参照する
A
f() <= P の条件が変化するように引数の値を変更する
} else {
}
}
=> 短い命令の記述で、長い命令の実行が可能になる
cf. 順接や、条件分岐は、
命令の記述の長さより、実行の長さが長くならない
==
制御構造は、何度でも適用可能(組み合わせも可能)なので、
制御構造を繰り返し適用する事により、複雑な命令が作れる
順接の組み合わせ : いくらでも長いプログラムがかける
条件分岐の組み合わせで : いくつでも場合わけができる
実は、(数学的/原理的に)作成可能なプログラムと同じ機能を
この三つの制御構造だけで、実現できる
=> 万能性
繰り返しは一回
次は、条件分岐(複数)
個々の条件に、順接をする
の形のプログラムでも、万能になる
==
関数の定義とその利用法
C 言語のプログラムは、main 関数がないといけない
=> main 関数だけがあればよい (cf. Hello, World )
=> *最悪* main の本体のところにいろいろかけば、
任意の機能のプログラムがかける
=> main だけにする
一度に全部を考える => 一定のサイズをこえると対応できなくなる
関数を作る
関数とは「命令の一部に名前つけて、名前で、その命令を実行するできるようにしたときのその名前」
=> 目的は「命令に名前をつける事」ではない
<= 関数を利用すると、(長い)命令が、(短い)関数呼び出しになる
=> 関数を呼び出す側が関数を利用を利用する事により短くなる
=> 関数の定義そのものは、命令数が少ないので短くなる
=> 関数を利用しないと長いプログラムが、
関数を利用する事により、短いプログラム集まりになる
=> 複雑すぎて解けないような一つの問題を、
単純で解けそうな複数の問題に還元する
分割統治法
関数定義する手順:命令に名前を付ける
1. 名前を決める
sub
2. その前に void と後ろに (void) そして、{} をつける
void sub(void) {
}
3. {} の間に名前をつけたい命令をかく
void sub(void) {
printf ( "Hello, World\n" );
printf ( "Hello, World\n" );
}
4. 関数の使いかた
関数名();
とする
sub(); /* Hello、World が二度実行される */
==
より一般的な関数の定義
型宣言
型宣言 : 関数の返す値の型 (void とした場合は、値を返さない
型宣言 関数名
関数名 : 個々の関数を識別するための名前
型宣言 関数名 ( 関数引数並び )
関数引数並び : その関数を呼び出すとき、
どの型の値をどの順で指定するかを定める
その引数を、次の関数の本体の中で、参照する名前(変数)を定める
引数がない場合は、void とする
引数がある場合は、
「型 変数名」の対を「,」で区切って並べる
型宣言 関数名 ( 関数引数並び ) {
命令
}
関数の本体は、関数が表す命令列で、
{ 命令 }
の形
1. 関数引数で指定されている変数が利用できる
2. return 命令を利用する事によって、値を返す事がきる
3. 命令列は任意で、他の関数の呼び出しなども可能
# 再帰を呼び出しを利用して、繰り返しも実行できる
==
Download : 20180713-01.c
/*
* 20180713-01-QQQQ.c
*
* 二つの整数の積を返す関数
*
* コンパイル :
* cc -I ~/c/include -c 20180713-01-QQQQ.c
* cc -o 20180713-01-QQQQ.exe 20180713-01-QQQQ.o
* 実行 :
* ./20180713-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;
}
$ ./20180713-01-QQQQ.exe 2 と、 3 の積は 6 です。 12 と、 78 の積は 936 です。 $
Download : 20180713-02.c
/*
* 20180713-02-QQQQ.c
*
* 自然数の階乗を返す関数
*
* コンパイル :
* cc -I../include -c 20180713-02-QQQQ.c
* cc -o 20180713-02-QQQQ.exe 20180713-02-QQQQ.o
* 実行 :
* ./20180713-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;
}
$ ./20180713-02-QQQQ.exe 3 の階乗の値は 6 になります。 5 の階乗の値は 120 になります。 $
Download : 20180713-03.c
/*
* 20180713-03-QQQQ.c
*
* 二つの整数の最大公約数を返す
*
* コンパイル :
* cc -I../include -c 20180713-03-QQQQ.c
* cc -o 20180713-03-QQQQ.exe 20180713-03-QQQQ.o
* 実行 :
* ./20180713-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;
}
$ ./20180713-03-QQQQ.exe 12 と、 18 の最大公約数は 6 です。 1111 と、 111111 の最大公約数は 11 です。 $