/*
* 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
今週の新規追加課題はなく、先週の課題を解いてください。