記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。

Slides:



Advertisements
Similar presentations
プログラミング演習 II 2005 年 1 月 19 日(第 9 回) 理学部数学科・木村巌. 前回までの復習 共用体( union type ) 共用体( union type ) 列挙 (enumerated type ) 列挙 (enumerated type ) 構造体、構造体のポインタ、
Advertisements

オブジェクト指向言語・ オブジェクト指向言語演習 中間試験回答例. Jan. 12, 2005 情報処理技術基礎演習 II 2 オブジェクト指向言語 中間試験解説 1  (1) 円柱の体積(円柱の体積 = 底面の円の面積 x 高さ) を求めるプログラムを作成しなさい。ただし、出力結果は、入 力した底面の円の半径.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
構造体(struct) 配列では、複数のデータをひとまとまりにして操作する ことが出来る。しかし、それぞれのデータは同じ型(例えば
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
問題提起その 1 一文字ずつ文字(数字)を読み込み、それぞれの文字が何回入力されたかを数えて出力するプログラム。
第13回 プログラミングⅡ 第13回
第8回 プログラミングⅡ 第8回
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
情報処理Ⅱ 第13回 2006年1月20日(金).
アルゴリズムとデータ構造 補足資料6-3 「サンプルプログラムcat3.c」
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
ファイル操作と文字列の利用.
情報処理Ⅱ 第13回 2004年01月25日(火).
10: ファイル入出力 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
Cプログラミング演習 第6回 ファイル処理と配列.
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
プログラミング入門2 ファイルの入出力 ポインタ 芝浦工業大学情報工学科 青木 義満
関数の定義.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
プログラミング演習I 2003年6月25日(第10回) 木村巌.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
プログラミング論 ファイル入出力
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第4回 ファイル入出力方法.
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング演習I 2003年7月2日(第11回) 木村巌.
ファイルの読み込み, ファイルからのデータの取り出し, ファイルの書き出し
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
モジュール分割.
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
全体の流れ 画像ファイルを開き,画像データをメモリ上にロード メモリ上にロードした画像データに処理を加える
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
コンピュータープログラミング (C言語)(10) 1.ファイル入出力
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
プログラミング演習I 補講用課題
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
プログラミング 2 静的変数.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。 今までの変数宣言はすべて、変数を自動変数( auto型)として宣言 auto int a; を省略して int a; と宣言 記憶クラス指定子 auto で自動変数を指定(省略可) 自動変数は、それが宣言されている関数が呼び出された時点で生成され、 関数の呼び出しが終了した時点で消滅する。 自動変数はメモリ上のスタックに格納される。

変数の生成と消滅 y y x x j j i i main() { int i,j; func_1(); ... func_2(); } void func_1(void) int x, y; .... void func_2(void) 局所変数 x, y の生成 局所変数 x, y の生成 消滅 消滅 y y x x メモリ空間 func_1 呼出 func_1 終了 func_2 呼出 func_2 終了 j j i i 時間 変数 i, j の寿命 変数 x, y の寿命 変数 x, y の寿命 main 文の開始 局所変数 i, j の生成 main 文の終了 局所変数 i, j の消滅

スタック 必要となる度に新たな領域を確保して、常に最新の領域に格納された値を操作する。不要になった値は最新のものから領域を開放する。そして、1 つ前に確保された領域が最新のものとして利用される仕組みをスタックという。 スタック (stack) : データの積み重ね 関数内 変数 y y x x j j j j j main 文 変数 i i i i i プログラム開始 関数呼出 関数呼出 プログラム終了 呼出終了 呼出終了

静的変数 static int x; 記憶クラス指定子 static を用いて、変数が静的変数であることを指定する 静的変数はメモリの静的領域に格納される。 静的変数は初期化の指定がない場合、ゼロで初期化される。 静的変数の初期化はコンパイル時に一度だけ行われる。 静的変数に対して、自動変数は関数の終了で消滅するため、プログラムの 実行中、値を保持することが出来ない。 プログラムの実行中常に値を保持するには静的変数を用いる。

静的変数の寿命 main() { int i; func_1(); func_2(); } void func_1(void) 自動変数 static int a; int b; .... void func_2(void) static int x; int y; main 文の局所変数 i main 文開始 生成 main 文終了 消滅 自動変数 func_1 の局所変数 b func_2 の局所変数 y func_1 呼び出し func_1 終了 func_2 呼び出し func_2 終了 func_1 の局所変数 a func_2 の局所変数 x 静的変数 main 文開始 生成 main 文終了 消滅

静的変数を用いた例 void count(void) % ./a.out main() 1 { 2 count(); % } static int x=0; printf(“%d\n”, x); x++; % ./a.out 1 2 % 関数 count 中の静的変数 x の値は、関数呼び出しが終わっても消滅しないで保持されている。 従って、呼び出されるごとに x の値は 1 増えるが変数 x は消滅しない。 静的変数の初期化はコンパイル時に一度だけ実行される % ./a.out % x を自動変数として宣言すると、関数呼びだし毎に x は生成され値は 0 に初期化される。実行結果は、

外部変数 関数の外で定義される変数を外部変数(大域変数)と呼ぶ。 外部変数のスコープは広域的(プログラム全体)。全ての関数で参照可能。 int a=10; double x=3.14159; main() { printf(“a = %d\n”, a); sample(); printf(“%f\n”, x); } void sample(void) x += 1.0; 外部変数 a, x の宣言。変数 a, x はどの関数(main 文を含む)からも利用可能。 外部変数はどの関数からも参照可能なの で、関数を独立したブラックボックスと して定義することが困難になる。 変数の隠ぺいができないため、外部変数の乱用は避けるべき。

プリプロセッサ コンパイルに先立ち、ソースプログラムを指示された内容に従って書き直す処理を前処理(プリ・プロセス)という。前処理を行うプログラムをプリ・プロセッサと呼ぶ。 通常、コンパイラが呼び出されると自動的にプリプロセッサが働いてソースプログラムを修正し、修正済みのプログラムがコンパイラに渡される。従ってプリプロセッサの存在をユーザが意識することはない。 ソースファイル プリプロセス コンパイル 標準ライブラリ リンク 実行可能ファイル % cc test.c -E コンパイラオプション -E により、プリプロセス後のファイルを標準出力(コンソール)に出力。コンパイル・リンクは行わない。

前処理指令 #include ファイルの取り込みを指定 #include < ファイル名 > 処理系の標準ヘッダファイルを読み込む #include <stdio.h> #include <math.h> #include "ファイル名" ユーザ定義のヘッダファイルを読み込む。 ヘッダファイルはソースファイルと同じディレクトリに有るものとする。 長いソースプログラムを複数のファイルに分割してコンパイルするときに用いる。共通する変数や関数の宣言をヘッダファイルにまとめて書く。

前処理指令 2 #define 記号定数(マクロ)の定義を指定 #define 記号定数 文字列 プリプロセッサは、ソースファイルの記号定数を文字列で置き換える #define SIZE 10 main() { int i, score[SIZE]; for(i=0; i<SIZE; i++) scanf(“%d”, &score[i]); .... } 配列要素数をマクロ定義しておけば 要素数の変更にも容易に対応可能 マクロ定義しておかないと、要素数に関係するソースの全ての部分を書き換えないといけない。大変。

ファイル処理 これまでは、データの入出力は標準入出力(キーボード及びコンソール)を用いてきた(シェルのリダイレクションを含む)が、入出力はファイル経由でも可能。 外部記憶装置(ハードディスクなど)に格納されたデータの集合をファイルという。ファイルを扱うために FILE という型が stdio.h に定義されている。 テキストファイル(text file)とバイナリファイル(binary file) 内容が文字と改行文字などそのまま表示可能なファイルをテキストファイル、データがバイト列となっているものをバイナリファイルという。ここではテキストファイルのみを取り扱う。 ファイルの入出力を行うには、事前、事後の操作が必要。 1) ファイルのオープン(ファイルを開く) 2) ファイルへの入出力 3) ファイルのクローズ(ファイルを閉じる)

ファイルのオープン ファイル型へのポインタ変数宣言 FILE *fp; ファイルのオープンには、ライブラリ関数 fopen() を用いる。 宣言しただけでは具体的なファイルを指していない。 ファイルのオープンには、ライブラリ関数 fopen() を用いる。 fp = fopen("data", "w"); ファイル名 モード "w" 書き込みモード(ファイルを新規作成) "r" 読み込みモード(ファイルが存在しないとエラー) 上記の例では、新規に data という名前のファイルが作成され、ファイルへのポインタ fp はこのファイルを指す。以後は fp を介してファイル入出力等を行う。ファイル data が既存の場合、内容は消去されて新規ファイル が作成される。

ファイル名の指定 文字列リテラルとしてファイル名を指定し、ファイルをオープンする例 FILE *fp; char file_name[]="data"; fp = fopen(file_name, "w"); 文字型配列として宣言と同時に初期化 FILE *fp; char file_name[100]; scanf("%s", file_name); fp = fopen(file_name, "w"); 文字型配列として宣言 scanf() で文字列として入力 文字列=文字型配列の操作により、ファイル名をプログラム内で変更可能。

ファイルオープン時のエラー処理 ファイルオープンに失敗すると fopen() は特殊な値 NULL を返す。下例のように、オープンに失敗した場合、ライブラリ関数 exit() でプログラムを正常に終了。 if( (fp = fopen("data", "w")) == NULL ){ printf("Can’t open file!\n"); exit(); } 書き込みモードでファイルを開く場合、ディスク容量が一杯、もしくは、読み込みモードで指定したファイルが存在しない等の理由でファイルオープンが失敗する場合がある。エラー処理を行わないと、ファイルへの入出力の時点で Bus error 等のプログラムの異常終了が起こる。 ライブラリ関数 exit() はプログラムの実行を終了する。

ファイルへの入出力 ライブラリ関数 fprintf(), fscanf() を用いた入出力 それぞれ、標準入出力に関する printf(), scanf() に相当する fprintf(fp, "socre is %d\n", i); ファイルポインタ fp が指すファイルへ書式付き出力 fscanf(fp, "%d", &data); ファイルポインタ fp が指すファイルからデータを整数値として読み込み、変数 data に格納。 使い方は printf(), scanf() と同じ。

ファイルのクローズ オープンしたファイルはプログラム終了時にクローズする必要がある ファイルのクローズ fclose(fp); 一般にプログラムが終了する直前でファイルを閉じる

具体例 1 main() { FILE *fp; fp = fopen("data", "w"); fprintf(fp, "Hello!\n"); fclose(fp); } data という名前のファイルを新規作成し、 文字列 “Hello!\n” を書き込む。 開いたファイルはちゃんと閉じること。 実行結果は左の通り。data というファイルが出来ていて、内容は Hello!\n である。 % ./a.out % cat data Hello! %

具体例 2 main() { FILE *fp; int score; fp = fopen("data", "r"); while( fscanf(fp, "%d", &score)!=EOF ){ printf("%d\n", score); } fclose(fp); 既存のファイル data を読み込みモード "r" で開き、ファイルに書かれているデータを整数値として読み込んで表示。 書き込みモード "w" でファイルを開くと、ファイルが新規作成されて中身が消えてしまうので注意! ファイルオープンの際、エラー処理をしていないので、data というファイルが存在しないと実行時エラーで異常終了する。

ファイル入出力続き ファイルから 1 文字ずつ文字を読み込むライブラリ関数 getc(), putc() 標準入出力に関する getchar(), putchar() に相当 int getc(FILE *fp); fp が指すファイルから 1 文字読み込み、文字コード(int)を返す int putc(int c, FILE *fp); fp が指すファイルへ文字コード c に対応する文字を書き込む。書き込み時にエラーが起こると EOF を返す

具体例 3 テキストファイル data_original の内容を別のファイル data_copy にコピーするプログラム main() { FILE *fp_in, *fp_out; int code; fp_in =fopen("data_original", "r"); fp_out=fopen("data_copy", "w"); while( (code=getc(fp_in)) != EOF )} putc(code, fp_out); } fclose(fp_in); fclose(fp_out); コピー元のファイルは読込みモードでオープンすること。 コピー元のファイルから 1 文字ずつ読み込んで、コピー先のファイルへ書きだす。

コマンド引数 端末からプログラム(a.out)へ引き渡す引数をコマンド引数と呼ぶ。 % ls -a % cc sample.c -lm コマンド cc への引数(ファイル名とオプション) コマンド引数は main 関数の関数頭部で定義する main(int argc, char *argv[]) コマンド(a.out)へ引き渡される引数の個数。コマンド名(a.out)自身も引数の 1 つとなるので、この値は常に 1 以上。 与えられた引数(文字列)へのポインタの配列(引数は一般に複数あるから)

コマンド引数 2 main(int argc, char *argv[]) { printf("コマンド引数の数は %d\n", argc); printf("第0引数は %s\n", argv[0]); printf("第1引数は %s\n", argv[1]); printf("第2引数は %s\n", argv[2]); } これを実行すると、、、 % ./a.out hello! 123 コマンド引数の数は 3 第0引数は ./a.out 第1引数は hello! 第2引数は 123 % 上のプログラムは、配列 argv[] の添え字 2 を参照しているため、コマンド引数の数は 3 以上でなければならない。

コマンド引数 3 コマンド引数の全てを表示させるサンプルプログラム main(int argc, char *argv[]) { int i; for(i=0; i<argc; i++) printf("%s\n", argv[i]); } argc はコマンド引数の数 コマンド引数 argv[i] を文字列として表示。i = 0 ~ argc–1

問題 1 指定したテキストファイルをオープンして内容を表示するプログラムを作れ。 テキストファイル anne.txt は演習時に配付する。 http://kako.ics.nara-wu.ac.jp/~kako/teaching/gengo1/anne.txt からdownloadすること。 #include <stdio.h> main() { int code; FILE *fp; fp = fopen("anne.txt", "r"); /* fp が指すファイルから1文字ずつ読み取って表示 */ fclose(fp); }

問題 2 データの個数は80です。 平均と偏差値は左の例とは違うかもしれません。 成績が記入してあるファイルを読み込み、平均点と標準偏差を表示するプログラム。 なお、データファイル名は score_data、成績は 100 点満点で整数として 記入されているとする。データファイルは演習時に配付する。 (http://kako.ics.nara-wu.ac.jp/~kako/teaching/gengo1/score.dataからdownload) データ入力にリダイレクションは使わず、ファイルをオープンして読み込むこと。 偏差の計算に、 <n>を平均値として、                               を使うと、全部のデータを 一旦配列に保存しておかないと、計算ができない。 で偏差を計算すれば、最後に平均値の二乗を引く事で、計算が可能である。 % ./a.out データ読み込み中... 80 人の成績を読み込みました。 平均点計算中... 平均点は 69.04 点です。 標準偏差値は 18.87点です。 % データの個数は80です。 平均と偏差値は左の例とは違うかもしれません。

問題 3 キーボードから文字を 1 文字ずつ読み込み、Ctrl-D で中断する。読み込んだ文字をファイルに書き出すプログラムを作れ。なお書きだすファイルの名前もキーボードから入力するとする。 % ./a.out ファイル名:text_file 文字を入力せよ(Ctrl-Dで終了) Summer vacation is close at hand! Ctrl-D % % cat text_file 書き出したファイルの内容を確認せよ。

問題 4 指定したファイル名のファイルの内容を表示し、文字数と行数を表示するプログラム。エラー処理も行うこと。 % ./a.out ファイル名を入力:sample.c #include <stdio.h> main() { printf("Hello!\n"); } 文字数は 55 文字。 行数は 5 行です。 % ファイル名を入力:sample2.c そのようなファイルはありません。 scanf でファイル名を文字列として入力。このファイルを fopen で開く。その後は 1 文字ずつファイルから文字を読み込んでいけばよい。 指定したファイルが存在しなかった場合の処理も正しく行うこと。

問題 5 ファイル名をコマンド引数として指定し、ファイルの内容を表示するプログラムを作れ。ただし、オプション -U を付けると大文字に,、また –Lを付けると小文字に変換するものとする。(どちらか一方しか指定しないものとする) 2 つめの文字列が ”-U" の時、大文字に変換して表示。2 つの文字列を比較するには strcmp() を用いる。 % ./a.out sample.c #include <stdio.h> main() { printf("Hello!\n"); } % ./a.out sample.c -U #INCLUDE <STDIO.H> MAIN() PRINTF("HELLO!\N"); % ./a.out sample2.c そのようなファイルはありません。 % int strcmp(char *s1, char *s2) 文字列 s1, s2 が等しいとき int 0 を返す。 #include <string.h> char str1[]="123"; char str2[]="hello!"; if( strcmp(str1, str2)==0 ) printf("2つの文字列は同一"); else printf("2つ文字列は異なる");