プログラミング演習3 - Cプログラミング -

Similar documents
プログラミング演習3 - Cプログラミング -

Taro-ファイル処理(公開版).jtd

2006年10月5日(木)実施

PowerPoint プレゼンテーション

Prog1_12th

memo

Microsoft PowerPoint - kougi4.ppt

PowerPoint Presentation

情報処理演習 B8クラス

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

02: 変数と標準入出力

gengo1-12

演算増幅器

gengo1-12

Microsoft PowerPoint - kougi2.ppt

計算機プログラミング

gengo1-12

Microsoft PowerPoint - 第3回目.ppt [互換モード]

Microsoft PowerPoint - kougi6.ppt

ファイル入出力

FORTRAN( と C) によるプログラミング 5 ファイル入出力 ここではファイルからデータを読みこんだり ファイルにデータを書き出したりするプログラムを作成してみます はじめに テキスト形式で書かれたデータファイルに書かれているデータを読みこんで配列に代入し 標準出力に書き出すプログラムを作り

PowerPoint Presentation

02: 変数と標準入出力

ファイル入出力

Microsoft Word - Cプログラミング演習(9)

プログラミング実習I

Prog1_10th

プログラミング基礎

Microsoft PowerPoint - prog06.ppt

ゲームエンジンの構成要素

Microsoft PowerPoint - 計算機言語 第7回.ppt

slide5.pptx

Microsoft PowerPoint pptx

Microsoft PowerPoint - prog04.ppt

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft Word - no204.docx

Microsoft Word - Cプログラミング演習(12)

02: 変数と標準入出力

Microsoft Word - no15.docx

memo

slide4.pptx

Microsoft PowerPoint - kougi9.ppt

02: 変数と標準入出力

Microsoft Word - Cプログラミング演習(10)

※ ポイント ※

第1回 プログラミング演習3 センサーアプリケーション

PowerPoint プレゼンテーション

PowerPoint Presentation

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

Microsoft PowerPoint - lec10.ppt

C言語講座 ~ファイル入出力編~

Microsoft PowerPoint - 11.pptx

1. ファイルにアクセスするには ファイルにアクセスするには 1. ファイルを開く 2. アクセスする 3. ファイルを閉じるという手順を踏まなければなりません 1.1. ファイルを読み込む まずはファイルの内容を画面に表示させるプログラムを作りましょう 開始 FILE *fp char fname

Microsoft PowerPoint - kougi7.ppt

memo

Microsoft Word - 3new.doc

C言語入門

Microsoft PowerPoint - guidance.ppt

Microsoft PowerPoint - 14th.ppt [互換モード]

Microsoft Word - no11.docx

Microsoft PowerPoint - kougi8.ppt

Microsoft PowerPoint ppt

02: 変数と標準入出力

Microsoft PowerPoint - 13.ppt [互換モード]

PowerPoint プレゼンテーション

Microsoft PowerPoint - 12.ppt [互換モード]

文字列 2 前回の授業ではコンピュータ内部での文字の取り扱い 文字型の変数 文字型変数への代入方法などを学習した 今回は 前回に引き続き 文字処理を学習する 内容は 標準入出力 ( キーボード ディスプレイ ) での文字処理 文字のファイル処理 文字を取り扱うライブラリ関数である 標準入出力 Lin

Microsoft Word - no202.docx

PowerPoint プレゼンテーション - 物理学情報処理演習

02: 変数と標準入出力

ポインタ変数

02: 変数と標準入出力

プログラミング基礎

02: 変数と標準入出力

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

ポインタ変数

プログラミング及び演習 第1回 講義概容・実行制御

02: 変数と標準入出力

02: 変数と標準入出力

関数の動作 / printhw(); 7 printf(" n"); printhw(); printf("############ n"); 4 printhw(); 5 関数の作り方 ( 関数名 ) 戻り値 ( 後述 ) void である. 関数名 (

Microsoft PowerPoint - 09.pptx

PowerPoint プレゼンテーション

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

PowerPoint プレゼンテーション

Microsoft PowerPoint - 10Com2.ppt

< F2D837C E95CF CF68A4A94C5816A2E6A>

Microsoft PowerPoint pptx

講習No.12

kiso2-03.key

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

プログラミングI第6回

Microsoft PowerPoint - 12.ppt [互換モード]

Microsoft PowerPoint - CproNt11.ppt [互換モード]

Cプログラミング1(再) 第2回

情報処理Ⅰ演習

PowerPoint プレゼンテーション

データ構造

PowerPoint プレゼンテーション

Prog1_6th

Transcription:

プログラミング演習 3 - 集中講義版 - 1 日目資料 & 課題花泉弘

この回の目標 1. テキストファイルからのデータの読み出し ファイルの open と close 1 文字ずつの入力と 1 行ずつの入力とを行う readnext( ) を作成する C 言語に限らず ファイルからデータを読み込む場合 必要になるのは ファイル名と場所 ( どのディレクトリにあるか ) プログラム上でデータを受け取るバッファ ( 変数の型に注意 ) 読み込み方 ( 一気に全部読むのか 少しずつ ( 例えば 1 行ずつ ) 読むのか ) といったことです C 言語でのファイル入出力はファイルポインタを介して行われます ファイルポインタは 今どこまで読み込んだかを指し示しています ファイルとファイルポインタとの対応付けは オープン文によって行い その解放はクローズ文によって行います 以下の関数を使います #include <stdio.h> // 使用時に宣言すべきインクロード文 FILE *fopen(char *path, char *mode); // ファイルのオープン int fclose(file *fp); // ファイルのクローズ int fgetc(file *fp); // ファイルからの1 文字読み込み Int feof(file *fp); // エンド オブ ファイルの検出

C プログラムの基本構造 /************************************ Programming 3H Example 0-1: 整数を読み込んで書き出す Produced by Taro Hosei on 26 May, 2014 ************************************/ #include <stdio.h> int main(int argc, char *argv[]) { int k; } printf( enter k= ); // 入力を促す scanf( %d, &k); //kを入力 printf( k=%d n, k); //kを出力 intk.c として保存 処理を行う関数群それぞれの文は ; セミコロンで終わります 最初にはプログラムに関するコメントを書きます 作成目的 ( 何をするプログラムか ) と作成日 作成者は必須です include 文はここに書きます main 文です コマンドラインから入力を得るため argc と argv[] とを定義しておきます argc にはコマンドライン引数の数が argv[] にはその文字列が格納されており プログラム内で使用できます 使用する変数と型の定義 コメントは入れすぎるぐらいに入れましょう コメント以外では全角文字を使ってはいけません C プログラムの構造は 上にあるように コメント include 文 main 文 変数宣言 関数群から成り 各行はセミコロンで終わります 全体としては main( ){ } のようになっています このほか 自分で関数を作ることも可能です

例題 1 1 ファイルが存在するかどうか ( あるはずのファイルのスペルミスも含めて ) を確認し ないときには ファイル名 : not found を出力し 存在するときには ファイル名 :found を出力する 方針 : コマンドラインからファイル名を入力し fopen() を用いてそのファイルのオープンを試みる もし 存在しなければ 戻り値は NULL となるので 存在が判定できる

ソースコードの作成とコンパイル 動作確認 1work 内に例題用のディレクトリ ex101 を作成して移動 2 ファイル名を exist.c として emacs で開く 3 ソースコードを入力して保存 4 コンパイル 5 起動 Usage の表示 6 存在するファイルを入力 found とでる 7 スペルミスの場合 not found とでる コマンドライン上のファイル名はここに入る こういうのはシステムの出力 1 2 5 4 6 7 3 上を入力してから [control] + x, [control] + s を行うと書き込まれる 8 コマンドとして ~/prsc/bin に登録

printf( ) と fprintf(stderr, ) について linux 上の gcc では 文字等を出力するのに 標準出力 stdout と標準エラー出力 stderr とを持っていて区別して使うことができます 混在させて使うと見た目にはわかりませんが 出力のリダイレクトの利用を考えると 区別して使う方が便利です 特に 画像を表示させる際に 画像 viewer が標準入力 stdin からの入力に対応していると 画像にかかわる出力を printf() で それ以外を fprintf() を用いて区別すると作業効率が上がります なお fprintf(stdout, ) は printf( ) と同じ動作をします $ cat image.jpg xv - & を思い出してください このやり方をパイプといいますが 画像データをそのまま標準出力に出力し それをファイルを経ることなく 直接 xv の標準入力に入力します xv の後ろの は 標準入力から入力する ことを指定するオプションです

例題 1 2 指定したテキストファイルのバイト数を数える 方針 : コマンドラインからファイル名を入力し fopen() を用いてそのファイルをオープンする 存在すれば 1 文字ずつ読みだしてその数を数える

ソースコードの作成とコンパイル 動作確認 1 2 3 5 4 6 1work 内に例題用のディレクトリ ex102 を作成して移動 2 ファイル名を filesize.c として emacs で開く 3 ソースコードを入力して保存し 4 コンパイルする 5 動作確認 462 バイト 6 確認のため $ ls -l を行った結果 607 バイト 同じことですが 上の方が記述が単純 きちんと求まっていることがわかります

例題 1 3 指定したテキストファイルの行数を数える 方針 : コマンドラインからファイル名を入力し fopen() を用いてそのファイルをオープンする 存在すれば 1 文字ずつ読みだして行くが 行の終わりのコードが n であることから その数を数える

ソースコードの作成とコンパイル 動作確認 1 2 読み込んだ文字が n の時だけカウントしている 4 5 3 1work 内に例題用のディレクトリ ex103 を作成して移動 2 ファイル名を filesize.c として emacs で開く 3 ソースコードを入力して保存 4 コンパイル 5 動作確認 24 ライン emacs で確認すると 下の帯に lines.c All L24 と表示されており 正しいことがわかります

例題 1 4 指定したテキストファイルから 指定した個数の文字を読みだす 方針 : コマンドラインからファイル名と読み出す文字数を入力する fopen() を用いてそのファイルをオープンする 存在すれば 1 文字ずつ読みだして指定した個数分をバッファに蓄え main 関数に戻る関数 readn() を作成する readn() の戻り値は正常読み出し時に EXIT_SUCCESS EOF が検出されたら EXIT_FAILURE を返すように設定する * 余裕を持たせて長めにある長さのバッファ内に それよりは短いデータが格納された場合 どこがデータの終端かがわからなくなる C では 最後のデータの後ろに 0x00 を書き込んで明示的にデータの終わりがわかるようにしています 個々の例題のように文字列を扱うときには 必ず文字列データの最後に 0x00 を加えてください

ソースコードの作成とコンパイル 動作確認 3 プロトタイプ宣言 コンパイル 動作確認 n = 50 途中省略 動作確認 n = 5000 最後に 0x00 を書き明示的に文字列の終端とします main 文に続けて書きます buf 内にデータは存在するがファイルの終端まで達した 大きすぎる n を指定すると ファイルの終端まで達してしまい EXIT_FAILURE が戻される 指定された数だけ読み込めれば正常終了

プロトタイプ宣言 C では 作成した関数を呼び出す際に 呼び出す関数よりも呼び出される関数が先に定義されている必要がありました あまりに不便なので main 関数の前に 1 戻り値の型 2 関数名 3 引数リストだけを宣言しておくと順序は問われないように改善されました 前のページの例では main 文の前に int readn(file *fp, char *buf, int n); が書いてありますが これがプロトタイプ宣言です 1 戻り値の型 : int 2 関数名 : readn( ) 3 引数リスト : FILE *fp, char *buf, int n ということになります なお 引数を使用しない関数であれば int func(void); のように 引数リストの位置には void だけ書いておきます 関数の実体はプロトタイプ宣言の後ろであれば どこに書いても構いません

例題 1 5 指定したテキストファイルから 指定した個数の文字を読みだす main 関数を readnmain.c, 関数 readn() を readn.c として 別のファイルとして作成する *gcc にはコンパイルの機能とリンカーの機能とを有するので 別々にコンパイルしてリンクすることを学ぶ * 関数を使う場合に call by reference と call by value との違いを理解する 方針 : コマンドラインからファイル名と読み出す文字数を入力する fopen() を用いてそのファイルをオープンする 存在すれば 1 文字ずつ読みだして指定した個数分をバッファに蓄え main 関数に戻る関数 readn() を作成する readn() の戻り値は正常読み出し時に EXIT_SUCCESS EOF が検出されたら EXIT_FAILURE を返すように設定する

コンパイルとリンク コンパイル : ソースファイル (.c) を参照しながら オブジェクトファイル (.o ) を作成する 内容は ソースコードをマシン後に翻訳したもの ただし このままでは動かない 未定義の関数はプロトタイプ宣言で引数の型や戻り値の型だけ確認し 詳細は後で出てくるだろうと仮定して作業が進む リンク : 実際にプログラムが動くのに必要なチェックを行う 複数の.o ファイルの中から参照すべき関数を見つけたりする操作 これによって 実行可能ファイルが作成される $ gcc source.c -o source -lm とすると コンパイルとリンクが続けて行われる 文法的なエラーはコンパイル時にでるが ( 打ち間違いなどで ) 見つからない関数が合ったりするとリンク時にエラーが出る コンパイルのみ行う場合は次のページの例のように c を付ける $ gcc -c source1.c o source1.o $ gcc -c source2.c o source2.o リンクを行って 実行可能ファイル source_exec を作成するには $ gcc -o source_exec source1.o source2.o -lm とする 最後のはエルエムです

ソースコードの作成とコンパイル 動作確認 1work 内に例題用のディレクトリ ex105 を作成して移動 2 ファイル名を指定して emacs で開く 3 ソースコードを入力して保存 4 それぞれをコンパイル 統合してリンク 5 動作確認 2 4 3-1 5 3-2 sc sc

ソースファイルの書き方について ここで想定しているソースファイルの書き方について 補足します 下図のような構造のプログラムを仮定します すなわち mian は func01 と func02 とをよび さらに func02 は func03 をよぶわけです int main() int func01() double func03() unsigned char *func02() このとき 4 つの関数をそれぞれ別の名前で xxxx_main.c, xxyy_01.c, xyyy_02.c, yyyy_03.c ( 名前は単なる例です ) 作成してあることを想定しています それぞれのファイルの先頭にはそれぞれに必要な include 文を書き そのファイル内で定義していない関数についてはプロトタイプ宣言が必要です これらのファイルを別々にコンパイルし リンクして 1 つにまとめ実行可能ファイルを作ります この操作を簡単に行うスクリプトを practicec00.pdf 内で紹介しています ~/prj3/bin に指定した実行可能ファイルの symbolic link を張るところまでやってくれます 使用に当たっては ~/prj3/bin に PATH を通すのを忘れずに なお お勧めはしませんが ひとつの.c ファイルの中に include 文 すべてのプロトタイプ宣言 main 文 関数 1 関数 2 関数 N をまとめて書いておくことも可能です この場合は $ gcc example.c -o example lm のようにしてコンパイルとリンクを同時に行うことも可能です ただし 大規模なプログラム作成には向きません

C は call by value 変数内の数値そのものを渡す 例 5 で 関数 readn() について見ていきます main 関数からは c = readn(fp, buf, n); のようによんでいます call by value では 数値そのものを関数に渡すだけですので 関数内で処理した結果をどのようにして main 関数に戻したらよいでしょうか 戻り値で返すことも可能ですが 大量のデータを戻すのには不向きです そのような場合 C では その変数が格納されているメモリ上の位置 ( アドレス ) を渡してやります 呼ばれた関数側では 数値として受け取ったメモリ上のアドレスに直接アクセスして計算結果を格納します main 側から見れば 関数から戻ってきた後にその変数を見ると 内容が書き換わっている ということになります このように 数値そのものではなくそれらのアドレスを表すものをポインタとよび そのための変数をポインタ変数とよび 宣言時には * を付けて表します なお 配列はすでにポインタとして扱われています char cc, buf[1024], *pa; と宣言した時 cc 用に 1 バイト buf 用に 1024 バイト分の領域 およびポインタ pa 用の領域が確保されますが buf 用の領域の先頭アドレスは buf に格納されています 変数 cc のアドレスを得るには 演算子 & を用いて pa = &cc; のように ポインタ変数で受けます 逆に ポインタで示される変数に書き込むには 演算子 * を用いて *pa = 0x0a; のようにします この例だと cc = 0x0a になっています

ポインタのつづき 宣言時には * をつけます int *k, c, d ; 変数使用時には 他の変数とは異なり 変数の値ではなくそれが格納されている番地 ( アドレス ) が代入されます 今 変数 c には 5 が入っていたとします 変数 c の番地は &c で求めることができます k = &c; とすることによって k には c の番地が格納されました プログラム中でポインタに * を付けると 今度はそのポインタ変数が指す番地に格納されている数値を読み出すことができます ここの例では d = *k; とすることで変数 d には 5 が格納されます

例題 1 6 ポインタの動作理解 ex106 を作成し その中に作成する 宣言 他の型でも同じです pa に変数 cc のアドレスを得て cc に値を代入 cc と *pa とが同じ値になっていることがわかります *pa に値を代入すると cc の値も変わっていることがわかります 実行結果 配列の場合は名前そのものがポインター ポインタ変数はなかなか便利

課題 1-1 次の仕様に基づいて コマンドラインで指定したテキストファイルから指定した個数の文字か 1 行分の文字列を読み込んで 引数で与えたバッファに格納して戻ってくる関数 readcharline() を作成し readcharline.c として保存して下さい なお 読み込んだ文字列の最後は 0 (0x00) で終わるようにしてください コンパイルはメイン関数と別々に行って リンク時に結合させなさい ソースコードなど 確認できるファイルを読み込ませて 動作確認を行いなさい その際 読み込む文字の個数もいくつか変えて動作させること 形式 int readcharline(file *fp, char *pa, int num) FILE *fp はファイルに対応するファイルポインタです char *pa は 読み込んだ 1 行分のデータを保存するバッファの先頭を指すポインタです int num は 正の場合は読み込むべき文字の個数を 負の場合には 1 行分の文字列を読み込むことを指定する変数です 戻り値は 読み込んだ文字列の個数とします P101 のようなディレクトリを作成し その中で作業してください ヒント : fopen() や fclose() および読み込んだ文字列を格納するバッファ buf[1024] は呼び出し側で定義します 型は char で 1024 という数値は一例です