C言語 情報理工学部 システム工学科 3年 H107035 亀窪祐太 H107042 纐纈琢真 H107034 神谷真輝 H107087 西村智 目的 入力時のエラーを無くそう 型にとらわれないプログラムを書こう 動的配列を使おう プログラム これを実行 すると… プログラムの問題点 1. バッファサイズのチェックを行っていない 2. 空白、改行も入力文字として取っている 3. 型をチェックしていない 1の改善策:入力関数 char* fgets(char* str, int strのサイズ, FILE* 入力ストリーム); ストリームから文字列を読み取り str が指す配列に格納する 格納されるのは (strのサイズ) – 1 バイト目まで 2の改善策:バッファ削除 int getchar(); 標準入力から1文字取り出し その文字コードを返す if (str[strlen(str) - 1] != ‘\n’){ //strlen 文字列の長さを取得する while(getchar() != '\n'); //改行がでるまで標準入力から1文字ずつ取り出す } ※入力が改行で終わるとき、この方法でできる 2の改善策:バッファ削除 int fflush(FILE* stream); streamが出力ストリーム、または直前の 操作が入力でない更新ストリームなら 全ての内容を出力し、捨てる bccでは、streamが入力ストリームなら 全ての内容を捨てる ※標準の規格では、入力ストリームに 対しての動作は未定義 3の改善策:フォーマット関数 int sscanf(const char* str, const char* format, 代入先の変数) str の文字列を format の形式に変換して、指 定した変数に代入する。 プログラムの解説 fgets(d,sizeof(d),stdin); [0] [1] [2] [3] [4] d \0 stdin a b c d ヌル文字を入れる d – 1 バイト目まで文字列を入れていく e f \n プログラムの解説 if(d[strlen(d) - 1] != ‘\n’) [0] [1] [2] [3] [4] d a b c d stdin \0 strlen = 4 strlen(d) – 1 番目が \n か判定 dの文字列の長さを求める(\0は含まない) e f \n プログラムの解説 while(getchar() != ‘\n’); [0] [1] [2] [3] [4] d a b c d stdin \0 getchar 取り出した文字が stdinから1文字取り出す \n を取り出すまで繰り返す \n か判定 e f \n プログラムの解説 if(sscanf(d,”%s”,c) == 0) exit(-1); [0] [1] [2] [3] [4] d a b c d \0 [0] [1] [2] [3] [4] c a cd を文字列型に変換 に文字列型に変換した d をコピー b c d \0 関数ポインタ 関数のアドレスを保持するポインタ 以下のように宣言する 戻り値の型 (*ポインタ名) (引数のリスト); 以下のように使う int (*p)(int x); int func(int x){ return x * 2; p = func; } ans = (*p)(10);(推奨) または ans = p(10); voidポインタとキャスト voidポインタ(汎用ポインタとも呼ばれる) あらゆるポインタ型に変換できる どのような型も受け取れる関数を作れる 使用する際には使いたい型にキャストする 例 void *v; int i; v = &i;//受け取る際 int *p = (int *)v;//使用する際 比較関数 並べ替えるための基準を指定する関数 2つの引数を持ち、int型を返り値とする 返り値は 第1引数を先頭側にする場合、負の値 第2引数を先頭側にする場合、正の値 両者が同じなら0 Cによる動的配列 動的に連続領域を確保する リスト構造を使用する 構造体とポインタを使用して実現 配列を動的に確保する malloc, calloc, realloc, free関数を使用して実 現 動的確保の利点 必要な場所で必要な量だけ確保する事が可 能 好きな時に、解放する事が出来る 使用範囲が自由に決められる メモリ確保関数 void* malloc(sizeの型 size) void* calloc(sizeの型 n, sizeの型 size) void* realloc(void *ptr, sizeの型 size) void free(void *ptr) void* malloc(sizeの型 size) メモリを確保する関数 引数には確保したいメモリサイズ(バイト)を渡す 任意の領域を確保するために、 voidポインタ型が使われている 確保領域に合わせてキャストする必要あり 返り値 成功 :確保領域の先頭アドレス 失敗 :NULL void* calloc(sizeの型 n,sizeの型 size) mallocと同じく、メモリを確保する関数 キャストする必要あり 引数には配列の要素数と要素の メモリサイズ(バイト)を渡す 返り値 成功 :確保領域の先頭アドレス 失敗 :NULL 確保した領域は 全てのビットを0で初期化されている void* realloc(void *ptr,sizeの型 size) 動的配列のサイズを再定義する キャストする必要あり 引数には再定義したい配列のアドレス、 再定義後のメモリサイズ(バイト)を指定する 返り値 成功 :確保領域の先頭アドレス 失敗 :NULL reallocの注意点 引数がおかしくても文法エラーにならない 第一引数をNULLに realloc(NULL, sizeの型 size)→malloc(sizeの型 size) 第二引数を0に realloc(void *ptr, 0)→free(void *ptr) void* free(void *ptr) 確保された領域を解放する関数 引数には動的に確保した領域のアドレスを渡す 動的に確保した領域以外のアドレスや既に解放した アドレスを渡してはいけない NULLを受け取った場合何もしない 解放し忘れていてもエラーにはならないので注意 解放し忘れる → メモリリークが起こる malloc ・ calloc : プログラム例 freeで解放 忘れずに realloc : プログラム例 課題1 5個の変数にそれぞれ整数を入力し、引数が 1つの関数ポインタを利用してその値を加算 せよ scanfは使わない 課題2 名前とGPAを持つ構造体を使った配列を10 人分保管し、qsortを使って並び変えよ mallocまたはcallocを使うこと 並び変えの基準 GPAの降順 GPAが同じ場合は名前の昇順(辞書順) 課題3 課題2のプログラムを任意の数扱えるように せよ ユーザに任意の人数分のデータを入力させよ
© Copyright 2025 ExpyDoc