第8回 http://www.fit.ac.jp/~matsuki/lecture.html プログラミングⅡ 第8回 http://www.fit.ac.jp/~matsuki/lecture.html
連絡 小テスト 授業開始直後と終了直前に小テストを2行います 授業開始直後テスト(復習テスト)⇒前回の復習 授業終了直前テスト(本テスト)⇒その日の内容の復習 本テストの成績(正答率)が50%以下の場合は、宿題を出します(レポートとは別)。 宿題を決められた期日までに提出しない場合は、欠席扱いにします
宿題の提出について 以下の場合は、出題日の出席を欠席とする 締切日を過ぎた場合 正解率が7割未満の場合 提出は、PDFファイルを印刷して、それに答えを書いて提出すること。
プログラミングに関する質問時間 月曜日と金曜日の12:00から13:00までは, CAE室で,プログラミングに関する質問を受け付けています. 遠慮なく相談に来てください.
今日の内容 ポインタ(応用編) 配列とポインタの関係 引数と配列 文字列とポインタ 文字列を扱う関数紹介 動的メモリ確保 strlen関数, strcpy関数, strcat関数, strcmp関数 動的メモリ確保 malloc関数, free関数
文字列の操作
標準ライブラリ関数を使う 標準ライブラリ関数 自分で定義した関数 printf scanf その他 予め用意されている 書込め max solve func1 予め用意されている 標準的な処理を行う関数 書込め プログラマーが自作した関数
標準ライブラリ関数を使う 文字列操作を行う関数 を紹介 標準ライブラリ関数 printf scanf その他 予め用意されている 標準的な処理を行う関数 文字列操作を行う関数 を紹介
文字列操作を行う関数 strlen : 文字列の長さを求める関数 strcpy : 文字列をコピーする関数 書込め strlen : 文字列の長さを求める関数 strcpy : 文字列をコピーする関数 strcat : 文字列をつなげる(連結する)関数 strcmp : 2つの文字列を比較する関数 注意: この文字列操作の関数を使うときは,string.hというファイルをインクルードする必要がある 書込め
文字列操作を行う標準ライブラリ関数を利用するときに必要 サンプルプログラム #include <stdio.h> #include <string.h> main() { 書込め 文字列操作を行う標準ライブラリ関数を利用するときに必要
文字列の長さを調べる(strlen関数) string lengthの略 関数宣言: size_t strlen(const char *str); 機能: 文字列strのNULL文字を除く長さを返す. 正の値のみのint型 書込め 5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ strlen(str) 5 str[0] str[1] str[2] str[3] str[4] str[5]
サンプルプログラム #include <string.h> #include <stdio.h> main() { 実行例 #include <stdio.h> #include <string.h> main() { char str[100]; printf(“文字列を入力してください\n”); scanf(“%s”, str); printf(“文字列の長さは%dです\n”, strlen(str) ); } 文字列を入力してください HELLO↵ 文字列の長さは5です. 書込め 文字列の長さを得る
文字列を配列にコピー(strcpy関数) string copyの略 関数宣言: char* strcpy(char *str1, const char *str2); 機能: 文字列str2を文字列str1の領域にコピーして,str1を返す. str2は変わらない 書込め コピーする ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ str1[0] str1[1] str1[2] str1[3] str1[4] str1[5] str2[0] str2[1] str2[2] str2[3] str2[4] str2[5] str1 str2
strcpyを使えば,簡単に配列に文字列を格納できる! サンプルプログラム #include <stdio.h> #include <string.h> main() { char str1[100]; char str2[100]; strcpy(str1, “HELLO”); strcpy(str2, “GoodBye”); printf(“配列str1は%sです\n”, str1); printf(“配列str2は%sです\n”, str2); } 実行例 配列str1はHELLOです 配列str2はGoodByeです str1に”HELLO”をコピー 書込め str2に”GoodBye”をコピー 書込め strcpyを使えば,簡単に配列に文字列を格納できる!
文字列を連結する(strcat関数) 関数宣言: char* strcat(char *str1, const char *str2); string concatenateの略 関数宣言: char* strcat(char *str1, const char *str2); 機能: 文字列str2を文字列str1の末尾に追加して,str1を返す. 書込め str1 str1 B y e ! \0 G o o d G o o d \0 B y e ! \0 \0の上から追記される str2
サンプルプログラム 配列str1はHELLOです 配列str2はGoodByeです 連結するとHELLOGoodByeです 書込め #include <stdio.h> #include <string.h> main() { char str0[100]; char str1[100]; char str2[100]; strcpy(str1, “HELLO”); strcpy(str2, “GoodBye”); strcpy(str0, str1); strcat(str0, str2); printf(“配列str1は%sです\n”, str1); printf(“配列str2は%sです\n”, str2); printf(“連結すると%sです\n”, str0); } 実行例 配列str1はHELLOです 配列str2はGoodByeです 連結するとHELLOGoodByeです str0にstr1をコピー str0の末尾にstr2を連結 書込め str0(連結した文字列)を表示
strcatの動作内容 strcat(str0, str2); strcpy(str1, “HELLO”); str1 H E L L O \0 strcpy(str2, “GoodBye”); str2 G o o d B y e \0 strcpy(str0, str1); str0 H E L L O \0 strcat(str0, str2); str0 H E L L O G o o d B y e \0 書込め 書込め 書込め 書込め 書込め 書込め 書込め 書込め
配列の大きさに注意 配列の大きさが十分でない場合, 配列の領域をはみ出してコピーすることが起こる(メモリ破壊) メモリ破壊の発生 配列の領域をはみ出してコピーすることが起こる(メモリ破壊) str2 G o o d B y e \0 strcat(str0, str2); str0 H E L L O G o o d B y e \0 確保した領域 char str0[10] メモリ破壊の発生 書込め 取り扱うデータ量が,配列の大きさを超えないように注意
文字列を比較する(strcmp関数) 関数宣言: string compareの略 関数宣言: char* strcmp(const char *str1, const char *str2); 機能: 文字列str1と文字列str2を比較して,一致していたら0を返す 書込め True (同じ) False (違う) str1とstr2は同じ? strcmp(s1, s2); 0を返す 辞書の並び順で1か-1を返す 書込め
2つの文字列を比較した結果,戻り値が0であれば サンプルプログラム #include <stdio.h> #include <string.h> main() { char str1[100]; char str2[100]; printf(“1番目の文字列を入力:”); scanf(“%s”, str1); printf(“2番目の文字列を入力:”); scanf(“%s”, str2); if ( strcmp( str1, str2 ) == 0 ) printf(“2つの文字列は同じです\n”); else printf(“2つの文字列は違います\n”); } 実行例 1番目の文字列を入力:hello 2番目の文字列を入力:hello 2つの文字列は同じです 2つの文字列を比較した結果,戻り値が0であれば 書込め
動的なメモリ確保
文字列の長さを実行時に決める プログラム実行前に配列の大きさは決まっている (実行時の変更は不可) char str1[100]; ・・・・ scanf(“%s”, str1); char *str2 = “GoodBye”; 文字列の入力 決まった文字列の大きさを指すポインタとして定義 実行時に文字列を格納する領域を,動的に確保する (好きな大きさのメモリを確保) 書込め
文字列の長さを実行時に決める メモリの確保: malloc関数 を利用 メモリの開放: free関数 を利用 書込め 書込め この関数によって,好きなメモリサイズを確保することができる 書込め malloc関数で確保したメモリ領域は,必ずfree命令で解放しなければならない 使い終わったメモリは解放しないと,使えるメモリが減っていくことになる (通常の変数や配列では,プログラムが終了すると自動的に解放される) 書込め メモリを解放し忘れることを,メモリリーク(Memory leak)という
malloc関数 機能: 確保したいメモリサイズを引数に指定すると,そのサイズ分だけメモリを確保し,その先頭アドレスを戻り値として返す. 確保したいメモリサイズを引数に指定すると,そのサイズ分だけメモリを確保し,その先頭アドレスを戻り値として返す. 使い方: char *p; p = (char *)malloc(確保したいメモリサイズ) 例: p = (char *)malloc(10); //10バイト分確保 書込め pはchar型へのポインタ char型へのポインタにキャストする必要がある 書込め pには,確保したメモリ領域の先頭アドレスが代入される バイト単位で指定
free関数 機能: 確保したいメモリ領域を解放する (mallocとfreeは必ず対で使う) 使い方: 確保したいメモリ領域を解放する (mallocとfreeは必ず対で使う) 使い方: free(解放するメモリ領域のアドレス); 例: p = (char *)malloc(10); //10バイト分確保 free(p); //メモリ解放 書込め 書込め mallocで確保したアドレス 書込め
動的メモリ確保の注意&その他 書込め malloc関数とfree関数は,対で使う 文字列用の領域を確保する場合は,NULL文字用に1バイト余分に領域を確保する stdlib.hをインクルードする必要がある sizeof(型名または変数名)⇒その型や変数の大きさを調べることができる sizeof(int); ⇒ 4 sizeof(double); ⇒ 8 int x; sizeof(x); ⇒ 4 char y[20]; sizeof(y); ⇒ 20 1バイト×20個の要素=20バイト int z[20]; sizeof(z); ⇒ 80 4バイト×20個の要素=80バイト 書込め 書込め
書込め ‘\0’用に1バイト余分に必要 プログラムの強制終了 書込め 何文字のaを用意しますか:4 aaaaを用意しました #include <stdio.h> #include <stdlib.h> main() { char *str; int num, i; printf(“何文字のaを用意しますか:”); scanf(“%d”,&num); str = (char *)malloc(sizeof(char)*(num+1)); if (!str) { printf(“メモリ確保に失敗しました\n”); exit(0); } for (i=0; i<num; i++) { *(str + i) = ‘a’; *(str + num) = ‘\0’; printf(“%sを用意しました\n”, str); free(str); stdlib.hをインクルードする 書込め 書込め ‘\0’用に1バイト余分に必要 1×(num+1)バイト分の領域を確保 プログラムの強制終了 書込め 実行例 何文字のaを用意しますか:4 aaaaを用意しました メモリを解放