基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。

Slides:



Advertisements
Similar presentations
C 言語講座第 5 回 構造体. 構造体とは ... 異なる型の値をまとめて新しい型とする 機能がある . つまり , 複数の変数を 1 つのまとまりにできる . 配列と違って同じ型でデータをまとめるのではな く違った型のデータをまとめられる .
Advertisements

アルゴリズムとデータ構造 第2回 線形リスト(復習).
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
基礎プログラミングおよび演習 第9回
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
基礎プログラミングおよび演習 第8回.
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
C言語講座 第4回 ポインタ.
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
第8回 プログラミングⅡ 第8回
構造体.
演習問題の答え #include #include #define NUM 5 typedef struct { // 構造体の定義 float shincho; // 身長 float taiju; // 体重 } shintai; void hyouji(shintai.
第10回 プログラミングⅡ 第10回
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
C言語講座 第3回 ポインタ、配列.
プログラミング論 関数ポインタ と 応用(qsort)
プログラミング2 関数
Cプログラミング演習 第7回 メモリ内でのデータの配置.
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング演習I 2003年5月7日(第4回) 木村巌.
第10章 これはかなり大変な事項!! ~ポインタ~
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
第13章 文字の取り扱い方 13.1 文字と文字型関数 13.2 文字列 13.3 文字型配列への文字列の代入
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
第11回 プログラミングⅡ 第11回
09: ポインタ・文字列 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
情報処理Ⅱ 第2回:2003年10月14日(火).
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
プログラミング論 ポインタ
09: ポインタ・文字列 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
ネットワーク・プログラミング Cプログラミングの基礎.
標準入出力、変数、演算子、エスケープシーケンス
プログラミング 4 文字列.
2005年度 データ構造とアルゴリズム 第2回 「C言語の復習:配列」
情報処理Ⅱ 第2回 2004年10月12日(火).
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
printf・scanf・変数・四則演算
C言語講座第5回 2017 構造体.
プログラミング演習II 2003年10月29日(第2,3回) 木村巌.
第1章 文字の表示と計算 printfと演算子をやります 第1章 文字の表示と計算.
第1章 文字の表示と計算 printfと演算子をやります.
プログラミング 3 ポインタ(1).
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
Presentation transcript:

基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。 期末テストは、この部屋で、Webや資料を見たり、 プログラム組んだりしながら回答していただきます。

ポインタとアドレス 112 2 int* p int a &変数名: 変数のアドレスを返す ポインタ:アドレスを入れるための変数 &変数名: 変数のアドレスを返す ポインタ:アドレスを入れるための変数 * ポインタ名:ポインタのアドレスにある変数 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 1 int a; int* p; a = 2; p = &a; printf(”p=%d\n”, p); printf(”*p=%d\n”, *p); int* p 112 int a 2 p=112 *p=2 実際のアドレスの値は、プログラムを 作ってみないと何になるかわかりません。

ポインタと変数 int* p; int a; ポインタ名 int* p; a = 2; int型の変数を指す型 p = &a; printf(”p=%d\n”, p); printf(”*p=%d\n”, *p); ポインタ名 int型の変数を指す型 p = &a; 変数のアドレスを返す演算子 int型の変数を指すポインタ * p int型の変数を指すポインタ ポインタが指す変数を取り出す演算子

ポインタが指す変数への代入 p a 104 112 112 p a 104 112 112 10 p a 104 112 int a; int* p; p = &a; *p = 10; 104 112 メモリ 112 p a 104 112 メモリ 112 10 p a 104 112 メモリ

ポインタと型 108 112 float* pf int* pi float f int a int a; float f; int* pi=&a; float* pf=&f; *pi = 10 *pf = 2.4; *pi = *pf; pf = &a; pi = pf; 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 float* pf 1 108 pi=112 : aを指す pf=108 : fを指す aに10を代入 fに2.4を代入 a = fで、 aは2になる。 エラー: pfは、float型変数       しか指せない。 エラー: piとpf は型が違う int* pi 112 float f int a ポインタは、アドレスを入れる変数だが、 そのアドレスにある(はずの)変数の型が同じでないと代入できない。

課題20 変数のアドレスを見てみる について mainの変数はスタック領域 というところからとります。 課題20 変数のアドレスを見てみる について mainの変数はスタック領域 というところからとります。 たいていの処理系で、大きなアドレスから -向きに変数を取っていきます。 グローバル変数は、静的領域 というところからとります たいていの処理系で小さなアドレスから +向きに変数を取っていきます。 0x00000000 0x00000001 0x00012020 0x00012021 0x00012022 0xBFFFF994 0xBFFFF995 0xBFFFF996 0xBFFFF997 0xBFFFF998 0xBFFFFFFE 0xBFFFFFFF 0xC0000000 1 1 1 1 char gc short gs char gc; short gs; int main(){ char c; short s; } short s char c

引数にポインタを使う pはdを指す。 p ここで、*p = dを 書き換えている d pd 呼び出し元のdが 書き換わる ポインタを渡すと、main()の変数を square()で書き換えられる。 →return を使わずに、関数から値を返せる。 pはdを指す。 p=pd; void square(double* p){ *p = *p * *p ; } p ここで、*p = dを 書き換えている int main(){ double d=2.0; double* pd = &d square(pd) ; printf(”%f\n”, d); } d pd 呼び出し元のdが 書き換わる 4

機能と構造 洗濯ばさみ (clothes-pin) 望遠鏡 (telescope) →名前は機能を表す。 関数の名前 機能:洗濯物を挟んで吊るすための物 構造:2つの棒がバネでつながっている。 望遠鏡 (telescope) 機能:遠くのものを見る 構造:筒に凸レンズと凹レンズが はまっている。  →名前は機能を表す。

良い名前とは? 関数の名前も、機能を表すのが良い。 関数の名前 関数の機能:ランダムな質点を返す struct Mass randMass(){ struct Mass m; m.px = rand() % 60; m.py = rand() % 20; m.vx = 20; m.vy = 20; return m; } 関数の構造(動作): 構造体mを作って、 m.px に rand()が返した 値を60で割った値を代入し …

良いプログラム→よい関数 関数の名前 よい関数とは、どんな関数か 機能がわかりやすい → 名前は重要 わかりやすい名前がつけられるような機能に なるように、関数を設計する。 → mainの中から、名前がつけられそうな部分   を切り出して、関数にする。 名前をつけるときは、英単語を調べましょう。 構造がわかりやすい → あまり長すぎるのは良くない。    あまり短いと関数にする意味が無い。 数行~画面3枚分(90行くらい)が良い。

構造体のメンバーとポインタ ポインタは、構造体のメンバーも指せます。 m.px pm pd m. py m m. vx m. vy struct Mass { double px; double py; double vx; double vy; }; int main(){ struct Mass m; struct Mass* pm; pm = &m; double* pd; pd = &m.vx; } m.px pm pd m. py m m. vx m. vy

ポインタをずらす pc pc+1 pc+2 ps ps+1 ps+2 ポインタと配列 ポインタに整数を足すと、足した分だけポインタがずれる。 配列は、メモリ上に詰まって並んでいるので、 ひとつずらすと次の要素のアドレスになる。 1 0x00000000 0x00000002 0x00000003 0x00000004 0x00000005 0x00000006 0x00000007 0x00000008 0x00000009 0x0000000A 0x0000000B 0x0000000C 0x0000000D cs[2] ’c’ cs[1] ’b’ cs[0] ’a’ ss[0] 0 ss[1] 1 pc pc+1 pc+2 ps ps+1 ps+2 ss[2] 2 char cs[3]; short ss[3]; int main(){ char* pc = &cs[0]; *pc = ’a’; *(pc+1) = ’b’; *(pc+2) = ’c’; short* ps = &ss[0]; *ps = 0; *(ps+1) = 1; *(ps+2) = 2; } char* なポインタは1byteずつ short*なポインタは2byteずつずれる (int*, float* は4byte, double* は8byte)

関数で配列を渡す 関数に配列を渡すことはできないが、 配列のアドレスを渡すことはできる。 ポインタと配列 // 文字列のコピー void strcpy(char* pdest, char* psrc){ int i; for(i=0;*(psrc+i); ++i){ *(pdest+i) = *(psrc+i); } *(pdest+i) = 0; int main(){ char src[7]=”string”; char dest[7]; char* psrc = &src[0]; char* pdest = &dest[0]; strcpy(pdest, psrc); printf(src); printf(”\n”); printf(dest); printf(”\n”); &src[0]と書くのが面倒なので、 src を &src[0] と同じ値と決めました。 なので、 char src[7]; char* p = src; // p = &src[0];と同じ とかけます。 ということは、 strcpy(&dest[0], &src[0]); の代わりに、 strcpy(dest, src); と書けます。 けれども、 配列が引数として渡されるのではないです。 配列の先頭のアドレスがポインタの引数に 渡されるだけです。

ポインタを配列っぽく使う 見た目と実態の違いに気をつけてください。 一見配列に見えますが、違うものです。 ポインタと配列 // 文字列のコピー void strcpy(char* pdest, char* psrc){ int i; for(i=0; psrc[i]; ++I){ pdesc[i] = psrc[i]; } pdesc[i] = 0; int main(){ char src[7]=”string”; char dest[7]; strcpy(dest, src); printf(src); printf(”\n”); printf(dest); printf(”\n”); 一見、src, descは配列に見えますが、 配列ではなく、ポインタです。 src[i]は *(src+i)と同じです。 *(src+i)と書くのが面倒なので、 src[i]と書いても良いことにしました。

文字列は文字の配列 ポインタと配列 msg[0] : ’s’ msg[1] : ’t’ msg[2] : ’r’ msg[3] : ’i’ msg[4] : ’n’ msg[5] : ’g’ msg[6] : 0 int main(){ char msg[] = ”string”; char * p = msg; p = ”abc”; printf(”Hello world!\n”); } p = &msg[0] p ’a’ ’b’ ’c’ ’H’ ’e’ ’l’ : 名前のない配列 (グローバル変数) int printf(char* pstr, …) 名前のない配列 (グローバル変数) よくわかんなければ、今はいいです。(これでやっと ”文字列“の説明ができました。)

ポインタと配列 課題21 文字列追加関数 文字列の後ろに文字列を追加する関数 void strcat(char* pdest, char* psrc); を作って、使ってみてください。 // 文字列を後ろにくっつける void strcat(char* pdest, char* psrc){ ここは考えてください。 } int main(){ char dest[20]="abcd"; strcat(dest, "efgh"); printf(dest); printf("\n"); char dest2[20]="0123456789"; strcat(dest2, "ABCDEF"); printf(dest2); printf("\n"); 配列は、十分長く。 足りないと事故がおきます。 もし、char dest[5];だと はみ出してしまう。 ほかの変数や 最悪の場合 プログラムを 壊すことも dest[0] ’a’ dest[1] ’b’ dest[2] ’c’ dest[3] ’d’ dest[4] ’e’ dest[5] ’f’ dest[6] ’g’ dest[7] ’h’ dest[8] 0 こんな 変数は 無い abcdefgh 0123456789ABCDEF

キャスト 型を変えることをキャストといいます。 ポインタをキャストすると変なことができます。 pd: 0x10 d p: 0x10 ポインタと配列 キャスト 型を変えることをキャストといいます。 ポインタをキャストすると変なことができます。 int main(){ int a; double d=10.4; a = (int)d; } (型) 変数 と書くと、変数を(型)に書いた 型にキャストできます。 普通に、a=10になります。 int main(){ double d = 0.2; double* pd = &d; int* p = (int*) pd; int a[2]; a[0] =*p; a[1] =*(p+1); printf(”%x %x\n”, a[0], a[1]) } pdを無理やり int* に変換 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 d pd: 0x10 p: 0x10 p+1: 0x14 doubleの中がどうなってるか見ることができる。

sizeof 演算子 変数のサイズを返す演算子です。 sizeof(char) = 1 sizeof(int) = 4 sizeof(double) = 8 sizeof d = 8 sizeof a = 20 sizeof a[0] = 2 length of a is 10 sizeof s = 8 10 0 0 0 20 20 20 20 変数のサイズを返す演算子です。 struct S{ char c; int i; }; int main(){ printf("sizeof(char) = %d\n", sizeof(char)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(double) = %d\n", sizeof(double)); double d; printf("sizeof d = %d\n", sizeof d); short a[10]; printf("sizeof a = %d\n", sizeof a); printf("sizeof a[0] = %d\n", sizeof a[0]); printf("length of a is %d\n", sizeof a / sizeof a[0]); struct S s; printf("sizeof s = %d\n", sizeof s); s.c = 0x10; s.i = 0x20202020; char* p = (char*)&s; int i; for(i=0; i<sizeof(s); ++i){ printf(" %x", *(p+i)); } return 0;