• 検索結果がありません。

大きな領域を確保して使う

ドキュメント内 Microsoft PowerPoint - lecture201509c_1.pptx (ページ 36-49)

• 全要素分のメモリを確保して、別途、列の先頭を指し示すポインタを持つ

※赤→はmalloc、

青→は参照を意味する

2015/9/7-8

36

• row行col列の行列を動的に作成する例

2015/9/7-8

37

int **mat;

mat = (int**)malloc(sizeof(int*)*row);

for(i=0; i<row; i++){

mat[i] = (int*)malloc(sizeof(int)*col);

}

// 行列に対する計算はここで行う for(i=0; i<row; i++){

free(mat[i]);

}

free(mat);

int **mat;

mat = (int**)malloc(sizeof(int*)*row);

mat[0] = (int*)malloc(sizeof(int)*row*col);

for(i=1; i<row; i++){

mat[i] = mat[i-1]+sizeof(int)*col;

}

// 行列に対する計算はここで行う free(mat[0]);

free(mat);

• 行数分の列ポインタを作成し、各 行のための領域を個別に確保

• 行をまたいだメモリ(アドレス)

が連続にならない(性能が下がる 原因となる)可能性が0ではない

• 行数分の列ポインタを作成するのは一緒 だが、全要素分のメモリを一度に確保し、

各行の先頭位置をあわせる

• mallocが減った分、freeも減る

• 配列を受け取る関数の作り方

• 引数に[]や*を使えば良い

• sizeof関数で配列長を取得 できないためlenで長さを 渡すという想定

• もちろん、関数内で値を 更新すれば呼び出し元の 値も変化する

• 実は int vector[N]に対して

&vector[0]とvectorは 等価である

void funcA(int len, int v[]){

int i;

for(i=0; i<len; i++){

printf(“ %d”, v[i]);

}

printf(“¥n”);

}

void funcB(int len, int *v){

int i;

for(i=0; i<len; i++){

printf(“ %d”, v[i]);

}

printf(“¥n”);

}

2015/9/7-8

38

• mallocして返すためにはポインタを一段階深 くせねばならない(と覚えておこう)

– 二次元配列の場合もやはりもう一段階深くなる

void my_alloc(int N, int **v){

*v = (int*)malloc(sizeof(int)*N);

}

void my_free(int **v){

free(*v);

}

int *vector = NULL;

my_alloc(10, &vector);

// vectorを用いた操作

for(i=0; i<10; i++)vector[i] = i;

for(i=0; i<10; i++)printf(" %d", vector[i]); printf("¥n");

my_free(&vector);

2015/9/7-8

39

• printfとは:指定されたフォーマット(書式)に従って文字列 を出力する関数

– printf(“フォーマット指定文字列”, 変数, …, 変数);

– printf(“今日は%d日です¥n”, day);

• フォーマット指定文字列の使い方と例

– %<フラグ><最小フィールド幅><精度><長さ修飾子><変換指定文字>

• フラグ:左詰め(-)、正符号付け(+)、ゼロで埋める(0) など

• 最小フィールド幅:数値出力幅

• 精度:小数点以下の桁数

• 長さ修飾子:(省略)

• 変換指定文字:(次ページ)

• “%2d” 整数2文字分以上の幅で出力

• “%-2d” 〃、左詰めされる

• “%02d” 〃、1桁の場合は0を付加

• “%+d” 正の値には+が付く

• “%2.1f” 整数部分2文字 + 小数1桁を表示

• “%%” %そのものを表示

2015/9/7-8

40

• 変換指定文字は表示したい変数の型と合わせる必要 がある

– 合わない場合は適当に変換される(予期せぬ出力になるこ ともあるので注意)

指定文字 意味 対象変数のデータ型

%c 1文字として出力する 文字型

%d 10進数で出力する

整数型

%x 16進数で出力する

%o 8進数で出力する

%f [-]dddd.ddddddの形式で出力する

浮動小数点型

%e 指数形式で出力する

%g %fと%eから自動選択される

%s 文字列として出力する 文字列

2015/9/7-8

41

• エスケープシーケンス

– 特殊な意味を持つ文字列、いずれも円記号(バック スラッシュ)で始まる

エスケープシーケンス 意味

¥n 改行

¥a 警告音(音が出る)

¥t タブ

¥b バックスペース

¥¥ ¥

¥’ ‘

¥” “

¥0 文字列の終端

2015/9/7-8

42

• printfの亜種について

– printfは書式に従い画面(標準出力)に結果を表示するもの – sprintfを使うと結果を文字列に格納できる

• 使い方

sprint(格納先char配列, “フォーマット指定文字列”, 変数, …, 変数);

• 例 char str[0xff];

int i=1, j=2;

sprint(str, “i = %d, j = %d¥n”, i, j);

printf(str);

実行結果:i = 1, j = 2

• 0xffは16進表記で255のこと、格納するのに十分な 長さがあれば良い

• snprintf関数を使うと長さの制限ができて安全

• 実はprintfにはchar配列をそのまま渡しても良い

2015/9/7-8

43

• sscanf関数:printfと同様のフォーマット文字列を用いて、逆に文字列か ら変数への格納を行うことができる

– sscanf(元となる文字列, “フォーマット指定文字列”, 代入先の位置, …);

– sscanf(buf, “今日は%d日です”, &day);

– char dofweek[3]; scanf(buf, “今日の曜日は%3sです”, dofweek);

• フォーマット指定文字列の例

– %<フィールド幅><変換指定文字>

– フィールド幅は変換する文字数か文字列の短い方 – sscanf(“1234”, “%2d”, &a); なら a=12になる

– sscanf(“1234”, “%8d”, &a); なら a=1234になる

– 文字列を受けるときは、代入する変数のサイズ-1を超えないよう必ず指定する こと(終端文字¥0が最後の 1つを埋めるため )

– floatは%fだがdoubleは%lfとなることに注意(printfでは両方%fで良い)

格納先のアドレス(ポインタ)が必要。大雑把には

• 変数に格納する場合は&をつける

• 配列に格納する場合は&をつけない

2015/9/7-8

44

• sscanf関数ではなくscanf関数を使うと、変数ではなくキー ボード入力(標準入力)から入力を受け取ることができる

– scanf(“フォーマット指定文字列”, 代入先, …);

– scanf(“%10s”, str); 文字列(10文字分)の取得 – scanf(“%d”, &value); 整数値の取得

• 変な入力(フォーマットに合わない文字列や長い文字列な ど)をされてしまった際の処理が難しいなどの問題がある ため、積極的に使う必要は無い

– 実行時引数やファイルの入出力で十分である

2015/9/7-8

45

• 基本手順:開いて、読み書きして、閉じる

• 開く:fopen(ファイル名, モード)

– モード

• r:読み専用

• w:書き専用(上書き)

• a:追記

• r+:読み書き

• w+:書き読み(上書き)

• a+:読み追記

– 上書きの場合、開いた瞬間に ファイルの内容が空っぽになる

– w, a, w+, a+ ではファイルが存在し ない場合には自動的に作成される – 失敗するとNULLが返る

• 閉じる:fclose(ファイルポインタ)

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char**argv){

FILE *fp;//ファイルポインタ

fp = fopen(“filename”, “r”);

if(fp == NULL){

perror(“fopen:”);

exit(EXIT_FAILURE);

}

/* ここに読み書き処理 */

fclose(fp);

return EXIT_SUCCESS;

}

2015/9/7-8

46

• perrorはエラーメッセージの出力

• exitは(関数終了ではなく)

プログラム終了処理

• fgets:テキストファイルを行単位で読む

– 第一引数:読み込んだ内容を格納するchar配列 – 第二引数:読み込み先のサイズ

• サイズ-1か改行があるまで読み込む。読めなかった分は次回読む

• -1は¥0を自動付加するため。

• 改行も読むので実質行のサイズより2つは大きくとる

– 第三引数:fopenから得られたファイルポインタ

– ファイルを全部読み終わるかエラーするとNULLが返る

• fscanf:scanf/sscanfと同様だが入力元がファイルポインタ

– 返り値は読み込み個数、終端orエラー時にはEOFが返る

• 頻出事例:fscanfでファイルから要素毎に変数へ代入、また はfgetsで一行読んでsscanfにより変数へ代入

char s[16];

while(fgets(s, 16, fp) != NULL){ sscanf(s,“format”, &value);}

2015/9/7-8

47

• fprintf:テキストファイルをフォーマット指定文 字列に従って書き込む

– 第一引数:fopenから得られたファイルポインタ – 第二引数以降:printfと同じ

– フォーマット指定文字列不要(変数値なし、テキスト のみ)ならfputsでも十分

– その他の入出力関数の例:fread, fwriteなど

fprintf(fp, “format”, value, …);

fputs(文字列, fp);

2015/9/7-8

48

ドキュメント内 Microsoft PowerPoint - lecture201509c_1.pptx (ページ 36-49)

関連したドキュメント