プログラミング言語 2 第 05 回 (2007 年 06 月 04 日 ) 今日の配布物 片面の用紙 1 枚 今日の課題が書かれています 本日の出欠を兼ねています 1
今日やること http://www.tnlab.ice.uec.ac.jp/~s-okubo/class/language/ にアクセスすると 教材があります 2007 年 06 月 04 日分と書いてある部分が 本日の教材です 本日の内容 先週の課題の簡単な解答 math library 型変換とキャスト 典型的なリファレンスの読み方 課題について 課題は 授業の最後に必ず出して下さい 途中までしかできて無くても 出して下さい 提出 非提出が出席点に直結します 終わらなかったら 次回の授業までにやっておいてください 模範解答と解説を行います ( 再提出する必要はありません ) 課最終レポートのときまでには 全部わかるようにしておきましょう 2
第 04 回の課題の簡単な解説 第 04 回の課題 課題 : 次の要求を満たすプログラムを書け 要求 1: input.txt を開いて 入力データを読み込む input.txt は 10 行からなっている input.txt の 各行には スペースで区切られて 2 つの整数値が並んでいる 1 つめの整数値を x 2 つめの整数値を y とする 要求 2: output.txt に出力を書き込む output.txt は 10 行からなる input.txt の 各行には スペースで区切られて 2 つの整数値が並んでいる 1 つめの整数値は x とする 2 つめの整数値は y y 2 y 10 とする 3
入力ファイル 1 1 2 3 3 2 4 5 5 4 6 7 7 6 8 9 9 8 10 10 スペースで区切られて 2 つの値が並び それが全部で 10 行ある fscanf の使い方について fscanfは スペースや改行を区切り文字として認識 (scanf も同様 ) 入力ファイルから 今回の入力データは fscanfにとっては 1 1 2 3 3 2 4 5 5 4 6 7 7 6 8 9 9 8 10 10 のように 20 個の整数値が スペースで区切られて書かれているのと同じ fscanfは formatの中に %d があると 1つ符号付 10 進数を読み込みむ プログラム全体で 20 回 %d が出るようにすれば すべてのデータを読み込める 4
ファイルの入出力 ファイルの扱い方ですが 1. ファイルをオープンする (fopen) その際に 自分が これから先 どのようなやり取りをしたいかも指定する 2. 実際に ファイルに書き込んだり ファイルから読み込んだりする (fscanf, fprintf) 3. ファイルを閉じる (fclose) という手順を踏まないといけないということを もう一度 復習しておきましょう 回答例 プログラムの方針例 : 1. 入力用と出力用で それぞれファイルを開く 2. 1 つの scanf で 2 つの値 (1 行分 ) を読み込む 3. 2 つの値を読み込んだら すぐに計算して ファイルに出力する 4. 上記のことを 10 回繰り返す ( 全部で 10 行分 ) 5
その 1/4: 回答例 回答例 プログラムの方針例 : 入力用と出力用で 用それぞれファイルを開く 1. 入力用 2. 1 つの s c a n f で 2 つの値 ( 1 行分 ) を読み込む 3. 2 つの値を読み込んだら すぐに計算して ファイルに出力する 4. 上記のことを 1 0 回繰り返す ( 全部で 1 0 行分 ) #include<stdio.h> // // 入出力を使うので stdio.h を include する FILE *fp, *fp2 // // FILE 構造体のポインタ fp fpと fp2 を宣言 // // 読み取りファイル用と書き込みファイル用 int i; i; // // 整数型の変数 i i を宣言 for for 文で使用する用 int x,y; // // 整数型の変数 x と y を宣言 // // 2 つの値を読み込むため その 2/4: 回答例 回答例 プログラムの方針例 : 入力用と出力用で 用それぞれファイルを開く 1. 入力用 2. 1 つの s c a n f で 2 つの値 ( 1 行分 ) を読み込む 3. 2 つの値を読み込んだら すぐに計算して ファイルに出力する 4. 上記のことを 1 0 回繰り返す ( 全部で 1 0 行分 ) main(){ fp=fopen("input.txt","r"); // // input.txt を読み込み用に // // 開き fp fpと関連付け fp2=fopen("output.txt","w"); //output.txt を書き込み用 // // に開いて fp2 と関連付け 今回は input.txt から読み込み output.txt に書き込むように ファイルを開きます 6
その 3/4: 回答例 回答例 プログラムの方針例 : 1. 入力用と出力用で それぞれファイルを開く 2. 1つの sc an f つの sc an fで 2 つの値 ( 1 行分 ) を読み込む つの値を読み込んだら すすぐに計算して ファイルに出力する る 3. 2つの 上記のことを 10 回繰り返す ( 全部で部 1 0 行分 ) 4. 上記 for(i=1;i<=10;i++){ // // 入力ファイルは 10 10 行あるので // // 10 10 回繰り返す fscanf(fp,"%d%d",&x,&y); // // fp fpから 2 つの整数を // // 読み込み x と y に代入する fprintf(fp2,"%d %d n",x,y*y-2*y-10); // // 2 つの値を fp2 に書き込む } 1 つの fscanf で 2 つの値 ( つまり 1 行分 ) を読み込んでいます それを 10 回繰り返しています 回答例 その4/4: fclose(fp); // // fp fpを閉じる fclose(fp2); // // fp2 を閉じる } ファイルをクローズして 終わります 7
math library math library とは 数値演算の関数がつまったライブラリ このライブラリを使用することによって 一般的な数値演算の関数を利用できるようにる 使用するためには 1. ソースファイルで math.h を include する 2. コンパイルするときに libm をリンクする ことが必要になる 8
libm とのリンクの仕方 コンパイルするときに -lmというオプションをつける gcc -lm sample.c libm.so とリンクするように指定 できた実行ファイル (a.out) に対して ldd a.out とすると リンクしていることを確認できる ソースの書き方 サンプルプログラム : #include<stdio.h> #include<math.h> math library を使用するときには math.h を include する double f; f; main(){ scanf("%f",&f); printf("%f n",log(f) log(f)); } math.h を include したので log が使用できる このサンプルプログラムでは 標準入力から double 型の値を読み込んで その値の log を返しています 9
math library の主な関数 三角関数関係 : double cos(double x) cos( x) double sin(double x) sin( x) double tan(double x) tan( x) double acos(double x) acos( x) double asin(double x) asin( x) double atan(double x) atan( x) double cosh(double x) x y ( e e ) 2 double sinh(double x) double sinh(double x) cosh x y ( e + e ) 2 ( x) sinh( x) x のコサイン x のサイン x のタンジェント x のアークコサイン x のアークサイン x のアークタンジェント x の双曲線コサイン x の双曲線サイン x の双曲線タンジェント math library の主な関数 累乗と対数と絶対値関係 : double pow(double x, double y) double sqrt(double x) double exp(double x) double log10(double x) double log(double x) int abs(int x) double fabs(double x) y x x x e log 10 ( x) ln( x) x x x の y 乗 x の平方根自然対数 e の x 乗 x の常用対数 x の自然対数整数 x の絶対値 double 型の x の絶対値 10
math library の主な関数 切り捨てと切り上げと余り関係 : double modf(double x, double *y) double fmod(double, double) double floor(double x) double ceil(double x) x x 浮動小数点実数 x から 符合付き整数を小数部分を取り出す 戻り値として小数部分が *y に整数部分が入る x を y で割ったあまりを計算 x の小数点以下切り捨て x の小数点以下切り上げ 例 : #include<stdio.h> #include<math.h> math.h を include する double x,y,z; x,y,z に値を読み込み main(){ ln( y) scanf("%f",&x); sin ( x) + x を scanf("%f",&y); z scanf("%f",&z); 計算して出力 printf("%f n",(sin(x)+pow(x,log(y)))/sqrt(z)); } 11
型変換とキャスト 型変換 次のようなプログラムの場合 #include<stdio.h> int i; i; double d; d; main(){ i=2; d=i; printf("%f n",d); } double 型の変数に整数型の変数 i の値を代入している! 大丈夫 C 言語では 自動的に型変換を行い 情報を失うことなく代入してくれます 今回も double 型の変数 d には 2 という値が代入されます 12
型変換 C 言語では 自動的に型変換が行われる 型の違う変数へ代入 double の変数に int を代入等 関数の引数として 異なる型の値を代入 pow(x,y) の x として整数値を渡す等 できる限り 情報を失うことがないように変換する int から double や float から double は 情報を失うことなく きちんと変換する double から int や double から float は 変換する際に情報が欠落する 強制的な型変換 ( キャスト ) 強制的に型変換を行うこともできる ( 型名 ) を 変数や値につける #include<stdio.h> int i; i; double d; d; main(){ i=2; d=(double)i; printf("%f n",d); } int 型の変数 i の値を double 型に変換したのち d に代入 d=i としたときと同じ 気にしなくてもプログラムを書くことができる場合も多い しかし 型変換を意識しないといけない場合もある 13
リファレンスの読み方 リファレンス C 言語のリファレンスとは 要するに 関数のリファレンス 引数として何を与えるか 引数と返値の型 関数が実行する内容 関数のリファレンスには 何通りか流儀があるらしい 自分で関数を作るときや /usr/include/ 以下を覗いた時など用に 読めた方がよい 14
リファレンスの書かれ方 以下の 3 つは 同じ事を言っている その1: double sample(double, int) この後 引数と戻り値の関係や 関数の動作が書かれます その2: double sample(double x, x, int inty) y) この後 引数と戻り値の関係や 関数の動作が書かれます その3: double sample(x, y); y); double x; x; int inty; y; この後 引数と戻り値の関係や 関数の動作が書かれます リファレンスの例 名前 pow 累乗関数 書式 #include <math.h> double pow(double x, x, double y); ライブラリ math library (libm, -lm) 説明 x の y 乗の値を返す コマンドプロンプトで man pow と打つと 見ることができます ( たぶん英語です ) 15
リファレンスの例 名前 pow 累乗関数 書式 ライブラリ 説明 #include <math.h> double pow(double x, x, double y); math library (libm, -lm) x の y 乗の値を返す コマンドプロンプトで man pow と打つと 見ることができます ( たぶん英語です ) 関数の名前 関数の概要 ヘッダ 引数の数 引数の型 戻り値の型等 ライブラリの名前 ファイル名 リンクするときの引数 関数の説明 挙動 16