9 ライブラリ関数 ( 教科書 P.84) C 言語には使用頻度が高そうな機能は関数として用意されており, それらは幾つかのライブラリに分類されている. それらの総称を C 言語標準ライブラリと呼ぶ. 次を参照のこと.

全文

(1)

9 ライブラリ関数(教科書 P.84) C 言語には使用頻度が高そうな機能は関数として用意されており,それらは幾つかのライ ブラリに分類されている.それらの総称をC 言語標準ライブラリと呼ぶ.次を参照のこと. http://ja.wikipedia.org/wiki/%E6%A8%99%E6%BA%96C%E3%83%A9%E3%82%A4%E3%83%9 6%E3%83%A9%E3%83%AA ライブラリの関数を必要に応じて使用すれば,プログラムを効率よく開発できる. 9.1 ライブラリ関数の使用方法 ライブラリに収められている関数の情報がヘッダファイルに含まれる.使用する関数が 含まれるライブラリのヘッダファイルを#include 文で取り込む必要がある. 例: #include<stdio.h> 9.2 文字列操作関数(string.h) 機能を次の表に示す. 表1 文字列操作関数の抜粋 関 数 動 作 strcat 二つの文字列を連結する. strncpy,strcpy 文字列をコピーする. strncmp,strcmp 二つの文字列を比較する. strlen 文字列のサイズを得る.

9.2.1 char * strcat(char * str1, char * str2)

str1 に str2 を連結して,それを str1 へセットする.例を次に示す. プログラム9-1 #include<stdio.h> #include<string.h> void main(void) {

char str1[10] = "ABC"; /* "ABC"を文字型配列変数 str1 に代入する */ char str2[10] = "XYZ"; /* "XYZ"を文字型配列変数 str2 に代入する */ printf("str1 =%s¥nstr2 = %s¥n¥n", str1, str2); /* str1, str2 を表示する */

/* str1 の後に str2 の文字列,XYZ が追加される */ strcat(str1, str2); /* str1="ABCXYZ" */

printf("str1 =%s¥nstr2 = %s¥n¥n", str1, str2); /* str1, str2 を表示する */ }

(2)

str2[0]から num 文字を str1 以降にコピーする.

char * strcpy(char * str1, char * str2)

str2 の文字列を str1 にコピーする.例を次に示す. プログラム9-2 #include<stdio.h> #include<string.h> void main(void) {

char str1[7] = "ABCDEF"; /* "ABCDEF"を文字型配列変数 str1 に代入する */ char str2[7] = "abcdef"; /* "abcdef"を文字型配列変数 str2 に代入する */ /* str1 の最初の 3 文字,ABC が str2[0]以降に上書きされる */ strncpy(str2, str1, 3); /* str2 = "ABCdef" */ printf("str1 =%s str2 = %s¥n¥n", str1, str2); /* str1, str2 を表示する */ /* str1 の文字列,ABCDEF が str2[0]以降に上書きされる */ strcpy(str2, str1); /* str2="ABCDEF" */ printf("str1 =%s str2 = %s¥n¥n", str1, str2); /* str1, str2 を表示する */ }

9.2.3 int strncmp(char * str1, char * str2, size_t num)

str1 と str2 のそれぞれの先頭から num 文字について比較する.両者が等しければ戻り値 0 を,文字(数)の関係が str1>tr2 ならば+1 を,そうでなければ-1 を返す.(ただし size_t は符号なし整数を意味する型である.)

int strcmp(char * str1, char * str2 )

str1 と str2 を比較する.両者が等しければ戻り値 0 を,文字(数)の関係が str1>str2 なら ば+ 1 を,そうでなければ-1 を返す.(但し処理系によっては負・0・正の区別だけになる ことがある.)例を次に示す. プログラム9-3 #include<stdio.h> #include<string.h> void main(void) {

/* CHARACTER CODE: 'A'=0x41, 'B'=0x42, 'C'=0x43, 'D'=0x44, 'E'=0x45, 'F' =0x46 */ /* CHARACTER CODE: 'x'=0x78, 'y'=0x79, 'z=0x7a . (TEXT P. 8) */

char str1[10] = "ABCDEF"; /* 文字コードで見ると,str1<str2 である.なぜなら */ char str2[10] = "ABCxyz"; /* 大文字より小文字の文字コードが大きいから */ /* str1[0]~str1[9]を便宜上 str1[0-9]と表現する */ printf("%d, ", strncmp(str1, str2, 10)); /* str1[0-10]<str2[0-10] : -1 */ printf("%d, ", strncmp(str1, str2, 6)); /* str1[0- 5] <str2[0-5] : -1 */ printf("%d, ", strncmp(str2, str1, 6)); /* str2[0- 6] >str1[0-6] : +1 */ printf("%d, ", strncmp(str1, str2, 3)); /* str1[0- 3] =str2[0-3] : 0 */ printf("%d¥n", strncmp(str1, str2, 1)); /* str1[0- 1] =str2[0-1] : 0 */

(3)

printf("%d¥n", strcmp(str1, str2)); /* str1[ ] <str2[ ] : -1 */ }

9.2.4 size_t strlen(char * string)

string の文字数を戻り値として返す.

例を次に示す.まず入力を促すメッセージを画面に表示する.キーボードから文字列を入力 し,そのデータを変数 string へセットする.string の文字数を変数 number へ代入する.string と number の内容を画面に表示する. プログラム 9-4 #include<stdio.h> #include<string.h> void main(void) {

char string[10]; /* 文字型配列変数 string を宣言する */ int number; /* int 型変数 number を宣言する */ printf("Please input string.¥n"); /* メッセージを画面に表示する */ scanf("%s", string); /* 文字列を string へ入力する */ number = strlen(string); /* string の文字数を number へ代入する */ printf("%s has %d characters.¥n", string, number);

}

9.3 数学関数(math.h) 機能を次に示す.

表 2 数学関数の抜粋

関 数 機 能 プログラムでの表現例

sin x ( cos x, tan x) 三角関数,単位rad sin(x) sinh x ( cosh x, tanh x) 双曲三角関数,単位rad sinh(x) sin-1 x ( cos-1 x, tan-1 x) 逆三角関数,単位 rad asin(x)

√𝐱 平方根 sqrt(x) xy x の y 乗 pow(x, y) ey e の y 乗 exp(x) |x| 絶対値 abs(x) ln x 自然対数 log(x) log10x 常用対数 log10(x) x を y で割った余り fmod(x, y) (注意!)math.h を含むとき,コンパイルするときはオプション,-lm を入れ る.(例: gcc -o p9_7 p9_7.c -lm[Enter] ) 9.4 データ変換関数(stdlib.h) atoi は文字列を整数に変換し,atof は文字列を実数に変換する.

(4)

9.5 メモリ操作関数(stdlib.h)

例えば顧客の情報を配列や構造体配列で管理しようとすると,まずその要素数を決める 必要がある.

例: struct data { … } Customer[100];

これをメモリの静的確保という.静的確保には次の問題がある.もし顧客数が 100 を超え ると,その情報を扱えない.またもし顧客数が 10 名になると,メモリの使用効率が悪くな る.そこで必要に応じてメモリを確保する方法,動的確保の方法が用意されている.

void * malloc(size_t size)

size_t 型の領域,size をメモリに動的に確保する.確保したメモリの使用が済んだ後にはメ モリを開放することになる.

void * free(void * ptr)

ptr で指し示した領域を開放する.動的確保を使用すると,メモリを効率的に使える.

例: char * ptr; /* char * 型変数 ptr を宣言する */

ptr = (char *)malloc(256); /* char * 型の 256 バイトのメモリを確保する */ free(ptr); /* ptr が占有していたメモリ領域を開放する */ 他の例を次に示す.プログラムではまず入力を促すメッセージを画面に表示する.キー ボードから学生数を入力する.malloc 関数で学生数分の氏名データの領域を確保する.次に 氏名の入力を促すメッセージを画面に表示する.for ループで人数分の名前のデータを読み 込む.for ループで入力の順番と逆に名前を表示する.最後に変数が占有していたメモリ領域 を解放する. プログラム 9-13 #include<stdio.h> #include<stdlib.h> void main(void) {

char *name; /* char * 型変数 name の宣言,名前を扱うポインタ */ int number; /* 学生数を扱う変数 number の宣言 */ int i; /* int 型変数 int を宣言する */ printf("Input number of students.¥n"); /* メッセージを画面に表示する */ scanf("%d", &number); /* キーボードから学生数を入力する */ name = (char *)malloc(number*10); /* 学生数分の氏名データの領域を確保する */ if(name == NULL){ /* 動的メモリ割り当ての失敗時の処理 */

(5)

printf("Allocate error.¥n"); /* 割り当てのエラーのメッセージ */ }else{

printf("Input names of students¥n"); /* 氏名の入力を要求する表示 */ for(i=0; i<number; ++i){ /* 人数分の名前のデータを読み込むためのループ */ scanf("%s", (name+i*10)); /* 人数分の名前のデータを読み込む */ }

printf("Let's print names backward.¥n"); /*入力の順番と逆に名前を表示する*/ for(i=0; i<number; ++i){ /* 人数分のデータを出力するためのループ*/ printf("%s ", (name+(number-1-i)*10)); /* 入力順番と逆に名前を表示 */ } printf("¥n"); /*改行する*/ free(name); /* 変数が占有していたメモリ領域を解放する */ } } 9.6 入出力関数

int sprintf(char * buf, string, 型 x1, 型 x2, …)

書式,string を指定して変数,x1,x2,…を文字列としてバッファに出力する.使い方は buf の部分を除いて関数,printf と同じである.string は printf の" "で囲むところである.バ ッファは短期的にデータを保存するための記憶領域であり,通信の効率化で使われる.あ る量のデータがバッファに集まると,それが通信先へ送信される. 例を次に示す.初めにデータを保持するためのバッファ,buf(128 バイト)を確保する. 変数 x=3.0,y=1.2 とする.それらの掛算と割算の結果を sprintf によってバッファへ出力す る.バッファのデータは printf で画面に出力される. プログラム 9-14 #include<stdio.h> #include<stdlib.h> void main(void) {

char buf[128]; /* char* 型配列変数 buf の宣言,バッファ領域の確保 */ double x = 3.0, y = 1.2; /*double 型変数 x,y を宣言して初期値を代入する*/ sprintf(buf, "x * y = %4.1f, x / y = %4.1f", x*y, x/y); /* buf に文字列をセットする */ printf("%s¥n", buf); /* バッファの内容を画面へ出力する */

}

9.7 その他の関数(略)

9.7.1 time_t time(time_t * today)関数は万国標準時(UTC)の 1970 年 1 月 1 日の 00:00:00 か ら 現 在 時 刻 ま で の 経 過 時 間 を 秒 単 位 で 表 し た 数 値 を 返 す 関 数 で あ る . ま た tm * localtime(time_t * today)関数は time()関数で得た時間を現地時間に変換し,tm 構造体に格納 する関数である.これらの関数の例を示す.動作は次のとおり.UTC 1/1/1970 からの経過 時間,今日の年・月・日・時・分・秒を表示する.

(6)

プログラム 9-15 #include<stdio.h> #include<time.h> void main(void) {

time_t ltime; /* time_t 型変数 ltime の宣言 */ struct tm * today; /* 構造体 tm * 型変数 today の宣言 */ time(&ltime); /* 現在時刻を ltime へセットする */

printf("UTC 1/1/1970 からの経過時間(秒)は %lu です.¥n", ltime); /* %lu: unsigned long: 符号なし倍精度整数を 10 進で出力する*/ today = localtime(&ltime); /* today に現地時間をセットする */

printf(" 今 日 は %d 年 %d 月 %d 日 で す . ¥n", today->tm_year+1900, today->tm_mon+1, today->tm_mday); /* 年・月・日の表示(Text p. 96) */

printf(" 時 刻 は %d 時 %d 分 %d 秒 で す . ¥n", today->tm_hour, today->tm_min, today->tm_sec); /* 時・分・秒の表示 */ } 9.7.3 qsort()関数(stdlib.h) データを並び替えて順番に整列する作業をソートという.例えばデータ,score[10] = {85, 90, 75, 30, 58, 62, 100, 98, 70, 48}を,{ 30, 48, .., 100}へと大きい順に並べることを昇順(正順), { 100, 98, .., 30 }へと小さい順に並べることを降順(逆順)という.qsort()関数はソートを実 行するための関数であり,クイックソート[1]という方法でデータの並べ替えを行う

void qsort( void * hairetus , size_t num, size_t width , int compare( const void * elm1, const void * elm2 ); 引数:

void * hairetus :並べ替えを行う配列を指すポインタ(ソート対象のデータ)

size_t num :配列の要素数(ソート対象のデータの件数)

size_t width :配列の各要素サイズ(ソート対象のデータの 1 つ当りのバイト数)

int compare( const void * elm1, const void * elm2 ) 引数:

const void * elm1:const のため,elm1 の内容は変化しない. const void * elm2:const のため,elm2 の内容は変化しない. 戻り値: elm1< elm2 の場合:負の整数 elm1= elm2 の場合:0 elm1> elm2 の場合:正の整数 戻り値:なし int compare( )関数 *elm1 と*elm2 とを比較して,それらの前後関係を整数値で返す. * elm1 が* elm2 よりも先であるとき: 負の整数

(7)

* elm1 と* elm2 とのどちらが先でもいいとき: 0

* elm1 が* elm2 よりも後であるとき: 正の整数

具体的には,評価式,*elm1-*elm2 の計算値を戻り値とする.つまり式で表現すると, return(*elm1-*elm2 );

とすると次のようになる.

*elm1<*elm2 のとき:戻り値は負: elm1 が先,*elm2 が後

*elm1=*elm2 のとき:戻り値は 0: elm1,elm2 のどちらが先でも後でもよい *elm1>*elm2 のとき:戻り値は正: elm1 が後,*elm2 が先

つまり小さい順に並べ替えることになる.評価式を compare( )関数内に実装して,ソートの 方法を指定することになる.プログラム 9-16 では評価関数として strcmp( )が利用されてい る.クイックソートの例を示す.動作は次のとおり.5 名分の氏名が文字型配列 hairetsu に セットされる.昇順ソートを行うため,副関数 cmpfunc1 がコールされる.結果を画面に表 示する.次に降順ソートを行うため,副関数 cmpfunc2 がコールされる.結果を画面に表示 する. プログラム 9-16 #include<stdio.h> #include<stdlib.h> #include<string.h>

char hairetsu[5][10] = {"yamada", "tanaka", "kawaguchi", "ando", "takeda"};

/* 配列の要素サイズの最大は 10 バイト(kawaguchi は 10 バイト=9 文字+'¥0') */ int cmpfunc1(const void *str1, const void *str2) /* 比較関数その 1,昇順 */

{ return(strcmp(str1, str2)); /* str1<str2:負, str1=str2:0, str1>str2:正 */ } /*昇順: ando, kawaguchi, takada, tanaka, yamada*/

int cmpfunc2(const void *str1, const void *str2)/* 比較関数その 2,降順 */ {

return(-strcmp(str1, str2)); /* cmpfunc1 の評価式にマイナス,-が掛っている */ } /*降順:yamada , tanaka, takada, kawaguchi, ando*/

void main(void) {

int i;

qsort(hairetsu, 5, 10, cmpfunc1);

/* 対象:hairetsu,データ数:5, 配列の各要素サイズの最大は 10 バイト, 評価関数: cmpfunc1 */ for(i=0; i<5; ++i){ /* クイックソート(昇順) の結果の出力*/

printf("%s ", hairetsu[i]); /* クイックソートの結果は hairetsu[]に格納されている */ }

printf("¥n");

qsort(hairetsu, 5, 10, cmpfunc2); /* */

/* 対象:hairetsu,データ数:5, 配列の各要素サイズの最大は 10 バイト, 評価関数: cmpfunc2 */ for(i=0; i<5; ++i){ /* クイックソート(降順) の結果の出力*/

printf("%s ", hairetsu[i]); /* クイックソートの結果は hairetsu[]に格納されている */ }

printf("¥n"); /*改行する*/ }

Updating...

関連した話題 :