Download : sample-001.c
/* * 2018/06/15 sample-001.c */ #include <stdio.h> #include <string.h> /* * myPrintf (No.1) * * myPrintf の考え方 * * <意味を考える> * 「文字列」を全部を出力 * = 文字列の先頭の文字を出力 + 残りの文字列を出力 * = 「文字列」の先頭の文字を出力 + 「残りの文字列」を全部を出力(再帰) * * <再帰関数の形にする> * myPrintf ( 「文字列」 ) * = putchar ( 「文字列」の先頭 ) + myPrintf ( 「文字列」の残り ) * = putchar ( *「文字列」 ) + myPrintf ( 「文字列」+ 1 ) * * <再帰を利用する場合は「終了の場合」を作る> * myPrintf ( 「文字列」 ) * = if ( 「文字列」が空文字列の時 ) { * なにもしない * } else { * putchar ( *「文字列」 ); * myPrintf ( 「文字列」+ 1 ); * } * */ void myPrintf ( char *string ) { if ( !strcmp ( string, "" ) ) { /* 空文字列なら..(終了条件) */ /* 何もしなくてよい */ } else { /* まだ出力する文字があれば */ putchar ( *string ); /* 先頭の文字を出力する */ myPrintf ( string + 1 ); /* 残りの文字列を出力する */ } } /* * main */ int main ( void ) { myPrintf ( "abcde\n" ); myPrintf ( "xyz\n" ); return 0; }
$ ./sample-001.exe abcde xyz $
Download : sample-002.c
/* * 2018/06/15 sample-002.c */ #include <stdio.h> #include <string.h> /* * myPrintf (No.2) * * 終了条件を EOS ( '\0' : End Of String) で判定 */ void myPrintf ( char *string ) { if ( *string == '\0' ) { /* 先頭が空文字('\0')なら空文字列 */ /* 文字の比較は 「==」で行う */ /* 何もしなくてよい */ } else { /* まだ出力する文字があれば */ putchar ( *string ); /* 先頭の文字を出力する */ myPrintf ( string + 1 ); /* 残りの文字列を出力する */ } } /* * main */ int main ( void ) { myPrintf ( "abcde\n" ); myPrintf ( "xyz\n" ); return 0; }
$ ./sample-002.exe abcde xyz $
Download : sample-003-01.c
/* * 2018/06/15 sample-003-01.c */ #include <stdio.h> /* putchar の為に必要 */ /* * println : 文字列を出力するついでに最後に改行を付加する */ void println ( char *string ) { if ( *string == '\0' ) { putchar ( '\n' ); /* 最後に改行を出力する */ } else { putchar ( *string ); println ( string + 1 ); } }
Download : sample-003.c
/* * 2018/06/15 sample-003.c */ #include <stdio.h> /* * println の extern 宣言 */ extern void println ( char *string ); /* 関数の頭部の前に extern 後に ; */ /* * main */ int main ( void ) { println ( "abcde" ); /* 改行(\n)が不要になった */ println ( "xyz" ); return 0; }
$ ./sample-003.exe abcde xyz $
Download : sample-004-01.c
/* * 2018/06/15 sample-004-01.c */ /* もはや printf も putchar も使わないので #include <stdio.h> も不要 */ /* * println の extern 宣言 */ extern void println ( char *string ); /* * triangle again * */ void triangle ( char *string ) { if ( *string == '\0' ) { /* 何もしなくてよい */ } else { println ( string ); /* println を利用する */ triangle ( string + 1 ); } }
Download : sample-004.c
/* * 2018/06/15 sample-004.c */ /* * triangle, println の extern 宣言 */ extern void println ( char *string ); extern void triangle ( char *string ); /* * main */ int main ( void ) { triangle ( "****" ); /* 間接的に println を使うので、改行が不要 */ println ( "" ); /* 空行を出力する */ triangle ( "*******" ); return 0; }
$ ./sample-004.exe **** *** ** * ******* ****** ***** **** *** ** * $
Download : sample-005-01.c
/* * 2018/06/15 sample-005-01.c */ /* * println の extern 宣言 */ extern void println ( char *string ); /* * rtriangle -- triangle の「逆」版 */ void rtriangle ( char *string ) { if ( *string == '\0' ) { /* 何もしなくてよい */ } else { rtriangle ( string + 1 ); /* 最初に残りをやって.. */ println ( string ); /* 最後に先頭を処理する */ } }
Download : sample-005.c
/* * 2018/06/15 sample-005.c */ /* * rtriangle, println の extern 宣言 */ extern void println ( char *string ); extern void triangle ( char *string ); extern void rtriangle ( char *string ); /* * main */ int main ( void ) { triangle ( "****" ); rtriangle ( "*******" ); return 0; }
$ ./sample-005.exe **** *** ** * * ** *** **** ***** ****** ******* $
Download : sample-006-01.c
/* * 2018/06/15 sample-006-01.c */ /* * extern 宣言 */ extern println ( char *string ); /* * string の文字列の長さ回 「Hello World\n」を表示する */ void nhello ( char *string ) { if ( *string == '\0' ) { /* 既に全てすんだ */ /* 何もしなくてよい */ } else { /* まだ、やる事がある */ println ( "Hello, World" ); /* 取り敢えず、一度出力 */ nhello ( string + 1 ); /* 文字列を短くして、残りを行う (再帰) */ } }
Download : sample-006.c
/* * 2018/06/15 sample-006.c */ /* * extern 宣言 */ extern println ( char *string ); extern nhello ( char *string ); /* * n 回数の繰返し */ int main ( void ) { println ( " 3 回 Hello : " ); nhello ( "***" ); /* 長さ 3 の文字列を指定 */ println ( " 5 回 Hello : " ); nhello ( "12345" ); /* 長さ 5 の文字列を指定 */ return 0; }
$ ./sample-006.exe 3 回 Hello : Hello, World Hello, World Hello, World 5 回 Hello : Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-007-01.c
/* * 2018/06/15 sample-007-01.c */ /* * extern 宣言 */ extern println ( char *string ); /* * string の文字列の長さ回 message を出力する * 基本は nhello と同じだが、出力する message が異なる */ void nprintln ( char *string, char *message ) { if ( *string == '\0' ) { /* 既に全てすんだ */ /* 何もしなくてよい */ } else { /* まだ、やる事がある */ println ( message ); /* 取り敢えず、一度出力 */ nprintln ( string + 1, message ); } }
Download : sample-007.c
/* * 2018/06/15 sample-007.c */ /* * extern 宣言 */ extern void nprintln ( char *string, char *message ); /* * n 回数の繰返し */ int main ( void ) { println ( " 3 回「Hello」: " ); nprintln ( "***", "Hello" ); println ( " 5 回「こんにちは」: " ); nprintln ( "12345", "こんにちは" ); return 0; }
$ ./sample-007.exe 3 回「Hello」: Hello Hello Hello 5 回「こんにちは」: こんにちは こんにちは こんにちは こんにちは こんにちは $
Download : sample-008-01.c
/* * 2018/06/15 sample-008-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * extern 宣言 */ extern println ( char *string ); /* * itemize ( char *item, char *message ) * 個々の文字の前にマークを付ける */ void itemize ( char *item, char *message ) { if ( *item == '\0' ) { /* 既に全てすんだ */ /* 何もしなくてよい */ } else { /* まだ、やる事がある */ putchar ( *item ); /* 項目 */ putchar ( ' ' ); /* 一文字空けて */ println ( message ); /* 一行出力 */ itemize ( item + 1, message ); } }
Download : sample-008.c
/* * 2018/06/15 sample-008.c */ /* * extern 宣言 */ extern void itemize ( char *item, char *message ); /* * n 回数の繰返し */ int main ( void ) { println ( " 3 回「Hello」: " ); itemize ( "***", "Hello" ); println ( " 5 回「こんにちは」: " ); itemize ( "12345", "こんにちは" ); return 0; }
$ ./sample-008.exe 3 回「Hello」: * Hello * Hello * Hello 5 回「こんにちは」: 1 こんにちは 2 こんにちは 3 こんにちは 4 こんにちは 5 こんにちは $
Download : sample-009-01.c
/* * 2018/06/15 sample-009-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * extern 宣言 */ extern println ( char *string ); extern nprintln ( char *string, char *message ); /* * mnprintln ( char *m, char *n, char *message ) * m * n 回数 message を出力する */ void mnprintln ( char *m, char *n, char *message ) { if ( *m == '\0' ) { } else { nprintln ( n, message ); /* n 回数は nprintln にお任せ */ mnprintln ( m + 1, n, message ); } }
Download : sample-009.c
/* * 2018/06/15 sample-009.c */ /* * extern 宣言 */ extern void mnprintln ( char *m, char *n, char *message ); /* * n 回数の繰返し */ int main ( void ) { println ( " 3 x 5 回「Hello」: " ); mnprintln ( "***", "*****", "Hello" ); println ( " 4 x 4 回「こんにちは」: " ); mnprintln ( "1234", "1234", "こんにちは" ); return 0; }
$ ./sample-009.exe 3 x 5 回「Hello」: Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello 4 x 4 回「こんにちは」: こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは こんにちは $
Download : sample-010-01.c
/* * 2018/06/15 sample-010-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * nprinttail * n 回数 message を出力するが、行末を変更する。 */ void nprinttail ( char *tail, char *message ) { if ( *tail == '\0' ) { } else { printf ( message ); if ( *tail == '\n' ) { /* 改行の時のみ */ putchar ( '\n' ); /* 改行する */ } else { /* それ以外は */ /* 何もしない */ } nprinttail ( tail + 1, message ); } }
Download : sample-010.c
/* * 2018/06/15 sample-010.c */ /* * extern 宣言 */ extern void println ( char *message ); extern void nprinttail ( char *tail, char *message ); /* * n 回数の繰返し */ int main ( void ) { println ( "毎回改行「Hello」: " ); nprinttail ( "\n\n\n", "Hello" ); println ( "3 回目, 7 回目だけ改行「Hello」: " ); nprinttail ( "12\n456\n", "Hello" ); return 0; }
$ ./sample-010.exe 毎回改行「Hello」: Hello Hello Hello 3 回目, 7 回目だけ改行「Hello」: HelloHelloHello HelloHelloHelloHello $
Download : sample-011.c
/* * 2018/06/15 sample-011.c */ #include <stdio.h> /* * 文字の扱い */ int main ( void ) { printf ( "abc\n" ); /* 「abc(改行)」とでる */ printf ( "abc\n" + 1 ); /* 「bc(改行)」とでる ( 1 を加えると短くなる ) */ putchar ( 'A' ); /* 「A」とでる */ putchar ( '\n' ); /* 「(改行)」とでる */ putchar ( 'A' + 1 ); /* 文字に 1 を加えると ? */ putchar ( '\n' ); /* 「(改行)」とでる */ return 0; }
$ ./sample-011.exe abc bc A B $
Download : sample-012-01.c
/* * 2018/06/15 sample-012-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * printcharln ( char ch ) * 文字を出力して改行する */ void printcharln ( char ch ) { putchar ( ch ); /* 指定された文字を出力 */ putchar ( '\n' ); /* その後に改行 */ }
Download : sample-012.c
/* * 2018/06/15 sample-012.c */ /* * extern 宣言 */ extern void printcharln ( char ch ); /* * 文字の扱い(2) */ int main ( void ) { printcharln ( 'A' + 1 ); /* 'B' になった */ printcharln ( 'B' + 1 ); /* 'C' になる */ printcharln ( 'A' + 1 + 1 ); /* これも 'C' になる */ printcharln ( 'A' + 0 ); /* これはもちろん 'A' */ printcharln ( 'A' + 10 ); /* 'A', 'B', .., 'J', 'K' になるはず */ printcharln ( 'A' + 25 ); /* 'Z' !! */ printcharln ( 'Z' + 1 ); /* ??? */ return 0; }
$ ./sample-012.exe B C C A K Z [ $
Download : sample-013-01.c
/* * 2018/06/15 sample-013-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * nprintcharln ( char ch ) * 文字を連続 n 個だけ、出力する */ void nprintcharln ( char *n, char ch ) { if ( *n == '\0' ) { putchar ( '\n' ); /* 改行 */ } else { putchar ( ch ); /* 指定された文字を出力 */ nprintcharln ( n + 1, ch + 1 ); } }
Download : sample-013.c
/* * 2018/06/15 sample-013.c */ /* * extern 宣言 */ extern void nprintcharln ( char *n, char ch ); extern void printcharln ( char ch ); extern void println ( char *string ); /* * 文字の扱い(3) */ int main ( void ) { println ( "'A' から 10 個 :" ); nprintcharln ( "1234567890", 'A' ); println ( "'U' から 10 個 :" ); nprintcharln ( "1234567890", 'U' ); println ( "'k' から 10 個 :" ); nprintcharln ( "1234567890", 'k' ); println ( "'0' から 10 個 :" ); nprintcharln ( "1234567890", '0' ); println ( "'9' + 1 は.. :" ); printcharln ( '9' + 1 ); /* 残念ながら "10" ではない */ return 0; }
$ ./sample-013.exe 'A' から 10 個 : ABCDEFGHIJ 'U' から 10 個 : UVWXYZ[\]^ 'k' から 10 個 : klmnopqrst '0' から 10 個 : 0123456789 '9' + 1 は.. : : $
Download : sample-014-01.c
/* * 2018/06/15 sample-014-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * printonedigit ( int n ) * 一桁の整数を出力する */ void printonedigit ( int n ) { putchar ( '0' + n ); /* n が 0 〜 9 の場合だけ、正く動く */ } /* * printonedigitln ( int n ) * 一桁の整数を出力して改行する */ void printonedigitln ( int n ) { printonedigit ( n ); /* 一桁の数値を出力し.. */ putchar ( '\n' ); /* 改行する */ }
Download : sample-014.c
/* * 2018/06/15 sample-014.c */ /* * extern 宣言 */ extern void println ( char *string ); extern void printonedigit ( int n ); extern void printonedigitln ( int n ); /* * 整数 */ int main ( void ) { println ( "整数値 0 の出力" ); printonedigitln ( 0 ); /* 「'0'」 でも 「"0"」 でもなく 「0」 */ println ( "整数値 9 の出力" ); printonedigitln ( 9 ); /* 一桁は OK */ println ( "整数値 11 の出力" ); printonedigitln ( 11 ); /* 上手く行かない */ println ( "整数値 1 + 1 の出力" ); printonedigitln ( 1 + 1 ); /* やっと計算がでてきた */ println ( "整数値 5 - 2 の出力" ); printonedigitln ( 5 - 2 ); /* 引算 */ println ( "整数値 3 * 2 の出力" ); printonedigitln ( 3 * 2 ); /* かけ算 */ println ( "整数値 8 / 3 の出力" ); printonedigitln ( 8 / 3 ); /* 小数点以下は余りは切り捨て */ println ( "整数値 8 % 3 の出力" ); printonedigitln ( 8 % 3 ); /* 余りは「%」をで計算 */ println ( "整数値 8 - ( 8 / 3 ) * 3 の出力" ); printonedigitln ( 8 - ( 8 / 3 ) * 3 ); /* 余りを求めるもう一つの方法 */ return 0; }
$ ./sample-014.exe 整数値 0 の出力 0 整数値 9 の出力 9 整数値 11 の出力 ; 整数値 1 + 1 の出力 2 整数値 5 - 2 の出力 3 整数値 3 * 2 の出力 6 整数値 8 / 3 の出力 2 整数値 8 % 3 の出力 2 整数値 8 - ( 8 / 3 ) * 3 の出力 2 $
Download : sample-015-01.c
/* * 2018/06/15 sample-015-01.c */ #include <stdio.h> /* putchar が必要なので.. */ /* * extern 宣言 */ extern void printonedigit ( int n ); /* * printpositiveintsub ( int n ) * 正の整数を出力する */ void printpositiveintsub ( int n ) { if ( n == 0 ) { /* 0 の場合 */ /* もう出力なくてよい */ } else { printpositiveintsub ( n / 10 ); /* 上位の桁を出力し */ printonedigit ( n % 10 ); /* 1 の位を出力する */ } } /* * printpositiveint ( int n ) * 非負の整数を出力する */ void printpositiveint ( int n ) { if ( n == 0 ) { /* 0 の場合は特別扱い */ putchar ( '0' ); /* 0 を出力 */ } else { /* その他の場合は、n 桁の処理 */ printpositiveintsub ( n ); /* 正の場合の処理 */ } } /* * printpositiveintln ( int n ) * 正の整数を出力して改行する */ void printpositiveintln ( int n ) { printpositiveint ( n ); /* 正の整数値を出力し.. */ putchar ( '\n' ); /* 改行する */ }
Download : sample-015.c
/* * 2018/06/15 sample-015.c */ /* * extern 宣言 */ extern void println ( char *string ); extern void printpositiveint ( int n ); extern void printpositiveintln ( int n ); /* * 整数 */ int main ( void ) { println ( "整数値 0 の出力" ); printpositiveintln ( 0 ); println ( "整数値 11 の出力" ); printpositiveintln ( 11 ); println ( "整数値 12345 の出力" ); printpositiveintln ( 12345 ); println ( "整数値 12 * 34 の出力" ); printpositiveintln ( 12 * 34 ); return 0; }
$ ./sample-015.exe 整数値 0 の出力 0 整数値 11 の出力 11 整数値 12345 の出力 12345 整数値 12 * 34 の出力 408 $
/* * 20180615-02-QQQQ.c * 出力する繰返し回数を整数で指定する ntimeprint を作りなさい * cf. * プリントの繰り返し回数を文字列の長さで指定する * f( "123", "Hello" ); * => * HelloHelloHello * => * Hello HelloHello * => * printf ( "Hello" ); * f( "23", "Hello" ); */ #include <stdio.h> /* * ntimeprint ( int times, char *message ) * ntimeprint ( 3, "Hello" ) * => * HelloHelloHello * => * Hello HelloHello * => * printf ( "Hello" ); * ntimeprint ( 2, "Hello" ) */ void ntimeprint ( int times, char *message ) { if ( times <= 0 ) { /* 非正なら、回数として不適切か、終わり */ /* 何もしないくてよい */ } else { /* 繰返し回数が正ならば.. */ printf ( message ); /* 少なくても一度は出力し.. */ ntimeprint (); } } /* * main */ int main ( void ) { printf ( "「Hello」を 3 回\n" ); ntimeprint ( 3, "Hello\n" ); printf ( "「ハ」を 30 回\n" ); ntimeprint ( 30, "ハ" ); printf ( "\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "一文字入力して[enter] キーを押してください :" ); putchar ( getchar() ); printf ( "\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "一文字入力して[enter] キーを押してください :" ); putchar ( getchar() + 1 ); /* もし、キーボードから「A」という文字が入力されたとする すると、'A' というもの(データ)が getchar() から帰ってくる # もちろん、そのまま、putchar に渡せば、画面「A」という文字が # 表示される しかし、今度は、+1 されている !! => 'A' =(ASCII)=> 65 'A' + 1 =(ASCII)=> 65 + 1 => 66 =(ASCII)=> 'B' */ printf ( "\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "一文字入力して[enter] キーを押してください :" ); putchar ( getchar() + 32 ); printf ( "\n" ); return 0; }
/* * 2018/06/15 sample-001.c */ #include <stdio.h> #include <string.h> /* * myPrintf (No.1) * * myPrintf の考え方 * * <意味を考える> * 「文字列」を全部を出力 * = 文字列の先頭の文字を出力 + 残りの文字列を出力 * = 「文字列」の先頭の文字を出力 + 「残りの文字列」を全部を出力(再帰) * * <再帰関数の形にする> * myPrintf ( 「文字列」 ) * = putchar ( 「文字列」の先頭 ) + myPrintf ( 「文字列」の残り ) * = putchar ( *「文字列」 ) + myPrintf ( 「文字列」+ 1 ) * * <再帰を利用する場合は「終了の場合」を作る> * myPrintf ( 「文字列」 ) * = if ( 「文字列」が空文字列の時 ) { * なにもしない * } else { * putchar ( *「文字列」 ); * myPrintf ( 「文字列」+ 1 ); * } * */ void myPrintf ( char *string ) { if ( !strcmp ( string, "" ) ) { /* 空文字列なら..(終了条件) */ /* 何もしなくてよい */ } else { /* まだ出力する文字があれば */ putchar ( *string ); /* 先頭の文字を出力する */ myPrintf ( string + 1 ); /* 残りの文字列を出力する */ } } /* * main */ int main ( void ) { myPrintf ( "abcde\n" ); myPrintf ( "xyz\n" ); return 0; }
#include <stdio.h> /* 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 1] */ /* 十通りの引数に対して、十通りの結果 => 条件分岐で OK */ if ( digit == 1 ) { /* 引数の値が 1 だったら.. */ putchar ( '1' ); /* 1 という文字を出力すればよい */ } else if ( digit == 2 ) { /* 引数の値が 2 だったら.. */ putchar ( '2' ); /* 2 という文字を出力すればよい */ } else if ( digit == 9 ) { /* 引数の値が 9 だったら.. */ putchar ( '9' ); /* 9 という文字を出力すればよい */ } else { /* そうじゃなかったら.. しょうがないので */ putchar ( '?' ); /* とりあえず ? を出す */ } } int main(void) { print_one_digit( 1 ); /* 画面に 1 がでる */ print_one_digit( 9 ); /* 画面に 9 がでる */ printf ( "\n" ); return 0; }
#include <stdio.h> /* **** まだ、C 言語で、整数値の計算や、その出力をやった事がない 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 2] */ /* 0 => '0' ( => 48 => 48 + 0 ) 1 => '1' ( => 49 => 48 + 1 ) .. 9 => '9' ( => 57 => 48 + 9 ) k => 'k' ( k + 48 ) */ /* 変数 digit がもっている整数値を出力するには、 それに 48 ( '0' ) を加えた値を文字として出力すればよい */ putchar ( digit + '0' ); /* これは、全体を網羅していないので注意 */ } int main(void) { print_one_digit( 1 ); /* 画面に 1 がでる */ print_one_digit( 9 ); /* 画面に 9 がでる */ printf ( "\n" ); return 0; }
#include <stdio.h> /* **** まだ、C 言語で、整数値の計算や、その出力をやった事がない 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 2] */ /* 0 => '0' ( => 48 => 48 + 0 ) 1 => '1' ( => 49 => 48 + 1 ) .. 9 => '9' ( => 57 => 48 + 9 ) k => 'k' ( k + 48 ) */ /* 変数 digit がもっている整数値を出力するには、 それに 48 ( '0' ) を加えた値を文字として出力すればよい */ putchar ( digit + '0' ); /* これは、全体を網羅していないので注意 */ } void print_two_digit(int digit) { /* 00 ? 99 までの値を表示したい .. */ /* [二桁] 表示するんだから、二回表示すればよいだろう.. */ /* 例 : 00 => 0 と 0 12 => 1 と 2 12 から 1 と 2 を取り出す必要がある */ print_one_digit ( digit / 10 ); /* 10 の位の数 */ /* 整数の割り算は、値が整数値になるように、小数点以下は、 切り捨てられる 12/10 => 1, 45 / 10 => 4 (10 の位の数)が取り出せる */ print_one_digit ( digit % 10 ); /* 1 の位の数 */ /* % は、余り計算 */ } int main(void) { print_two_digit( 19 ); /* 画面に 19 がでる */ printf ( "\n" ); return 0; }
#include <stdio.h> /* **** まだ、C 言語で、整数値の計算や、その出力をやった事がない 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 2] */ /* 0 => '0' ( => 48 => 48 + 0 ) 1 => '1' ( => 49 => 48 + 1 ) .. 9 => '9' ( => 57 => 48 + 9 ) k => 'k' ( k + 48 ) */ /* 変数 digit がもっている整数値を出力するには、 それに 48 ( '0' ) を加えた値を文字として出力すればよい */ putchar ( digit + '0' ); /* これは、全体を網羅していないので注意 */ } void print_positive_number(int number) { if ( number == 0 ) { } else { print_positive_number ( number / 10 ); print_one_digit ( number % 10 ); } } int main(void) { printf ( "0: " ); print_positive_number ( 0 ); printf ( "\n" ); printf ( "1: " ); print_positive_number ( 1 ); printf ( "\n" ); printf ( "12: " ); print_positive_number ( 12 ); printf ( "\n" ); printf ( "12345: " ); print_positive_number ( 12345 ); printf ( "\n" ); return 0; } /* 1234 => '1' '2' '3' '4' 12345 => '1' '2' '3' '4' '5' 1234 => 123 '4' 12345 => 1234 '5' print_positive_number( 12345 ) => 12345 を出力したいので、最終的には '1' '2' '3' '4' '5' => 1234 と '5' を出力 => print_positive_number ( 1234 ) print_one_digit ( 5 ) => print_positive_number ( 12345 / 10 ) print_one_digit ( 12345 % 10 ) 一般に、 print_positive_number( digit ) => print_positive_number ( digit / 10 ) print_one_digit ( digit % 10 ) 後は、終了時の問題 digit が 0 のときには、何も出力しない */
#include <stdio.h> /* **** まだ、C 言語で、整数値の計算や、その出力をやった事がない 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 2] */ /* 0 => '0' ( => 48 => 48 + 0 ) 1 => '1' ( => 49 => 48 + 1 ) .. 9 => '9' ( => 57 => 48 + 9 ) k => 'k' ( k + 48 ) */ /* 変数 digit がもっている整数値を出力するには、 それに 48 ( '0' ) を加えた値を文字として出力すればよい */ putchar ( digit + '0' ); /* これは、全体を網羅していないので注意 */ } void print_positive_number(int number) { if ( number == 0 ) { } else { print_positive_number ( number / 10 ); print_one_digit ( number % 10 ); } } void print_number(int number) { if ( number > 0 ) { /* number が正の数だったら */ print_positive_number ( number ); } else if ( number == 0 ) { /* number が 0 の時 */ putchar ( '0' ); } else { /* ここにきたら number < 0 に決まっている */ /* -123 => '-' '1' '2' '3' */ /* => '-' 123 */ putchar ( '-' ); print_positive_number ( number * (-1) ); } } int main(void) { printf ( "-123: " ); print_number ( -123 ); printf ( "\n" ); printf ( "-1: " ); print_number ( -1 ); printf ( "\n" ); printf ( "0: " ); print_number ( 0 ); printf ( "\n" ); printf ( "1: " ); print_number ( 1 ); printf ( "\n" ); printf ( "12: " ); print_number ( 12 ); printf ( "\n" ); printf ( "12345: " ); print_number ( 12345 ); printf ( "\n" ); return 0; } /* 次は、0 や、負の数も考えたい。 print_number 123 => '1' '2' '3' 0 => '0' -123 => '-' '1' '2' '3' */
#include <stdio.h> extern void print_number( int ); int main(void) { printf ( "-123: " ); print_number ( -123 ); printf ( "\n" ); printf ( "-1: " ); print_number ( -1 ); printf ( "\n" ); printf ( "0: " ); print_number ( 0 ); printf ( "\n" ); printf ( "1: " ); print_number ( 1 ); printf ( "\n" ); printf ( "12: " ); print_number ( 12 ); printf ( "\n" ); printf ( "12345: " ); print_number ( 12345 ); printf ( "\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "和: 123 + 456 = " ); print_number ( 123 + 456 ); printf ( "\n" ); printf ( "差: 123 - 456 = " ); print_number ( 123 - 456 ); printf ( "\n" ); printf ( "積: 123 * 456 = " ); print_number ( 123 * 456 ); printf ( "\n" ); printf ( "商: 123 / 456 = " ); print_number ( 123 / 456 ); printf ( "\n" ); printf ( "余り: 123 % 456 = " ); print_number ( 123 % 456 ); printf ( "\n" ); }
#include <stdio.h> /* **** まだ、C 言語で、整数値の計算や、その出力をやった事がない 整数を引数とする関数を作りたい => 一桁の整数値を出力する関数を考えたい */ void print_one_digit(int digit) { /* digit は、一桁の非負整数値(0,1,2,..,9)が指定される これを画面にだしたい */ /* [考え方:その 2] */ /* 0 => '0' ( => 48 => 48 + 0 ) 1 => '1' ( => 49 => 48 + 1 ) .. 9 => '9' ( => 57 => 48 + 9 ) k => 'k' ( k + 48 ) */ /* 変数 digit がもっている整数値を出力するには、 それに 48 ( '0' ) を加えた値を文字として出力すればよい */ putchar ( digit + '0' ); /* これは、全体を網羅していないので注意 */ } void print_positive_number(int number) { if ( number == 0 ) { } else { print_positive_number ( number / 10 ); print_one_digit ( number % 10 ); } } void print_number(int number) { if ( number > 0 ) { /* number が正の数だったら */ print_positive_number ( number ); } else if ( number == 0 ) { /* number が 0 の時 */ putchar ( '0' ); } else { /* ここにきたら number < 0 に決まっている */ /* -123 => '-' '1' '2' '3' */ /* => '-' 123 */ putchar ( '-' ); print_positive_number ( number * (-1) ); } } /* 次は、0 や、負の数も考えたい。 print_number 123 => '1' '2' '3' 0 => '0' -123 => '-' '1' '2' '3' */
/* * 2018/06/15 sample-001.c */ #include <stdio.h> #include <string.h> /* * myPrintf (No.1) * * myPrintf の考え方 * * <意味を考える> * 「文字列」を全部を出力 * = 文字列の先頭の文字を出力 + 残りの文字列を出力 * = 「文字列」の先頭の文字を出力 + 「残りの文字列」を全部を出力(再帰) * * <再帰関数の形にする> * myPrintf ( 「文字列」 ) * = putchar ( 「文字列」の先頭 ) + myPrintf ( 「文字列」の残り ) * = putchar ( *「文字列」 ) + myPrintf ( 「文字列」+ 1 ) * * <再帰を利用する場合は「終了の場合」を作る> * myPrintf ( 「文字列」 ) * = if ( 「文字列」が空文字列の時 ) { * なにもしない * } else { * putchar ( *「文字列」 ); * myPrintf ( 「文字列」+ 1 ); * } * */ void myPrintf ( char *string ) { if ( !strcmp ( string, "" ) ) { /* 空文字列なら..(終了条件) */ /* 何もしなくてよい */ } else { /* まだ出力する文字があれば */ putchar ( *string ); /* 先頭の文字を出力する */ myPrintf ( string + 1 ); /* 残りの文字列を出力する */ } } /* * main */ int main ( void ) { myPrintf ( "abcde\n" ); myPrintf ( "xyz\n" ); return 0; }
[前回の話] C 言語で「文字」が扱える 文字は、'A' の形で、「A」という文字を表現する # 対象(データ)を直接表現したものを「リテラル」と呼ぶ # 'A' は、「A」という文字のリテラル # "ABC" は、「ABC」という文字列のリテラル putchar(文字), getchar() で、文字の入出力ができる [今回の話] 「文字」は、計算ができる # cf. 文字列も計算ができた(例: "abc" + 1 => "bc" ) 実は、「文字」は、小さな整数値で表現されている # つまり、「文字」は、C 言語の中では、「小さな数値」でコーディングされている # => 「文字」と「整数値」の対応表[同型対応]がある # => その表は、(半角英数記号の場合)ASCII Code 表 C 言語での整数の扱い 123 は、整数値「123」を表すリテラル # cf. # "3" => 「3」の一文字からなる文字列(を表すリテラル) # '3' => 「3」という文字(を表すリテラル) # 3 => 「3」という整数値(を表すリテラル) # 3.0 => 「3」という実数値(浮動小数点数)(を表すリテラル) これまでは、関数の引数に、「文字列」のみ想定してきた 引数変数には、char * をつけてきた これからは、 関数の引数に、「文字列」だけでなく、 「文字」や「整数」を指定したい 「文字を渡したい場合」 char 「整数を渡したい場合」 int char 文字型を表す int 整数型を表す 整数値に関しては、 四則 ( +, -, *, / ) が使える あまりの計算 % が使える 例: 11 % 4 => 11 = 4 * 2 + 3 => 3 比較 == : 同じ != : 異なる > : 大きい < : 小さい >= : 以上 <= : 以下 # ほかにもいろいろできるが、自分で調べよう [まとめ] 整数型 (int 型) ^ -2^(31) ? 2^(31)-1 の範囲の整数値をとる 四則計算や、余りの計算、比較が可能 # print_number を使えば、画面にも表示できる 文字型 (char 型) は、実は、小さな(-128?127)の数値で、表現される 対応は ASCII Code 表に記載されている # 日本語は ? # 全角の文字は、基本 C 言語では扱えない # why ? => 2 byte 以上になる # windows : sjis => 2 byte # Ubuntu : utf-8 => 3 byte # => 1 byte では表せないから # 文字列(byte 列)は OK # 「文字」は、整数値なので、普通に計算ができる [ハノイの塔] API : 我々は何ができるか ? # 「巨人の肩に乗る」 # すでに、作られたものを再利用する # => 作った人のルール (API) を守る必要がある ハノイの塔の問題を解く 高さが 3 なので、人間が解いて、計算機には、その解を実行してもらう
Download : 20180615-01.c
/* * 20180615-01-QQQQ.c * コマンドライン引数で指定した長さのハノイの塔を解く */ #include <stdio.h> #include <stdlib.h> /* exit を利用するために必要 */ /* * ハノイプログラムには、s_hanoi.h が必要 */ #include "s_hanoi.h" /* * hanoi ( char *f, char *t, char *w, char *size ) * 高さ size のハノイの塔を、 * f で表されている棒から * t で表されている棒へ * w で表されている棒を * 作業領域として利用して移動する * w は空っぽか、size より大きな円盤しかない */ void hanoi ( char *f, char *t, char *w, char *size ) { if ( !strcmp ( size, "" ) ) { /* 空っぽだったら*/ /* する事はない */ } else { /* まだ仕事があるなら */ /* やりたい事は、 「size の大きさの塔を f から t に動かしたい」事 そのためには、最終的に、size の大きさの円盤を動かす必要がある。 そのためには、 size の大きさの上の塔を t を利用して、一旦、f から w に移し size の大きさ円盤を f から t に移し size の大きさの上の塔を f を利用して、w から、t に動かせば良い */ /* f の所にある size の円盤の上の塔を w に移動して退かす (再帰呼出し) */ hanoi ( f, w, t, size + 1 ); /* f の所にある size の円盤を t に移動 */ /* ** この部分を完成させなさい */ /* size の円盤の上に w に退かした塔を載せる (再帰呼出し) */ /* ** この部分を完成させなさい */ } } /* * ハノイの塔 プログラム */ int main ( int argc, char *argv[] ) { /* コマンドライン引数を用いるので、 int main ( int argc, char *argv[] ) と、main 関数の引数を宣言する。 */ if ( argc < 1 ) { /* 引数が指定されていない */ printf ( "ハノイの塔の高さを指定する文字列を指定してください\n" ); /* エラーメッセージの出力 */ exit ( -1 ); /* エラーコード : -1 でプログラム終了 */ /* main 関数内であれば return -1; でも可 */ } /* else {} */ /* 「else {}」は省略可 */ /* * 最初は "1" に全ての円盤が置いてある * これを "2" に全ての円盤を移動する */ /* * ハノイで、できること * s_hanoi_init() : ハノイプログラムの開始 : 最初に一度だけ呼び出す * s_hanoi_size ( char *discs ) : ハノイの塔の高さを設定する * s_hanoi_move ( char *from, char *to ) : from にある円盤を to に移す * s_hanoi_clear () : 最初の状態に戻す * s_hanoi_stop() : ハノイ塔プログラムの終了 : return 0 の前に呼び出す */ s_hanoi_init(); /* ハノイの塔のプログラムの初期変化 */ /* コマンドライン引数の一つ目 (argv[1]) で、問題の高さを初期化 */ /* s_hanoi_size を呼び出す */ /* ** この部分を完成させなさい */ printf ( "これから解答を開始します。[Enter] キーを押してください\n" ); putchar ( '>' ); putchar ( getchar() ); /* 開始前に、一旦停止 */ /* 解答開始 */ hanoi ( "1", "2", "3", argv[1] ); /* 解答終了 */ printf ( "プログラムを終了するには [Enter] キーを押してください\n" ); putchar ( '>' ); /* 終了前に確認 */ putchar ( getchar() ); s_hanoi_stop(); return 0; }
$ ./20180615-01-QQQQ.exe 1234 これから解答を開始します。[Enter] キーを押してください > プログラムを終了するには [Enter] キーを押してください > $
Download : 20180615-02.c
/* * 20180615-02-QQQQ.c * 出力する繰返し回数を整数で指定する ntimeprint を作りなさい */ #include <stdio.h> /* * ntimeprint ( int times, char *message ) */ void ntimeprint ( int times, char *message ) { if ( times <= 0 ) { /* 非正なら、回数として不適切か、終わり */ /* 何もしないくてよい */ } else { /* 繰返し回数が正ならば.. */ printf ( message ); /* 少なくても一度は出力し.. */ /* ** この部分を完成させなさい */ } } /* * main */ int main ( void ) { printf ( "「Hello」を 3 回\n" ); ntimeprint ( 3, "Hello\n" ); printf ( "「ハ」を 30 回\n" ); ntimeprint ( 30, "ハ" ); printf ( "\n" ); return 0; }
$ ./20180615-02-QQQQ.exe 「Hello」を 3 回 Hello Hello Hello 「ハ」を 30 回 ハハハハハハハハハハハハハハハハハハハハハハハハハハハハハハ $
Download : 20180615-03.c
/* * 20180615-03-QQQQ.c * 負の整数も処理できる printint を作成しなさい * ただし、正の整数を出力する printpositiveintsub, printpositiveint を利用してよい */ #include <stdio.h> /* * printint */ void printint ( int n ) { if ( n < 0 ) { /* 負の時は.. */ /* ** この部分を完成させなさい */ } else { /* 正の時には.. */ printpositiveint ( n ); } } /* * printintln */ void printintln ( int n ) { printint ( n ); putchar ( '\n' ); } /* * main */ int main ( void ) { printf ( "123 の出力\n" ); printintln ( 123 ); printf ( "-123 の出力\n" ); printintln ( -123 ); printf ( "123 + 456 の出力\n" ); printintln ( 123 + 456 ); printf ( "123 - 456 の出力\n" ); printintln ( 123 - 456 ); return 0; }
$ ./20180615-03-QQQQ.exe 123 の出力 123 -123 の出力 -123 123 + 456 の出力 579 123 - 456 の出力 -333 $