2009年11月10日 (火) 16:06

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のプログラムを任意の数扱えるように
せよ
ユーザに任意の人数分のデータを入力させよ