• 全要素分のメモリを確保して、別途、列の先頭を指し示すポインタを持つ
※赤→は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