/* * CDATE FILENAME * * キーボードから一文字入力し、その文字によって異る国の挨拶をする */ #include <stdio.h> /* * hello ( char contry ) * char contry : 国を表す一文字 * j : 日本 * e : 英語 * c : 中国 * f : フランス語 * g : ドイツ語 */ void hello ( char cmd ) { if ( cmd == 'j' ) { /* 'j' の時は、日本語にする */ printf ( "こんにちは\n" ); } else if ( cmd == 'e' ) { /* 'e' の時は、英語にする */ /* ** この部分を完成させなさい */ printf ( "Good Afternoon\n" ); } else if ( cmd == 'c' ) { /* 'c' の時は、中国語にする */ printf ( "ニイハオ\n" ); } else if ( cmd == 'f' ) { /* 'f' の時は、フランス語にする */ printf ( "Bonjour\n" ); /* ** この部分を完成させなさい ** ** } e ... { */ printf ( "Guten tag\n" ); } else { /* どれでもなければ.. */ printf ( "???\n" ); } } /* * main */ int main( void ) { printf ( "国を表す文字を入力してください\n" ); printf ( "\tj\t日本\n" ); printf ( "\te\t英語\n" ); printf ( "\tc\t中国\n" ); printf ( "\tf\tフランス\n" ); printf ( "\tg\tドイツ\n" ); hello ( getchar() ); /* getchar() で文字を入力し、それに対応する結果を出す */ return 0; }
/* * CDATE FILENAME * * キーボードから一行(改行まで..)文字列を読込み、それを逆順に出す */ #include <stdio.h> /* * reverse ( char contry ) * char cmd : どのメッセージにするかを表す文字 * */ void reverse_line ( char ch ) { if ( ch == '\n' ) { /* 改行ならば.. */ /* なにもしなくてよい */ } else { /* そうでなければ.. */ putchar ( ch ); /* その文字を出力し、.. */ reverse_line ( getchar() ); /* 先読みをして、再帰呼出をする */ /* とすると、逆順ではなくて、入力順になってしまう.. */ } } /* * main */ int main( void ) { reverse_line ( getchar() ); /* 最初の文字を読み込んで .. */ putchar ( '\n' ); /* 改行を出力 */ return 0; }
#include <stdio.h> /* * 与えられた引数である文字列を二度出力する */ /* 関数に引数を与えたい 関数の宣言の頭部の所で、仮引数宣言をする 下例では「char *message:の部分 歴史: 一番最初は、「無条件に char* としろ」 二度目は、引数のタイプによって、表現を変えろ 文字を指定するなら「char」 整数を指定するなら「int」 にする */ void printMessageTwice ( char *message ) { /* 引数に文字列を指定する */ printf ( message ); /* 一回目の出力 */ printf ( message ); /* ニ回目の出力 */ } void printCharactorTwice ( char ch ) { /* 引数に文字を指定する場合 */ putchar ( ch ); /* 一回目の出力 */ putchar ( ch ); /* ニ回目の出力 */ } int main(void){ printMessageTwice ( "Hello World\n" ); /* "Hello, World を二度 */ printMessageTwice ( "こんにちは\n" ); /* "こんにちは を二度 */ printCharactorTwice ( 'A' ); /* A を二度 */ printCharactorTwice ( '8' ); /* 0 を二度 */ putchar ( '\n' ); /* 改行 */ return 0; }
#include <stdio.h> int main(void){ printMessageTwice ( "Hello World\n" ); /* "Hello, World を二度 */ printMessageTwice ( "こんにちは\n" ); /* "こんにちは を二度 */ printCharactorTwice ( "A" ); /* これはただしくない */ printCharactorTwice ( "8" ); /* これもただしくない */ putchar ( '\n' ); /* 改行 */ return 0; }
#include <stdio.h> extern printCharactorTwice ( char ch ); /* プロトタイプ宣言 */ /* 関数 printCharactorTwice の定義が別のファイルにあるので 引数の情報がわかならない その情報を「プロトタイプ宣言」の形で、追加してあげる */ int main(void){ printMessageTwice ( "Hello World\n" ); /* "Hello, World を二度 */ printMessageTwice ( "こんにちは\n" ); /* "こんにちは を二度 */ printCharactorTwice ( 'A' ); /* これはただしくない */ printCharactorTwice ( '8' ); /* これもただしくない */ putchar ( '\n' ); /* 改行 */ return 0; }
#include <stdio.h> void main ( void ) { printf ( "Hello, World\n" );/* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h> int main ( void ) { return 0; }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h>
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h> int nain ( void ) { printf ( "Hello, World\n" );/* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ int main ( void ) { printf ( "Hello, World\n" );/* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ int main ( void ) { return 0; }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ extern int printf (const char *__restrict __format, ...); /* #inclue <stdio.h> の代わりに、この一行を追加 */ int main ( void ) { printf ( "Hello, World\n" ); return 0; }
/* * 2015/05/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h> void main ( void ) { /* 頭の所で、int main に対応して、実は、return 0; が必要で、 void にしておけば、return 0; は不要 */ printf ( "Hello, World\n" );/* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ /* return の正体に関しては、次週 or 次々週に説明する予定 */ }
#include <stdio.h> int sub() { printf ( "hello\n" ); } int main(void) { sub(); return 0; }
#include <stdio.h> void printCharctorTri ( char ch ) { putchar ( ch ); putchar ( ch ); putchar ( ch ); } int main (void) { printCharctorTri ( 'A' ); printCharctorTri ( '6' ); putchar ( '\n' ); return 0; }
#include <stdio.h> void printCharctorTri ( char ch ) { putchar ( ch ); putchar ( ch ); putchar ( ch ); } int main (void) { printCharctorTri ( 'A' ); /* プログラム内で、引数の値を指定している */ printCharctorTri ( getchar() ); /* キーボードからの入力で、引数の値を指定する */ /* 文字を直接指定するのではなく、getcahr() からの 帰り値(関数値)で指定する */ /* この段階で、関数 getchar() が呼び出されて キーボードから一文字入力し、 その文字に置き換わる */ putchar ( '\n' ); return 0; }
#include <stdio.h> void printCharctorTri ( char ch ) { putchar ( ch ); putchar ( ch ); putchar ( ch ); } int main (void) { printCharctorTri ( 'A' ); printCharctorTri ( getchar() ); /* 五つ文字を読み込む */ printCharctorTri ( getchar() ); printCharctorTri ( getchar() ); printCharctorTri ( getchar() ); printCharctorTri ( getchar() ); putchar ( '\n' ); return 0; }
#include <stdio.h> /* 例題: キーボードから入力された文字列を、そのまま画面に出力するプログラム */ int main(void) { putchar ( getchar() ); /* 一文字入力して、その一文字を出力する */ return 0; }
#include <stdio.h> /* 例題: キーボードから入力された文字列を、そのまま画面に出力するプログラム */ int main(void) { putchar ( getchar() ); /* 一文字入力して、その一文字を出力する */ putchar ( getchar() ); /* 一文字入力して、その一文字を出力する */ putchar ( getchar() ); /* 一文字入力して、その一文字を出力する */ /* 結果的に、三文字入力して、その入力した三文字を出力する */ return 0; }
#include <stdio.h> void echoback ( void ) { putchar ( getchar() ); echoback(); } int main(void) { echoback(); return 0; }
#include <stdio.h> /* * 改行迄をエコーバックする */ void echobackToEnter ( char ch ) { if ( ch == '\n' ) { /* 先読みした文字が改行だったら、何もしない */ putchar ( '\n' ); /* コピーがおわったら、改行する */ } else { putchar ( ch ); /* その文字を出力し、.. */ echobackToEnter ( getchar() ); /* 先読みをして、再帰呼出をする */ } } int main(void) { echobackToEnter ( getchar() ); /* 先読みをする */ return 0; }
分割コンパイル 前回の課題 3 (printint を作れ) 20150515-03-9999.c の中に printint 定義がある printint で利用している printpositive は sample-015-01.c の中に定義 printpositive で利用している printdigit は sample-014-01.c の中に定義 なので、(利用している関数が別のソースファイルに入っている) 20150515-03-9999.exe を作るには、 20150515-03-9999.o の他に sample-015-01.o sample-014-01.o が必要 この場合は、それぞれをコンパイルして、後で、それをまとめて実行ファイルを作る 具体的には次のコマンドで作成する。 cc -c 20150515-03-9999.c cc -c sample-015-01.c cc -c sample-014-01.c cc -o 20150515-03-9999.exe 20150515-03-9999.o sample-015-01.o \ sample-014-01.o 分割コンパイルの利点は *.o を使い回せる 例: sample-014-01.o は、sample-014.o と一緒に、sample-014.exe を作るために使った しかも、sample-05.exe や 20150515-03-9999.exe にも使った 「実」を言えば printf.o (に相当する printf の定義されたファイル) も、再利用されている Shell Script 分割コンパイルをする時は、作業量が増える 例: p-001.c cc -c p-001.c cc -o p-001.exe p-001.o p-003.c + p-002-01.c cc -c p-003.c cc -c p-002-01.c cc -o p-003.exe p-002-01.o 複数のコマンドが一度にできると便利 次のようなファイルを作成する mkp-003.sh -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- # cc -c p-003.c cc -c p-002-01.c cc -o p-003.exe p-003.o p-002-01.o -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- 一行目は 「 #」の行 二行目以後は、実行したいコマンドを並べる 拡張子は、習慣により .sh を付ける 次に、次のコマンドを実行する -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- sh mkp-003.sh -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- すると、mkp-003.sh の中の三つコマンドが実行される 一度に、三つのコマンドが実行できるようになった mkp-001.sh と mkp-004.sh を比較すると ファイルの中の 001 の部分と 004 の部分が異るだけ 一部分だけが異る場合は、「変数」を使えば、まとめられる shell script では、使える「変数名」に制限がある 実引数 : コマンドライン引数で指定したもの 仮引数 : 順に $1, $2, .. という変数名を利用する コマンドラインで指定した k 番目の引数の値が $k で参照される mkp-n.sh -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- # cc -c p-$1.c cc -o p-$1.exe p-$1.o -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- 使う時は、 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- sh mkp-n.sh 001 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- とすると、mkp-n.sh の中の $1 が 001 に置き換わるので、mkp-001.sh と同じ -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- sh mkp-n.sh 004 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- とすると、mkp-n.sh の中の $1 が 004 に置き換わるので、mkp-004.sh と同じ になる。 Hello, World 再び main 関数はないと駄目 C 言語のプログラムでは、必ず main 関数が必要 C 言語のプログラムでは、最初に main 関数が呼び出される そして、main 関数から、他の関数が呼び出される形で、プログラムが動く #include <stdio.h> は、printf を使う時に必要な表記だった # 実は、stdio.h の中に printf の引数に関する情報が記述されている # プロトタイプ宣言が入っています。 return 0; は int main() と関係がある void main() とすれば、return 0 は不要 入力 getchar() 関数は、文字を指定する場所に、文字の代わりに置くことができる その文字が本当に必要になった時点で、キーボードからの入力をまって、 その文字におきかわる。 getchar() は、一文字ずつよみこむが、キーボードから入力する時は、 [Enter]キーをおすまで、先にすすまない [Enter]キーをおすと、そのエンターキーに対応する '\n' までがはいる 例題: キーボードから入力された文字列を、そのまま画面に出力するプログラム putchar ( getchar() ); を繰り返せばよい 「繰返し」ときたら... 「再帰呼出」 echoback() --> putchar ( getchar() ); putchar ( getchar() ); ... putchar ( getchar() ); ... --> putchar ( getchar() ); + putchar ( getchar() ); ... putchar ( getchar() ); ... --> putchar ( getchar() ); + echoback(); ABC -> ABC echoback ( getchar() ) -> putchar ( ch ) echoback ( getchar() ) ABC -> CBA reverse_line ( getchar() ) -> reverse_line ( getchar() ) putchar ( ch )
# echo 1st $1 echo 2nd $2 echo 3td $3
# cc -c p-001.c cc -o p-001.exe p-001.o
# cc -c p-003.c cc -c p-002-01.c cc -o p-003.exe p-003.o p-002-01.o
# cc -c p-004.c cc -o p-004.exe p-004.o
# cc -c p-$1.c cc -o p-$1.exe p-$1.o
今週の新規追加課題はなく、先週の課題を解いてください。