#include <stdio.h> /* 与えられた引数(文字列)の二文字目を返す関数 */ char second_charactor(char *string) { /* string が表す文字列の二文字目を返す */ /* 二文字目は、「string[1]」で表現される */ /* string[1] = *(string + 1) = 「string の先頭を一文字削って、その先頭の文字」*/ /* 例: "abc"[1] = *( "abc" + 1 ) = *( "bc" ) = 'b' */ /* 「string[1]」の値を返せばよい */ return string[1]; /* return 命令により、string[1] の値が返る */ /* この関数は char 型の値を返す */ } int main(int argc, char *argv[]) { printf ( "文字列 「abc」の二番目の文字は " ); putchar ( second_charactor ( "abc" ) ); /* 'b' が出力される */ printf ( "\n" ); printf ( "文字列 「1234」の二番目の文字は " ); putchar ( second_charactor ( "1234" ) ); /* '2' が出力される */ printf ( "\n" ); return 0; }
#include <stdio.h> int main(int argc, char *argv[]) { /* main 関数には、コマンドライン引数(空白文字でわけられている)の内容が argc : 引数の個数 + 1 argv : argv[k] (k>0) k 番目の引数の文字列 */ printf ( "2 番目の引数(パラメータ)は : " ); printf ( argv[2] ); printf ( "です。\n" ); /* コマンドライン引数が 2 つ以上ある場合しか想定していない */ /* 結果 : (誤り易い人間が、誤って..) 2 未満の引数しか指定しない 場合を想定していないので、その場合に、何が起きるか保証できない */ return 0; }
#include <stdio.h> int main(int argc, char *argv[]) { /* main 関数には、コマンドライン引数(空白文字でわけられている)の内容が argc : 引数の個数 + 1 argv : argv[k] (k>0) k 番目の引数の文字列 */ if ( argc > 2 ) { /* 引数が 2 個以上の時だけ、適切なプログラム */ printf ( "2 番目の引数(パラメータ)は : " ); printf ( argv[2] ); printf ( "です。\n" ); /* 正常にプログラムが動作 */ } else { printf ( "引数を 2 個以上、指定してください。\n" ); /* 異常な状態がおきている */ exit ( -1 ); /* エラーを報告して、終了する */ /* exit 関数、呼び出すをもどってこない => プログラムを終了する。その時に、引数で 指定した、値を、エラーコードとして報告 */ /* エラーコードは、0 は正常で、0 以外は異常 */ /* 異常の場合は、その値がエラーの種類を表す (エラーコード) */ /* main 関数では、「return 式;」で置き換える事も可能 逆に main 以外では、exit 関数呼び出す事によって、 (main に戻らないで..) プログラムを終了(abort)する事できる => プログラムの途中で、どうしても続きができない場合 exit 関数を利用して、エラーステータスを返して、終了する */ } return 0; /* 0 という正常値を返していた... */ }
#include <stdio.h> int zero_dev ( int a, int b ) { /* 本来は、ここで、 b の値が 0 でない事を確認する必要がある */ /* もし、仮に 0 なら、その時には、適切な処理を(考えて/取り決めをして)行う */ return a / b; } int main(int argc, char *argv[]) { printf ( "プログラムスタート\n" ); /* zero_dev ( 1, 1 ); */ /* 正常 */ zero_dev ( 1, 0 ); /* 異常 */ printf ( "プログラムエンド\n" ); return 0; }
#include <stdio.h> /* 以下、main 関数の定義をしている */ /* main の前の int => main 関数が「整数値」を返す関数 main の後ろ () の中身は、関数への引数変数 変数には、その関数が呼び出されるたびに、呼び出す側が指定した値を持つ int argc, 整数値 : コマンドライン引数の個数 + 1 char *argv[] 引数文字列 : argv[k] とすると k 番目の文字列 C プログラムには、必ず main 関数が必要 */ int main(int argc, char *argv[]) { /* main => 関数名 */ printf ( "Hello, World\n" ); /* printf という標準ライブラリ関数を利用している */ /* 本来 関数を利用するには、その関数が定義されていないといけない */ /* ところが、printf は、(少なくても自分では..) 定義していない */ /* 誰か(自分以外の)他の人が、printf を定義してくれている */ return 0; /* main 関数の返り値が 0 : 正常[終了] */ } /* 一周目 プログラムのひな型 小さいながら、完全に動く、意味のプログラム -> 新しいプログラムを作るための、スタート台 */ /* プログラムは作っただけではやくにたたない コンパイル(リンク)して、実行しないと意味がない ubuntu 上で コンパイル cc -c ファイル名(*.c) 例 : cc -c p-006.c => C 言語で記述されたソースコード(プログラム)が、 機械語で記述されたオブジェクトコード(プログラム)に、 変換される cc : コンパイルをするプログラム リンク cc -o *.exe *.o 例 : cc -o p-005.exe p-005.o => 機械語で書かれたプログラムに、 さらに実行に必要別のプログラムを追加して、 単体で実行可能な、「実行ファイル」を作成する *.exe は実行ファイル プログラムの中で利用されている関数に対して、 その関数の定義をライブラリからさがし、 追加してくれる。 あれば OK だが、なければエラーになる 実行 ./*.exe 例 : ./p-005.exe */
/* * 2018/06/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h> int nain ( int argc, char *argv[] ) { printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
/* * 2018/06/22 sample-001.c */ /* * "Hello, World" again */ #include <stdio.h> int main ( int argc, char *argv[] ) { printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
/* * 2018/06/22 sample-002.c */ /* * "Hello, World" again */ #include <stdio.h> int main ( int argc, char *argv[] ) { return 0; }
/* * 2018/06/22 sample-003.c */ /* * "Hello, World" again */
/* * 2018/06/22 sample-004.c */ /* * "Hello, World" again */ int main ( int argc, char *argv[] ) { printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
/* * 2018/06/22 sample-004.c */ /* * "Hello, World" again */ extern int printf ( const char *, ... ); int main ( int argc, char *argv[] ) { printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
[前回の復習] 関数の値 関数には、引数の形で情報を与える事ができる 関数は、与えられた引数の値(情報)によって、 振る舞いを変更する事ができる => 引数という一部を変更すだけで、異なる動作を記述できる 関数は、いろいろな動きの抽象化 引数付きの実行は、関数の動作の具体化 関数から逆に、呼び出し側に情報を「返す」事ができる 返す情報の事を「返り値」と呼ぶ 関数の定義(本体)内で、return 命令を実行すると、 return 命令の後ろにある「式」の値が、関数の返り値となる [注意] 関数の本体内 ( { ? } ) で、return 命令が実行されると、 関数は、その時点で終了する。 => 基本、関数は、閉じ } で終わるが、 return 命令を途中に置くことで、「中断」可能 「C 言語の『関数』」は、二つの側面を持つ 式の中の値を計算する仕組みの一部 => 数学の『関数』と同じ 例 : f(x) + g(x) => f(x), g(x) それぞれ計算されて、値に代わり、 その値がさらに、加えられる 「一つの命令」として、なんらかの行為(命令の実行)をする単位 関数を呼び出す事により実行される内容 => 副作用 一つのものに複数の役割を担わせるは、あんまり良くない これまでは、副作用だけ議論してきた これからは、値の議論もできるようになった... おすすめ : 値を返す関数と、副作用を行う関数(目的が異なる)は、 完全に区別して、作成する事が、安全(効率がわるいかもしれない..) [おまけ] s_input.h と s_print.h の使い方を説明 => 色々な「型(int, char, 文字列)]の情報の入出力の Library [エラー処理と exit 関数] 人間は、誤る生き物なので、人間の誤りに対応する処理(エラー処理) が必要。 基本は、if 構文を利用して、「誤り検知」を行う 誤りがなければ、正常処理 誤りがある場合は、適切な「エラー処理」を行う 例 : エラーメッセージを出力する / 悪い事が起きないように命令を無効にする 誤りが原因で、プログラムの継続ができない場合 exit 関数で、プログラムを abort (異常終了) させる事ができる exit 関数の引数は、「プログラムの終了コード」として、プログラムの呼び出し側に報告される 例 : shell は、$? や &&, || で、そのコードを利用できる ! exit 関数は、main 以外でも使える ! main 関数は、exit の代わりに return でもよい ! main 関数の「return 0」は実は、「正常」の終了コードを返していた [二周目] 最初から、もう一度 一周目で「内緒(おまじない)」の部分を、今度は、ちゃんと説明する 今やっている内容を適切に理解するために、一周目の内容を参照する A => B => C => .. => Z ^ | | | +<--------+ 復習をする ( 実際に、以前の内容を / 話を聞きながら、復習 ) Hello, World again 基本的なプログラム ひな型に プログラムの実行のサンプル sample-001.c => Hello, World sample-002.c => printf を削除すると、何も表示されない => 表示を行っているのは printf => printf の部分だけを変更し、他は「おまじない」 <= 意味があることをしめしたい sample-003.c => main の定義も削除 => プログラムとしてなりたたない => C 言語でプログラムを作成するには、 main 関数が必要
Download : 20180706-01.c
/* * 20180706-01-QQQQ.c * 「Hello, 自分の名前」を出力する */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { printf ( /* q:ここ */ ); return 0; }
$ ./20180706-01-QQQQ.exe Hello, 栗野 $
Download : 20180706-02.c
/* * 20180706-02-QQQQ.c * 「Hello, 自分の名前」を三回、出力する * */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { printf ( /* q:ここ */ ); printf ( /* q:ここ */ ); printf ( /* q:ここ */ ); return 0; }
$ ./20180706-02-QQQQ.exe Hello, 栗野 Hello, 栗野 Hello, 栗野 $
Download : 20180706-03.c
/* * 20180706-03-QQQQ.c * コマンドライン引数に名前を一つ指定し、その人に挨拶をする */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { if ( argc == 2 ) { printf ( /* p:ここ */ ); /* 挨拶 */ printf ( /* q:ここ */ ); /* 一つ目の引数を出力 */ printf ( "\n" ); /* 改行 */ } else { printf ( "引数を一つ指定してください。\n" ); exit ( -1 ); /* エラーコードを出力する */ } return 0; }
$ ./20180706-03-QQQQ.exe kurino Hello, kurino $