memo

Similar documents
memo

memo

memo

02: 変数と標準入出力

02: 変数と標準入出力

PowerPoint プレゼンテーション

プログラミングI第10回

Microsoft PowerPoint - lec10.ppt

02: 変数と標準入出力

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

cp-7. 配列

memo

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

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

PowerPoint プレゼンテーション

memo

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

Microsoft PowerPoint pptx

Microsoft Word - 3new.doc

プログラミング実習I

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

02: 変数と標準入出力

gengo1-11

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

memo

02: 変数と標準入出力

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

Taro-ポインタ変数Ⅰ(公開版).j

02: 変数と標準入出力

Microsoft PowerPoint - 11.pptx

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

Prog1_15th

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

PowerPoint プレゼンテーション

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

情報処理Ⅰ演習

関数の中で宣言された変数の有効範囲はその関数の中だけです さっきの rectangle _s で宣言されている変数 s は他の関数では使用できません ( 別の関数で同じ名前の変数を宣言することはできますが 全く別の変数として扱われます このように ある関数の中で宣言されている変数のことをその関数の

問 2 ( 型変換 ) 次のプログラムを実行しても正しい結果が得られない 何が間違いかを指摘し 正しく修正せよ ただし int サイズが 2 バイト long サイズが 4 バイトの処理系での演算を仮定する #include <stdio.h> int main( void ) { int a =

Microsoft PowerPoint - 09.pptx

kiso2-09.key

PowerPoint Presentation

Prog1_10th

プログラミング基礎

PowerPoint プレゼンテーション

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

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

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

Microsoft PowerPoint - prog06.ppt

program7app.ppt

gengo1-8

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

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

プログラミング基礎

Microsoft Word - no202.docx

Microsoft PowerPoint - kougi9.ppt

02: 変数と標準入出力

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

演習課題No12

C言語講座

第2回

情報処理演習 B8クラス

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

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

Microsoft PowerPoint ppt

Microsoft PowerPoint - prog07.ppt

memo

Microsoft Word - no11.docx

02: 変数と標準入出力

(2) 構造体変数の宣言 文法は次のとおり. struct 構造体タグ名構造体変数名 ; (1) と (2) は同時に行える. struct 構造体タグ名 { データ型変数 1; データ型変数 2;... 構造体変数名 ; 例 : struct STUDENT{ stdata; int id; do

PowerPoint Presentation

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

PowerPoint Presentation

演算増幅器

02: 変数と標準入出力

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

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

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

02: 変数と標準入出力

Microsoft PowerPoint pptx

gengo1-12

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

プログラミング実習I

Microsoft PowerPoint - prog08.ppt

1. 入力した正の整数を降順に並べ換えて出力するプログラムを作成せよ プログラムは個別にコンパイルし make コマンドで実行すること 入力データは 50 以下とし 以下の数が混在しているとする 16 進数 : 先頭 1 文字が x または X( エックスの小文字か大文字 ) 8 進数 : 先頭 1

ファイル入出力

Microsoft Word - no12.doc

Taro-リストⅢ(公開版).jtd

CプログラミングI

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

Microsoft PowerPoint - 5Chap15.ppt

PowerPoint Presentation

講習No.10

Taro-再帰関数Ⅲ(公開版).jtd

Taro-リストⅠ(公開版).jtd

Taro-スタック(公開版).jtd

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

Microsoft PowerPoint - C++_第1回.pptx

Transcription:

計数工学プログラミング演習 ( 第 3 回 ) 2016/04/26 DEPARTMENT OF MATHEMATICAL INFORMATICS 1

内容 ポインタ malloc 構造体 2

ポインタ あるメモリ領域 ( アドレス ) を代入できる変数 型は一致している必要がある 定義時には値は不定 ( 何も指していない ) 実際にはどこかのメモリを指しているので, #include<stdio.h> そこに書き込むと実行時にエラー int main() double B[3] = 1.0, 2.0, 3.0; double *p; // 実数型のポインタ p = B; // p に B のアドレスを代入 printf( p[1] = %lf n, p[1]); p[1] = 4.0; // 実際には B[1] に代入される printf( B[1] = %lf n, B[1]); return 0; 3

メモリ確保 ポインタは宣言しただけではメモリは確保されず, 初期値は不定 不定なアドレスを読み書きすると通常はsegmentation faultで終了 たまたま動く場合も, 他の変数の値を破壊することがある malloc 関数で必要なサイズ ( 以上 ) の領域を確保する必要がある void main(void) yをポインタとして宣言 int *y; メモリのどこに書かれる *y = 1; か分からない printf("main: y = %d n", *y); 間違い void main(void) int *y; y = malloc(sizeof(int)); *y = 1; free(y); 正解 整数 1 つ分の領域を確保 4

エラーチェック malloc に必要なメモリが無い場合はエラー 返り値が NULL かどうかチェックする y = malloc(sizeof(int)); if (y == NULL) printf( Not enough memory. n ); exit(1); // プログラム終了 *y = 1; 5

関数呼び出し #include <stdio.h> #include <stdlib.h> void sub_value(int x) x = x + 1; printf("sub_value: x = %d n", x); void main(void) int x; x = 1; printf("main: x = %d n", x); sub_value(x); printf("main: x = %d n", x); 実行結果 main: x = 1 sub_value: x = 2 main: x = 1 6

引数がポインタの場合 x は整数変数へのポインタ void sub_reference(int *x) *x = *x + 1; ポインタの中身を参照 printf("sub_reference: x = %d n", *x); void main(void) int y; y = 1; printf("main: y = %d n", y); yのアドレス sub_reference(&y); printf("main: y = %d n", y); 実行結果 main: y = 1 sub_reference: x = 2 main: y = 2 7

引数が配列の場合 配列は参照渡しになる void sub_reference(int x[]) x[0] = x[0] + 1; printf("sub_reference: x = %d n", x[0]); void main(void) int y[1]; y[0] = 1; printf("main: y = %d n", y[0]); sub_reference(y); printf("main: y = %d n", y[0]); 実は int *x と書いても同じ 実行結果 main: y = 1 sub_reference: x = 2 main: y = 2 8

長さ可変の配列 ポインタ int A[n]; などは ( 基本的には ) できないので, 動的に確保する #include<stdio.h> 実数 1 個が何バイトかを返す. 通常は8バイト. int main() double *A; int i, n; scanf( %d, &n); A = malloc(n * sizeof(double)); // 実数 n 個分の領域を確保してそのアドレスを A に代入 for (i=0; i<n; i++) A[i] = (double)i; free(a); // 使わなくなった領域を開放する return 0; 不要になった領域は必ず free を実行して回収する. 回収しないと, プログラムが使えるメモリがだんだん減っていく ( メモリリーク ) free したあとの領域をアクセスしてはいけない 9

ポインタの演算 整数へのポインタを 1 増やすと, アドレスが整数 1 個分増える 配列の要素は連続したアドレスに格納されるので, ポインタを 1 ずつ増やすと配列の要素に順番にアクセスできる 配列の長さを超えてもポインタは増やせるのでバグに注意 コンパイルはできるが実行するとエラー int A[10]; for (i=0; i<10; i++) A[i] = 0; int *p, A[10]; p = A; for (i=0; i<10; i++) *p = 0; p += 1; 10 *p++ = 0; とも書ける

変数を格納するメモリ領域 /* test4.c */ #include<stdio.h> #include<stdlib.h> int a[10]; // グローバル変数 ( どの関数からもアクセス可 ) int main() int b[10]; // ローカル変数 ( この関数内からのみアクセス可 ) int *c; // 動的に確保する領域へのポインタ int i; printf("address of a = %p, size of a[i] = %d bytes n", a, (int)sizeof(a[0])); for (i=0; i<10; i++) printf("address of a[%d] = %p n", i, &a[i]); printf("address of b = %p, size of b[i] = %d bytes n", b, (int)sizeof(b[0])); for (i=0; i<10; i++) printf("address of b[%d] = %p n", i, &b[i]); c = (int *)malloc(10*sizeof(*c)); // ヒープにメモリを確保 printf("address of c = %p, size of c[i] = %d bytes n", c, (int)sizeof(c[0])); for (i=0; i<10; i++) printf("address of c[%d] = %p n", i, &c[i]); printf("address of &a = %p, sizeof(&a) = %d bytes n", &a, (int)sizeof(&a)); printf("address of &b = %p, sizeof(&b) = %d bytes n", &b, (int)sizeof(&b)); printf("address of &c = %p, sizeof(&c) = %d bytes n", &c, (int)sizeof(&c)); free(c); return 0; 11

実行例 %./a.out Address of a = 0x601060, size of a[i] = 4 bytes Address of a[0] = 0x601060 Address of a[1] = 0x601064 Address of b = 0x7fff0347a1a0, size of b[i] = 4 bytes Address of b[0] = 0x7fff0347a1a0 Address of b[1] = 0x7fff0347a1a4 Address of c = 0x143d010, size of c[i] = 4 bytes Address of c[0] = 0x143d010 Address of c[1] = 0x143d014 Address of &a = 0x601060, sizeof(&a) = 8 bytes Address of &b = 0x7fff0347a1a0, sizeof(&b) = 8 bytes Address of &c = 0x7fff0347a198, sizeof(&c) = 8 bytes 実行中に確保される領域 ( サイズ不変 ) 0x7fff0347a1a0 0x7fff0347a198 実行中に確保される領域 ( サイズ可変 ) 0x143d010 実行前に確保される領域 ( サイズ不変 ) 0x601060 b[1] b[0] &c c[1] c[0] a[1] a[0] 12

サイズ可変の 2 次元配列の実現法 n 行 m 列の配列を作る場合 各行は, 長さ m の (1 次元 ) 配列 malloc (m * sizeof(double)) で確保 2 次元配列は, 行ベクトルの配列 M[] として実現する M[i] は i 行目に対応する配列を指すポインタ 配列へのポインタの型は double * だったので,M[i] の要素の型は double * M の長さ n は実行時に決まるので, ポインタとして定義して実行時に malloc で領域を確保する つまり M の型は double ** となる (double へのポインタ ) へのポインタ 13

ポインタのポインタ #include <stdio.h> #include <stdlib.h> double **create_matrix(int n, int m) double **R; // R は (double へのポインタ ) へのポインタ int i, j; R = malloc(n*sizeof(double *)); // R は n 個のポインタを格納できる配列 for (i=0; i<n; i++) R[i] = malloc(m*sizeof(double)); // R[i] は (i+1) 行目へのポインタを格納 for (i=0; i<n; i++) for (j=0; j<m; j++) R[i][j] = 0.0; return R; R[2] R[1] R[0] R &R R[2][1] R[2][0] R[1][1] R[1][0] R[0][1] R[0][0] R[2] R[1] R[0] R 14

struct ( 構造体 )1 複数の変数をまとめたもの struct matrix int n, m; // 行数, 列数 double **A; // 行列の中身 ; 15

struct ( 構造体 )2 typedef で構造体に名前をつけると便利 typedef struct int n, m; // 行数, 列数 double **A; // 行列の中身 matrix; matrix *X, *Y; // 行列の構造体へのポインタの宣言 X = malloc(sizeof(matrix)); // 構造体を格納するメモリを確保 X-> n = 3; X->m = 2; // 行数, 列数を定義 16

struct ( 構造体 )3 注意 : ポインタの代入では中身は複製されない int main() matrix *X, *Y; X = malloc(sizeof(matrix)); X->n = 3; Y = X; // ポインタの代入 Y->n = 4; 実行結果 X->n = 4 Y->n = 4 printf( X->n = %d n", X->n); printf( Y->n = %d n", Y->n); int main() matrix *X, *Y; X = malloc(sizeof(matrix)); X->n = 3; Y = malloc(sizeof(matrix)); // 新しい領域の確保 Y->n = 4; printf( X->n = %d n", X->n); printf( Y->n = %d n", Y->n); 実行結果 X->n = 3 Y->n = 4 17

struct ( 構造体 )4 関数の返り値を構造体へのポインタにする matrix *create_matrix(int n, int m) // 新しい零行列を作る関数 int i, j; matrix *X; X = malloc(sizeof(matrix)); // 構造体を格納するメモリを確保 X-> n = n; X->m = m; // 行数, 列数を構造体に代入 X->A = malloc(n*sizeof(double *)); // 行ベクトルの配列のメモリを確保して構造体に代入 // ここで列ベクトルのメモリを確保 for (i=0; i<n; i++) for (j=0; j<m; j++) X->A[i][j] = 0.0; // 値を初期化 return X; int main() matrix *A; A = create_matrix(3, 2); 18

第 3 回課題 : 2 つの行列の積を計算するプログラム 入力行列は標準入力から与えられる 1 行目は行列の行数と列数 1 つ目の行列のデータの直後に 2 つ目の行列のデータが来る 標準入力から続けて読めばいい 結果は標準出力に 入力と同じ形式 積を計算できない場合は 0 行 0 列の行列を出力する 出力は 0 0 の 1 行だけ 行列の形式 2 3 // 行数, 列数 1.0 2.0 3.0 // 1 行目 4.0 5.0 6.0 // 2 行目 main 関数の最後は return 0; をつけておく 提出するソースコードの中に, 学生証番号, 氏名, メールアドレスをコメントとして書いておく 締切 : 2016 年 4 月 26 日 ( 火 ) 17:35 ( 演習終了時 ) http://133.11.136.29/domjudge/ 19

ヒント : 以下の関数を順番に作っていけばいい matrix *create_matrix(int n, int m) n 行 m 列の零行列のメモリを確保する matrix *read_matrix() 標準入力から行列のデータを読み, 新しく行列を作る 行列のメモリはこの関数内で確保する void print_matrix(matrix *A) 行列を指定された形式で標準出力に書く matrix *product(matrix *A, matrix *B) 行列積を求め, 新しい行列を作る void free_matrix(matrix *X) 行列のメモリを開放する ( 作らなくても動くが ) 20