#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 $