2 THE UNIVERSITY OF TOKYO

THE UNIVERSITY OF TOKYO
数理情報工学演習第一C
プログラミング演習 (第3回 )
2014/04/21
DEPARTMENT OF MATHEMATICAL INFORMATICS
1
THE UNIVERSITY OF TOKYO
今日の内容:
 #define
 typedef
 struct
 ファイルの読み書き
 課題:行列を表す構造体とファイル読み書き
2
THE UNIVERSITY OF TOKYO
#define
 定数(数値,文字列)に名前をつける
– #define ARRAY_LENGTH 100
– int a[ARRAY_LENGTH];
– for (i=0; i<ARRAY_LENGTH; i++) a[i] = 0;
 プログラム中に直接数値を書くと,値を変更し忘れたりするので,
極力名前を定義してそれを使う
3
THE UNIVERSITY OF TOKYO
typedef
 通常の変数の型に違う名前をつけられる
– typedef int data_t;
– data_t x, y, z;
 ポインタの型なども定義できる
– typedef char *string_t;
– string_t name; // 文字列へのポインタ
4
THE UNIVERSITY OF TOKYO
struct (構造体)1
 複数の変数をまとめたもの
struct person {
char *name; // 名前の文字列
int age;
// 年齢
};
struct person P1;
P1.name = “Kunihiko Sadakane”;
P1.age = 10;
5
THE UNIVERSITY OF TOKYO
struct (構造体)2
 typedef で構造体に名前をつけると便利
typedef struct {
char *name; // 名前の文字列
int age;
// 年齢
} person;
person P1;
P1.name = “Kunihiko Sadakane”;
P1.age = 10;
6
THE UNIVERSITY OF TOKYO
struct (構造体)3
person inc_age(person P)
{
person Q;
 構造体は関数の引数や返り値にできる
Q = P;
 構造体変数間の代入もできる
Q.age++;
return Q;
}
int main()
{
person P1, P2;
P1.name = "Kunihiko Sadakane";
実行結果
P1.age = 10;
P2 = inc_age(P1);
age(P1) = 10
age(P2) = 11
7
printf("age(P1) = %d\n", P1.age);
printf("age(P2) = %d\n", P2.age);
}
THE UNIVERSITY OF TOKYO
struct (構造体)4
 構造体のポインタを使うほうが一般的
int main()
{
#include <stdio.h>
person *P1, *P2;
#include <stdlib.h>
P1 = malloc(sizeof(person));
typedef struct {
P1->name = "Kunihiko Sadakane";
char *name;
P1->age = 10;
int age;
} person;
P2 = malloc(sizeof(person));
void inc_age(person *P)
*P2 = *P1; // 中身のコピー
{
P->age++;
実行結果
inc_age(P1);
}
age(P1) = 11
age(P2) = 10
8
printf("age(P1) = %d\n", P1->age);
printf("age(P2) = %d\n", P2->age);
}
THE UNIVERSITY OF TOKYO
struct (構造体)5
 注意:ポインタの代入では中身はコピーされない
 さらに注意:中身をコピーした場合でも,構造体の要素 name は
ポインタなので,元の文字列を変更するとそれを参照している全ての変数
が変わる
int main()
#include <stdio.h>
{
#include <stdlib.h>
person *P1, *P2;
typedef struct {
P1 = malloc(sizeof(person));
char *name;
P1->name = "Kunihiko Sadakane";
int age;
P1->age = 10;
} person;
実行結果
P2 = P1; // ポインタの代入
void inc_age(person *P)
{
P->age++;
}
9
inc_age(P1);
age(P1) = 11
age(P2) = 11
printf("age(P1) = %d\n", P1->age);
printf("age(P2) = %d\n", P2->age);
}
THE UNIVERSITY OF TOKYO
行列を構造体で表す
 typedef struct {
int n, m; // 行数,列数
double **A; // (行を表す配列)の配列へのポインタ
} matrix;
matrix *malloc_matrix(int n, int m)
{
matrix *a;
main()
int i;
{
a = malloc(sizeof(*a));
matrix *a;
a->n = n; a->m = m;
a = malloc_matrix(10, 10);
a->A = malloc(n * sizeof(double *));
}
for (i=0; i<n; i++) {
a->A[i] = malloc(m * sizeof(double *));
}
return a;
10
}
THE UNIVERSITY OF TOKYO
ファイル操作の手続き:
 ファイル操作
– ファイルからのデータ読み込み
– ファイルへのデータ書き出し
 基本的な手順
– 読みこむ/書き出すファイルを開く (fopen)
– 読み込み/書き出しの操作 (fscanf/fprintf)
– ファイルを閉じる (fclose)
11
THE UNIVERSITY OF TOKYO
ファイルを開く/閉じる: fopen/fclose
 fopen(ファイル名, モード)
– モード:r(読み込み), w(書き込み), a(追記)
FILE *fp; // ファイルポインタの宣言
fp = fopen(“input.txt”, “r”) ; // 読み込みモー
ドでinput.txtを開く
各種ファイル処理
fclose(fp); // 閉じる
12
THE UNIVERSITY OF TOKYO
ファイルへの書き込み、読み込み:
 ファイルポインタ以外はprintf/scanfと同様
– 書き出し:fprintf(ファイルポインタ, …)
• fprintf(fp, “%d \n”, i)
– 読み込み:fscanf(ファイルポインタ, …)
• 整数は %d, 実数は %lf
int x; double y;
fscanf(fp, “%d %lf”, &x, &y);
• ファイルの最後に到達した場合 EOF を返す
if ( fscanf(。。。) == EOF ){….}
13
THE UNIVERSITY OF TOKYO
コマンドライン引数の利用
 ./a.out input.txt 10 0.1 と引数をつけて実行したとき
 argc = 4;
int main(int argc, char *argv[])
 argv[0] = “./a.out”; プログラム名
{
FILE *f;
 argv[1] = “input.txt”;
int n;
 argv[2] = “10”;
double x;
 argv[3] = “0.1”;
if (argc < 4) exit(1); // 引数が足りない
f = fopen(argv[1], “r”);
n = atoi(argv[2]); // 文字列を整数に
x = atof(argv[3]); // 文字列を実数に
}
14
THE UNIVERSITY OF TOKYO
課題
 n 行 m 列の行列をファイルから読み込み,新たに確保した行列に代入
– matrix *input_matrix(char *filename);
 行列を入力と同じ形式でファイルに出力
– void output_matrix(char *filename, matrix *a);
 2つの行列 A, B の積を計算し,新たに確保した行列 C に代入
– matrix *product(matrix *A, matrix *B);
– 行列のサイズが合わないときは C は確保せずに NULL を返す
 行列のメモリを開放する
– void free_matrix(matrix *A);
15
THE UNIVERSITY OF TOKYO
行列のファイル形式
2 3
1.0 2.0 3.0
4.0 5.0 6.0
16
行数 列数
1行目
2行目
THE UNIVERSITY OF TOKYO
課題の提出:
 本日(4/21)の18時までに提出
 提出ファイルをメールに添付し以下に送付
– 宛先:[email protected]
17
THE UNIVERSITY OF TOKYO