*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  このファイルには,『C言語関数の使い方+作り方 完全制覇』(柏原正三著,技術評論社刊)の各章のサンプルプログラムを収録しています.サンプルプログラムを試してみる場合は,各ソースコード部分をコピーして,拡張子が.Cのソースファイルに貼り付けてください.各サンプルプログラムの解説と用法については,『C言語関数の使い方+作り方 完全制覇』の本文の該当個所を参照してください。  このファイルに収録されたプログラムは上記書籍に関し著作権法により保護されています.再配布,転載などの行為は禁じられていますからご注意ください. (C) 2001 Shyozo Kashihara *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ☆☆Sample List 1.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* 関数のプロトタイプ宣言 */ void OperationError(char *pstr); int main(int argc, char *argv[]) { FILE *pfile; int n, count = 0; /* ヘルプを表示する */ if (argc > 3 || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")) { OperationError("プロトタイプ宣言テストプログラム\n\n" "起動方法:Proto 入力ファイル名 [ > 出力ファイル名]\n"); } /* バイナリ読み取りモードでファイルを開く */ if ((pfile = fopen(argv[1], "rb")) == NULL) OperationError("入力ファイルを開けませんでした.\n"); /* EOFを返すまで読み取りを繰り返す */ while ((n = fgetc(pfile)) != EOF) /* 文字nを出力する(標準出力) */ fputc(n, stdout); /* ファイルを閉じる */ fclose(pfile); return 0; } /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } ------------------------------------------------------------- ☆☆Sample List 1.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include void ChangeParam(int n) { /* 仮引数nに変更を加える */ n += 100; printf("ChangeParam()関数の仮引数n = %d\n", n); } main () { int i = 5; /* ChangeParam()関数を呼び出す */ ChangeParam(i); /* 変数iの内容を表示する */ printf("ChangeParam()関数呼び出しの後のi = %d\n", i); return 0; } ------------------------------------------------------------- ☆☆Sample List 1.3☆☆(注意!) ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include int *ReturnLocalRef1(void) { int n = 500; return &n; } char *ReturnLocalRef2(void) { char str[] = "これはローカルな文字列"; return str; } main () { /* ReturnLocalRef1()関数を呼び出す */ printf("*ReturnLocalRef1() = %d\n", *ReturnLocalRef1()); /* ReturnLocalRef2()関数を呼び出す */ printf("ReturnLocalRef2() = %s\n", ReturnLocalRef2()); return 0; } ------------------------------------------------------------- ☆☆Sample List 1.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include void Dereference1(int *p) { /* 間接参照代入を使って変数の値を変更する */ *p = 500; } void Dereference2(char *pstr) { strcpy(pstr, "文字列をコピーする"); } main () { int n = 100; char str[] = "これはもとの文字列"; /* Dereference1()関数を呼び出す */ Dereference1(&n); /* nの内容を表示する */ printf("n = %d\n", n); /* Dereference2()関数を呼び出す */ Dereference2(str); /* strの内容を表示する */ printf("str = %s\n", str); return 0; } ------------------------------------------------------------- ☆☆Sample List 2.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } main () { int n; while ((n = getchar()) != EOF) { /* 漢字文字を読み飛ばす */ if (IsKanji1st(n)) { getchar(); continue; } /* isXXX系の関数が真の判定結果を返す文字だけを出力する */ else if (isalnum(n)) /* <--- ここに,isXXX形式の関数を記述する */ putchar(n); } return 0; } ------------------------------------------------------------- ☆☆Sample List 2.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } main () { int n; while ((n = getchar()) != EOF) { /* 漢字第1文字を読み飛ばす */ if (IsKanji1st(n)) { /* 漢字第2バイトを確認する */ /* <--- ここに,isXXX形式の関数を記述する */ if (isalnum(n = getchar())) putchar('?'); else putchar('*'); continue; } /* 真の判定結果が得られる文字だけを出力する */ else if (isalnum(n)) /* <--- ここに,isXXX形式の関数を記述する */ putchar(n); else ; } return 0; } ------------------------------------------------------------- ☆☆Sample List 2.3☆☆(注意!) ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { int n; while ((n = getchar()) != EOF) { /* 英文字であれば変換を行う */ if (isalpha(n)) /* tolower()またはtoupper()関数を使う */ putchar(toupper(n)); else putchar(n); } return 0; } ------------------------------------------------------------- ☆☆Sample List 2.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } main () { int n; while ((n = getchar()) != EOF) { /* 漢字文字を素通りさせる */ if (IsKanji1st(n)) { putchar(n); putchar(getchar()); continue; } else /* tolower()またはtoupper()関数を使う */ putchar(toupper(n)); } return 0; } ------------------------------------------------------------- ☆☆Sample List 2.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } /* 半角カナ文字を判定する関数 */ int IsHKana(int c) { /* char型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 半角カナ文字を判定する */ if (uch >= 0xa1 && uch <= 0xdf) return 1; else return 0; } /* 8進数字を判定する関数 */ int IsODigit(int c) { /* 8進数字を判定する */ if (c >= '0' && c <= '7') return 1; else return 0; } /* ASCII文字を判定する関数 */ int IsAscii(int c) { /* ASCII文字を判定する */ if (c >= 0x00 && c <= 0x7f) return 1; else return 0; } main () { int i; /* IsKanji1st()関数を使う */ for (i = 0; i < 255; i++) { if (IsKanji1st(i)) { /* ヘキサ表示する */ printf("%X ", i); } } printf("\n"); /* IsHKana()関数を使う */ for (i = 0; i < 255; i++) { if (IsHKana(i)) { /* 文字表示する */ printf("%c ", i); } } printf("\n"); /* IsODigit()関数を使う */ for (i = 0; i < 255; i++) { if (IsODigit(i)) { /* ヘキサ表示する */ printf("%X ", i); } } printf("\n"); /* IsAscii()関数を使う */ for (i = 0; i < 255; i++) { if (IsAscii(i)) { /* ヘキサ表示する */ printf("%X ", i); } } printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 2.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include /* 記号定数を定義する */ #define ARRAYSIZE 10 /* 10進の数字文字を1桁の数値に変換する関数 */ int ToDigitVal(int c) { /* 10進の数字文字であれば1桁の数値に変換する */ if (c >= 0x30 && c <= 0x39) return (c - '0'); else return c; } /* 1桁の数値を10進の数字文字に変換する関数 */ int ToDigitNum(int c) { /* 1桁の数値であれば10進の数字文字に変換する */ if (c >= 0 && c <= 9) return (c + '0'); else return c; } main () { char carray1[] = "252511378"; char carray2[ARRAYSIZE + 1] = ""; int size = sizeof(carray1)/sizeof(char) -1; int i, dval, maxcolumn = 1000000000, index = 0; long lval = 0; /* 配列carray1の数字文字列を1つのlong型の数値に変換する */ for (i = 0; i < size; i++) { /* ToDigitVal()関数を使って変換する */ lval += ToDigitVal(carray1[i]); /* 後続桁があれば桁上げする */ if (i < size - 1) lval *= 10; } /* 生成したlvalの値を表示する */ printf("lval = %d\n", lval); /* 10進の総桁数を求める */ while (maxcolumn) { if (lval >= maxcolumn) { break; } maxcolumn /= 10; } /* 上位桁から数字文字に変換する */ while (maxcolumn) { /* 上桁の10進の桁値を求める */ dval = lval / maxcolumn; /* ToDigitNum()関数を使って変換する */ carray2[index++] = ToDigitNum(dval); /* 上桁を削除する */ lval -= dval * maxcolumn; /* 下位桁に移行する */ maxcolumn /= 10; } /* 文字列を完成させる */ carray2[index] = '\0'; /* 生成した数字文字列を表示する */ printf("carray2 = %s\n", carray2); return 0; } ------------------------------------------------------------- ☆☆Sample List 2.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 記号定数を定義する */ #define ARRAYSIZE 10 /* 10進の数字文字を1桁の数値に変換する関数 */ int ToDigitVal(int c) { /* 10進の数字文字であれば1桁の数値に変換する */ if (c >= 0x30 && c <= 0x39) return (c - '0'); else return c; } /* 1桁の数値を10進の数字文字に変換する関数 */ int ToDigitNum(int c) { /* 1桁の数値であれば10進の数字文字に変換する */ if (c >= 0 && c <= 9) return (c + '0'); else return c; } /* 数字文字列をlong型数値に変換する関数(strlen()バージョン) */ long StrToL(const char *str) { long lval = 0; int i; int len = strlen(str); for (i = 0; i < len; i++) { /* 後続桁があれば桁上げする */ lval *= 10; /* ToDigitVal()関数を使って変換する */ lval += ToDigitVal(str[i]); } return lval; } /* long型数値を数字文字列に変換する関数(正の整数バージョン) */ int LToStr(long lval, char *str, size_t n) { int dval, index = 0, maxcolumn = 1000000000; unsigned int maxcol = 10; /* 負の値を受け付けない */ if (lval < 0) /* 失敗した */ return 1; /* 10進の総桁数を求める */ while (maxcolumn) { if (lval >= maxcolumn) { break; } maxcol--; maxcolumn /= 10; } /* バッファサイズが足りるかどうか(ヌル文字を含む) */ if (maxcol + 1 > n) /* 失敗した */ return 1; /* 上位桁から数字文字に変換する */ while (maxcolumn) { /* 上桁の10進の桁値を求める */ dval = lval / maxcolumn; /* ToDigitNum()関数を使って変換する */ str[index++] = ToDigitNum(dval); /* 上桁を削除する */ lval -= dval * maxcolumn; /* 下位桁に移行する */ maxcolumn /= 10; } /* 文字列を完成させる */ str[index] = '\0'; /* 成功した */ return 0; } main () { char carray1[] = "252511378"; char carray2[ARRAYSIZE + 1] = ""; long lval; /* StrToL()関数が生成した値を表示する */ printf("StrToL()関数が生成した値 = %d\n", lval = StrToL(carray1)); /* LToStr()関数を使って数字文字列を生成する */ if (!LToStr(lval, carray2, ARRAYSIZE + 1)) /* LToStr()関数が生成した数字文字列を表示する */ printf("LToStr()関数が生成した文字列 = %s\n", carray2); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define SIZE 26 #define MAXSIZE 256 main () { char array1[] = "strcpy()関数の正しい操作"; char array2[] = "これはstrcpy()関数の間違った操作"; char array3[SIZE + 1]; char array4[] = "strncpy()関数の正しい操作"; char array5[] = "これはstrncpy()関数の間違った操作"; char buff1[MAXSIZE + 1]; char buff2[MAXSIZE + 1]; char buff3[MAXSIZE + 1]; int i; /* ヌル文字の付かない文字列を作成する */ for (i = 0; i < SIZE; i++) { array3[i] = 'A' + i; } /* strcpy()を使ってヌル文字付き文字列をコピーする */ strcpy(buff1, array1); printf("buff1 = %s\n", buff1); /* strcpy()を使ってarray3の文字列をコピーする */ strcpy(buff1, array3); /* 末尾にヌル文字がない!! */ printf("buff1 = %s\n", buff1); /* strncpy()を使ってヌル文字付き文字列をコピーする */ strncpy(buff2, array4, sizeof(array4)/sizeof(char)); printf("buff2 = %s\n", buff2); /* buff3の後半に歯止めをかけておく */ strcpy(&buff3[SIZE + 2], array5); /* strncpy()を使って部分文字列をコピーする */ strncpy(buff3, array3, sizeof(array3)/sizeof(char)); printf("buff3 = %s\n", buff3); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define MAXSIZE 256 main () { char array1[MAXSIZE + 1] = "\"これはarray1のもとの文字列\""; char array2[] = "\"これはarray2のもとの文字列\""; char array3[MAXSIZE + 1] = "\"これはarray3のもとの文字列\""; /* strcat()を使ってarray1にarray2を連結する */ strcat(array1, array2); printf("array1 = %s\n", array1); /* strncat()を使ってarray3にarray2を連結する */ strncat(array3, array2, sizeof(array2)/sizeof(char)); printf("array3 = %s\n", array3); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define BUFFSIZE 256 main () { char array1[] = "strchr()とstrrchr()関数を使えば文字列に" "含まれる文字を検索できる"; char array2[] = "strpbrk(),strcspn(),strspn()関数を使えば" "文字列に含まれる複数の文字セットを一括して" "検索できる"; char array3[] = "strstr()関数を使えば文字列に含まれる" "部分文字列を検索できる"; /* 検索用文字セット */ char cset[] = "trsb"; /* 文字t,r,s,bのどれかを検索する */ /* 検索用部分文字列 */ char substr[] = "strstr()"; /* 「strstr()」という文字列を検索する */ /* 書き出し用 */ char buff[BUFFSIZE]; int count = 0, span; char *p = array1, *term; /* strchr()を使って文字「s」を前方検索する */ while ((p = strchr(p, 's')) != NULL) { count++; p++; } printf("array1に含まれる文字\'s\'の数 = %d\n", count); count = 0; p = array1; /* strrchr()を使って文字「s」を後方検索する */ while ((p = strrchr(p, 's')) != NULL) { count++; *p = '\0'; p = array1; } printf("array1に含まれる文字\'s\'の数 = %d\n", count); p = array2; /* strpbrk()を使って文字セット(「t,r,s,bのどれか」)を検索する */ while ((p = strpbrk(p, cset)) != NULL) printf("見つかった文字 = %c\n", *p++); /* strspn()とstrcspn()を使って文字セットを検索する */ p = array2; term = array2 + strlen(array2); while (p < term) { /* 異なるグループ文字があれば前進する */ if ((span = strcspn(p, cset)) > 0) p += span; /* 末尾に達していればループを抜ける */ if (p >= term) break; /* 文字セットのスパン文字列を抽出する */ strncpy(buff, p, span = strspn(p, cset)); /* ヌル文字を追加する */ buff[span] = '\0'; printf("見つかったスパン文字列 = %s\n", buff); /* 前進する */ p += span; } /* strstr()を使って部分文字列(「strstr()」)を検索する */ p = array3; while ((p = strstr(p, substr)) != NULL) { /* 見つかった文字列をbuffに抽出する */ strncpy(buff, p, strlen(substr)); buff[strlen(substr)] = '\0'; printf("見つかった文字列 = %s\n", buff); p += strlen(substr); } return 0; } ------------------------------------------------------------- ☆☆Sample List 3.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { char array1[] = "漢字文字列"; char array2[] = "漢字文字列"; char array3[] = "文"; int len1 = strlen(array1), len2 = strlen(array3), i; /* strcmp()関数を使って2つのヌル文字付き文字列を比較する */ if (!strcmp(array1, array2)) printf("一致している\n"); else printf("不一致である\n"); /* strncmp()関数を使って指定サイズだけ2つの部分文字列を比較する */ if (!strncmp(array1, array2, strlen(array2))) printf("一致している\n"); else printf("不一致である\n"); /* strncmp()関数を使って部分文字列を検索する */ for (i = 0; i < len1; i++) { if (!strncmp(&array1[i], array3, len2)) break; } /* 検出できていれば表示する */ if (i < len1) printf("%s\n", &array1[i]); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { char array1[] = "#strtok()関数を使えば,#指定した区切り文字をデリミタとして" "#文字列からトークン#(#字句#)#を切り出すことができる."; /* 区切り文字セット */ char cset[] = "#"; char *p = NULL; /* strtok()の初回の呼び出し */ printf("%s\n", strtok(array1, cset)); /* strtok()の2回目以降の呼び出し */ while ((p = strtok(NULL, cset))) { printf("%s\n", p); } return 0; } ------------------------------------------------------------- ☆☆Sample List 3.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } /* 文字を前方検索するStrChr()関数(漢字対応版) */ char *StrChr(const char *str, int c) { int i, len = strlen(str); for (i = 0; i < len; i++) { /* 漢字文字をスキップする */ if (IsKanji1st(str[i])) { i++; continue; } /* 合致していればその文字へのポインタを返す */ if (str[i] == c) /* コンパイラが文句を言うので型を合わせておく */ return (char *)(str + i); } /* 見つからなければNULLを返す */ return NULL; } main () { /* 漢字文字「ッ」の第2バイトは「b」である */ char array1[] = "ステップステップbbb"; int count = 0; char *p = array1; /* strchr()を使って前方検索する */ while ((p = strchr(p, 'b')) != NULL) { count++; p++; } printf("array1に含まれる文字\'b\'の数 = %d\n", count); p = array1; count = 0; /* StrChr()を使って前方検索する */ while ((p = StrChr(p, 'b')) != NULL) { count++; p++; } printf("array1に含まれる文字\'b\'の数 = %d\n", count); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* ここに,IsKanji1st()関数を定義する */ /* 文字セット文字を前方検索するStrPBrk()関数(漢字対応版) */ char *StrPBrk(const char *str, const char*cset) { int i, j, len1 = strlen(str), len2 = strlen(cset); for (i = 0; i < len1; i++) { /* 漢字文字をスキップする */ if (IsKanji1st(str[i])) { i++; continue; } /* csetのいずれかの文字に合致していればその文字へのポインタを返す */ for (j = 0; j < len2; j++) { if (str[i] == cset[j]) /* コンパイラが文句を言うので型を合わせておく */ return (char *)(str + i); } } /* 見つからなければNULLを返す */ return NULL; } main () { /* 漢字文字「ッ」の第2バイトは「b」である */ char array1[] = "ステップステップbbb"; /* 検索用の文字セット */ char cset[] = "abc"; int count = 0; char *p = array1; /* strpbrk()関数を使う */ printf("%s\n", strpbrk(array1, cset)); /* StrPBrk()関数を使う */ printf("%s\n", StrPBrk(array1, cset)); return 0; } ------------------------------------------------------------- ☆☆Sample List 3.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* ここに,IsKanji1st()関数を定義する */ /* ここに,IsKanji2nd()関数を定義する */ /* 部分文字列を検索するStrStr()関数(漢字対応版) */ char *StrStr(const char *str, const char *substr) { size_t len = strlen(substr); int i = 0; /* 1文字の検索で漢字第2バイトと競合するケース */ if (len == 1 && IsKanji2nd(substr[0])) { /* 検索対象文字列の長さが十分であれば */ while (strlen(&str[i]) >= len) { /* 漢字文字なら2バイト前進する */ if (IsKanji1st(str[i])) i += 2; else { if (str[i] == substr[0]) /* 合致した文字列の位置を返す */ return (char *)(str + i); /* 1文字前進する */ i++; } } /* 見つからなければNULLを返す */ return NULL; } /* 競合のないケース */ else return strstr(str, substr); } main () { char array[] = "strstr()関数は,半角アルファベット1文字" "の文字列検索に弱い-AAA"; char *p = NULL; /* 検索用部分文字列 */ char substr[] = "A"; /* 「A」という1文字の文字列を検索する */ /* strstr()関数を使って部分文字列を検索する */ p = strstr(array, substr); if (p != NULL) printf("strstr()関数の検索結果 = %s\n", p); /* StrStr()関数を使って部分文字列を検索する */ p = StrStr(array, substr); if (p != NULL) printf("StrStr()関数の検索結果 = %s\n", p); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { /* ヌル文字付きの数字文字列 */ char array1[] = "123456789"; /* ホワイトスペース付きの文字列 */ char array2[] = "\t\n\v\f\r 123456789"; /* 符号付きの文字列 */ char array3[] = "-11"; /* 末尾が数字文字でない文字列 */ char array4[] = "+2@*"; /* atoi()を使う */ printf("%d %d\n", atoi(array1), atoi(array1) - 123000000); printf("%d %d\n", atoi(array2), atoi(array2) - 789); printf("%d %d\n", atoi(array3), atoi(array3) + 11); printf("%d %d\n", atoi(array4), atoi(array4) - 2); /* atol()を使う */ printf("%d %d\n", atol(array1), atol(array1) - 123000000); printf("%d %d\n", atol(array2), atol(array2) - 789); printf("%d %d\n", atol(array3), atol(array3) + 11); printf("%d %d\n", atol(array4), atol(array4) - 2); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include main () { char array[6]; /* char型のポインタpcharを宣言して, char型のアドレスarrayで初期化する */ char *pchar = array; /* char型ポインタへのポインタppcharを宣言して, char型ポインタpcharのアドレスで初期化する */ char **ppchar = &pchar; /* 2種類の間接参照代入により配列arrayに要素を代入する */ *(*ppchar)++ = 'A'; /* pcharをインクリメントする*/ *(*ppchar)++ = 'B'; *(*ppchar)++ = 'C'; /* pcharを再度設定し直す */ pchar = array; (*ppchar)[3] = 'D'; /* ポインタの添え字用法 */ (*ppchar)[4] = 'E'; (*ppchar)[5] = '\0'; printf("array = %s\n", array); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { char *p; /* ヌル文字付きの数字文字列 */ char array1[] = "123456789"; /* ホワイトスペース付きの文字列 */ char array2[] = "\t\n\v\f\r 0123456789"; /* 符号と「0X」付きの文字列 */ char array3[] = "-0X1f1b"; /* 基数より大きい数字文字が付いた文字列 */ char array4[] = "+02568899@*0123456789"; printf("strtol()を適用した場合\n"); /* 基数自動判定方式でstrtol()を使う */ printf("%d\n", strtol(array1, NULL, 0)); printf("%d\n", strtol(array2, NULL, 0)); /* strtol()の第3引数を指定する */ printf("%d\n", strtol(array3, NULL, 16)); /* strtol()の第2引数を指定する */ printf("%d\n", strtol(array4, &p, 0)); printf("pの指す文字列 = %s\n", p); printf("strtoul()を適用した場合\n"); /* 基数自動判定方式でstrtoul()を使う */ printf("%u\n", strtoul(array1, NULL, 0)); printf("%u\n", strtoul(array2, NULL, 0)); /* strtoul()の第3引数を指定する */ printf("%u\n", strtoul(array3, NULL, 16)); /* strtoul()の第2引数を指定する */ printf("%u\n", strtoul(array4, &p, 0)); printf("pの指す文字列 = %s\n", p); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { char *p; /* ホワイトスペース付き小数点定数の文字列 */ char array1[] = "\t\n\v\f\r 3.141592"; /* 符号付き指数表記の文字列 */ char array2[] = "-3141592E-6"; /* 末尾が数字文字でない文字列 */ char array3[] = "0.3141592653589793238462643383E1ABCDE"; printf("atof()を適用した場合\n"); /* atof()を使う */ printf("%%f: \t\t%f\n", atof(array1)); printf("%%e: \t\t%e\n", atof(array1)); printf("%%.7g: \t\t%.7g\n", atof(array1)); /* atof()を使う */ printf("%%f: \t\t%f\n", atof(array2)); printf("%%e: \t\t%e\n", atof(array2)); printf("%%.7g: \t\t%.7g\n", atof(array2)); /* atof()を使う */ printf("%%f: \t\t%.28f\n", atof(array3)); printf("%%e: \t\t%.28e\n", atof(array3)); printf("%%.28g: \t\t%.28g\n", atof(array3)); printf("strtod()を適用した場合\n"); /* strtod()を使う */ printf("%%f: \t\t%f\n", strtod(array1, NULL)); printf("%%e: \t\t%e\n", strtod(array1, NULL)); printf("%%.7g: \t\t%.7g\n", strtod(array1, NULL)); /* strtod()を使う */ printf("%%f: \t\t%f\n", strtod(array2, NULL)); printf("%%e: \t\t%e\n", strtod(array2, NULL)); printf("%%.7g: \t\t%.7g\n", strtod(array2, NULL)); /* strtod()を使う */ printf("%%.28f: \t\t%.28f\n", strtod(array3, &p)); printf("pの指す文字列 = %s\n", p); printf("%%.28e: \t\t%.28e\n", strtod(array3, &p)); printf("pの指す文字列 = %s\n", p); printf("%%.28g: \t\t%.28g\n", strtod(array3, &p)); printf("pの指す文字列 = %s\n", p); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define BUFF_SIZE 256 /* 文字列変換を行う汎用関数 */ char *GetStr(char *buffer, void *pval, int type) { switch (type) { case 1: /* int *型 */ sprintf(buffer, "%d", *(int *)pval); return buffer; case 2: /* char *型 */ sprintf(buffer, "%s", (char *)pval); return buffer; case 3: /* double *型 */ sprintf(buffer, "%17.16g", *(double *)pval); return buffer; } return NULL; } main () { int n = 200; char array[] = "文字列"; double d = 3.141592653589793; char buff[BUFF_SIZE]; /* int *型としてGetStr()を呼び出す */ printf("n = %s\n", GetStr(buff, &n, 1)); /* char *型としてGetStr()を呼び出す */ printf("array = %s\n", GetStr(buff, array, 2)); /* double *型としてGetStr()を呼び出す */ printf("d = %s\n", GetStr(buff, &d, 3)); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define BUFFSIZE 256 int main(int argc, char *argv[]) { int n; char array[BUFFSIZE + 1]; float f; printf("整数文字列浮動小数点数の順に入力:\n"); /* scanf()を使って,3つのフィールドに変換値を格納する */ scanf("%d %s %f", &n, array, &f); /* int型フィールドの格納値を表示する */ printf("%d\n", n); /* char型文字列フィールドの格納値を表示する */ printf("%s\n", array); /* float型フィールドの格納値を表示する */ printf("%f\n", f); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define SIZE 50 int main(int argc, char *argv[]) { char array1[SIZE]; char array2[SIZE]; int n = 0, total = 0; printf("《累計値計算プログラム》\n" "入力した数値を累計して累計値を表示します.\n\n"); while (1) { /* 数字を文字列として読み取る */ scanf("%s", array1); /* 「Q」または「q」なら終了する */ if (sscanf(array1, "%[Qq]", array2) == 1) return 0; /* 数字文字列をint型整数値に変換する */ if (sscanf(array1, "%d", &n) == 1) { /* 変換値を加算する */ total += n; /* 累計値を表示する */ printf("累計値: %d\n", total); } /* 間違った入力文字が含まれていたケース */ else printf("数値を入力してください." "「Q」または「q」で終了します.\n"); } return 0; } ------------------------------------------------------------- ☆☆Sample List 4.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } int main(int argc, char *argv[]) { FILE *pfile; char *pch = "temp"; char array[] = "3.141592"; /* ファイルを書き込みモードで開く */ if ((pfile = fopen(pch, "w")) == NULL) OperationError("出力ファイルを開けませんでした.\n"); /* fprintf()を使って,配列arrayの文字列 を浮動小数点数に変換して保存する */ fprintf(pfile, "%f", atof(array)); /* ファイルを閉じる */ fclose(pfile); /* ファイルを読み込みモードで開く */ if ((pfile = fopen(pch, "r")) == NULL) OperationError("入力ファイルを開けませんでした.\n"); /* 配列arrayを消去する */ array[0] = '\0'; /* fscanf()を使って,浮動小数点数を 文字列に変換してarrayに読み取る */ fscanf(pfile, "%s", array); /* arrayの文字列を表示する */ printf("array = %s\n", array); /* ファイルを閉じる */ fclose(pfile); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.9☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #define BUFF_SIZE 256 /* 文字列変換を行う汎用関数 */ char *GetStr(char *buffer, void *pval, int type) { switch (type) { case 1: /* int *型 */ sprintf(buffer, "%d", *(int *)pval); return buffer; case 2: /* char *型 */ sprintf(buffer, "%s", (char *)pval); return buffer; case 3: /* double *型 */ sprintf(buffer, "%17.16g", *(double *)pval); return buffer; } return NULL; } main () { int n = 200; char array[] = "文字列"; double d = 3.141592653589793; char buff[BUFF_SIZE]; /* GetStr()を使ってbuffに文字列を生成する */ printf("n = %s\n", GetStr(buff, &n, 1)); /* nをクリアする */ printf("n = %d\n", n = 0); /* sscanf()を使ってbuffからnに整数値を生成する */ sscanf(buff, "%d", &n); printf("n = %d\n", n); /* GetStr()を使ってbuffに文字列を生成する */ printf("array = %s\n", GetStr(buff, array, 2)); /* 配列arrayをクリアする */ printf("array = %s\n", strcpy(array, "")); /* sscanf()を使ってbuffからarrayに文字列を生成する */ sscanf(buff, "%s", array); printf("array = %s\n", array); /* GetStr()を使ってbuffに文字列を生成する */ printf("d = %s\n", GetStr(buff, &d, 3)); /* dをクリアする */ printf("d = %17.16g\n", d = 0); /* sscanf()を使ってbuffからdに浮動小数点数を生成する */ sscanf(buff, "%lf", &d); printf("d = %17.16g\n", d); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.10☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* 記号定数を定義する */ #define ARRAYSIZE 10 /* 10進の数字文字を1桁の数値に変換する関数 */ int ToDigitVal(int c) { /* 10進の数字文字であれば1桁の数値に変換する */ if (c >= 0x30 && c <= 0x39) return (c - '0'); else return c; } /* 1桁の数値を10進の数字文字に変換する関数 */ int ToDigitNum(int c) { /* 1桁の数値であれば10進の数字文字に変換する */ if (c >= 0 && c <= 9) return (c + '0'); else return c; } /* 数字文字列をlong型数値に変換する関数(非数字文字バージョン) */ long StrToL(const char *str) { long lval = 0; int i = 0; int flag = 0; /* ホワイトスペース文字をスキップする */ while (isspace(str[i])) i++; /* マイナス符号を拾う */ if (str[i] == '-') { flag = 1; i++; } /* プラス符号を拾う */ else if (str[i] == '+') i++; while (isdigit(str[i])) { lval *= 10; /* ToDigitVal()関数を使って変換する */ lval += ToDigitVal(str[i++]); } /* 符号を数値に反映する */ if (flag) return -lval; else return lval; } /* long型数値を数字文字列に変換する関数(符号認識バージョン) */ int LToStr(long lval, char *str, size_t n) { int dval, index = 0, maxcolumn = 1000000000; unsigned int maxcol = 10; int flag = 0; /* 負の値を絶対値変換する */ if (lval < 0) { flag = 1; /* 絶対値に変換する */ lval = abs(lval); } /* 10進の総桁数を求める */ while (maxcolumn) { if (lval >= maxcolumn) { break; } maxcol--; maxcolumn /= 10; } /* バッファサイズが足りるかどうか(ヌル文字を含む) */ if (flag) { if (maxcol + 2 > n) /* 失敗した */ return 1; /* マイナス符号を付ける */ str[index++] = '-'; } else if (maxcol + 1 > n) /* 失敗した */ return 1; /* 上位桁から数字文字に変換する */ while (maxcolumn) { /* 上桁の10進の桁値を求める */ dval = lval / maxcolumn; /* ToDigitNum()関数を使って変換する */ str[index++] = ToDigitNum(dval); /* 上桁を削除する */ lval -= dval * maxcolumn; /* 下位桁に移行する */ maxcolumn /= 10; } /* 文字列を完成させる */ str[index] = '\0'; /* 成功した */ return 0; } main () { char carray1[] = "\t\n\v\f\r -123456789@*"; char carray2[ARRAYSIZE + 1] = ""; long lval; /* StrToL()関数が生成した値を表示する */ printf("StrToL()関数が生成した値 = %d\n", lval = StrToL(carray1)); /* LToStr()関数を使って数字文字列を生成する */ if (!LToStr(lval, carray2, ARRAYSIZE + 1)) /* LToStr()関数が生成した数字文字列を表示する */ printf("LToStr()関数が生成した文字列 = %s\n", carray2); return 0; } ------------------------------------------------------------- ☆☆Sample List 4.11☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include /* 間違った仮引数用法のTestFunc1()関数定義 */ void TestFunc1(char **ppch, char *pch) { /* 引数のコピーである仮引数に引数のコピーのアドレスを代入する */ ppch = &pch; } /* ポインタの参照先を変更する正しいTestFunc2()関数定義 */ void TestFunc2(char **ppch, char *pch) { /* 引数のコピーの参照先に引数のコピーの保持情報を代入する */ *ppch = pch; } main () { char ch1 = 'A'; char ch2 = 'B'; char *pch1 = &ch1; char *pch2 = &ch2; char **ppch = &pch2; /* 最初の5つの変数の状態 */ printf("ch1 = %c\n", ch1); printf("ch2 = %c\n", ch2); printf("*pch1 = %c\n", *pch1); printf("*pch2 = %c\n", *pch2); printf("**ppch = %c\n", **ppch); TestFunc1(ppch, pch1); printf("TestFunc1()関数呼び出しの後\n"); /* TestFunc1()関数呼び出し後の5つの変数の状態 */ printf("ch1 = %c\n", ch1); printf("ch2 = %c\n", ch2); printf("*pch1 = %c\n", *pch1); printf("*pch2 = %c\n", *pch2); printf("**ppch = %c\n", **ppch); TestFunc2(ppch, pch1); printf("TestFunc2()関数呼び出しの後\n"); /* TestFunc2()関数呼び出し後の5つの変数の状態 */ printf("ch1 = %c\n", ch1); printf("ch2 = %c\n", ch2); printf("*pch1 = %c\n", *pch1); printf("*pch2 = %c\n", *pch2); printf("**ppch = %c\n", **ppch); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* 1/2バイトを16進文字に変換する関数 */ unsigned char HalfToHex(int x) { static unsigned char str[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /* 下位4ビットのマスクをかける */ x &= 0x0f; return str[x]; } /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } int main(int argc, char *argv[]) { FILE *pfile; int n, count = 0; /* ヘルプを表示する */ if (argc > 3 || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")) { OperationError("Dumpプログラム\n\n" "起動方法:Dump 入力ファイル名 [ > 出力ファイル名]\n"); } /* バイナリ読み取りモードでファイルを開く */ if ((pfile = fopen(argv[1], "rb")) == NULL) OperationError("入力ファイルを開けませんでした.\n"); /* EOFを返すまで変換を繰り返す */ while ((n = fgetc(pfile)) != EOF) { /* 上位4ビットを16進文字に変換出力する(標準出力) */ fputc(HalfToHex((n & 0xf0) >> 4), stdout); /* 下位4ビットを16進文字に変換出力する(標準出力) */ fputc(HalfToHex(n & 0x0f), stdout); /* 半角スペースを出力する(標準出力) */ fputc(' ', stdout); /* 見やすくするためのコラム調整 */ if (!(++count % 24)) /* \nを出力する(標準出力) */ fputc('\n', stdout); else if (!(count % 8)) /* 半角スペースを出力する(標準出力) */ fputc(' ', stdout); } /* ファイルを閉じる */ fclose(pfile); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } main () { int n; /* getchar()とputchar()を使ったフィルタプログラムの原型 */ while ((n = getchar()) != EOF) { /* 漢字文字を読み飛ばす */ if (IsKanji1st(n)) { putchar(n); n = getchar(); putchar(n); continue; } /*******************************************/ /* フィルタ処理コード記述箇所 */ putchar(n); /*******************************************/ } return 0; } ------------------------------------------------------------- ☆☆Sample List 5.3☆☆(注意!) ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include unsigned char HalfToHex(int x) { static unsigned char str[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /* 下位4ビットのマスクをかける */ x &= 0x0f; return str[x]; } main () { int n; while ((n = getchar()) != EOF) { putchar(HalfToHex((n & 0xf0) >> 4)); putchar(HalfToHex(n & 0x0f)); putchar(' '); } return 0; } ------------------------------------------------------------- ☆☆Sample List 5.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #define BUFF_SIZE 1024 /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } int main(int argc, char *argv[]) { FILE *pfile1; FILE *pfile2; char *pch1, *pch2; char buff[BUFF_SIZE]; size_t ret; /* 用法を検証してヘルプを表示する */ if (argc < 3 || argc > 3 || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")) { OperationError("Copyプログラム\n\n" "起動方法:Copy 入力ファイル名 出力ファイル名" " [> オプションのファイル名]\n"); } pch1 = argv[1]; pch2 = argv[2]; /* バイナリ読み取りモードで開く */ if ((pfile1 = fopen(pch1, "rb")) == NULL) OperationError("入力ファイルを開けませんでした.\n"); /* バイナリ書き込みモードで開く */ if ((pfile2 = fopen(pch2, "wb")) == NULL) OperationError("出力ファイルを開けませんでした.\n"); /* ファイル末尾までコピーする */ while (!feof(pfile1)) { ret = fread(buff, sizeof(char), sizeof(buff)/sizeof(char), pfile1); if (fwrite(buff, sizeof(char), ret, pfile2) != ret) { OperationError("ファイル出力に失敗しました.\n"); } if (ret < sizeof(buff)/sizeof(char)) break; } /* ファイルを閉じる */ fclose(pfile1); /* fclose(pfile2); <--- これは,freopen()関数が代行するので不要 */ /* freopen()を使ってpfile2ストリームを閉じ, テキスト読み取りモードで開き直す */ if ((freopen(pch2, "r", pfile2)) == NULL) OperationError("再入力ファイルを開けませんでした.\n"); /* pfile2をファイル末尾まで読み取り標準出力する */ while (!feof(pfile2)) { ret = fread(buff, sizeof(char), sizeof(buff)/sizeof(char), pfile2); if (fwrite(buff, sizeof(char), ret, stdout) != ret) { OperationError("標準出力に失敗しました.\n"); } if (ret < sizeof(buff)/sizeof(char)) break; } /* ファイルを閉じる */ fclose(pfile2); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #define ARRAYSIZE 8 /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } /* 商品在庫管理用のINVENTORY構造体定義 */ typedef struct inventory { /* 商品番号 */ int bumber; /* 商品名 */ char *name; /* 在庫数量 */ int volume; /* 仕入れ日数 */ int leadtime; } INVENTORY; /* 商品在庫を表示する */ void DispInventory(INVENTORY *ip) { printf("商品名:%s\n", ip->name); printf("商品番号:%d ", ip->bumber); printf("在庫数量:%d ", ip->volume); printf("仕入れ日数:%d\n", ip->leadtime); printf("------------------\n"); } main () { int i; FILE *ptemp; /* fgetpos()とfsetpos()が使う */ fpos_t save; /* tmpnam()が使う */ char buff[L_tmpnam]; /* レコード情報を格納するINVENTORY構造体型の配列 */ INVENTORY ia[ARRAYSIZE]; /* 1レコード読み取り用 */ INVENTORY work; INVENTORY *ip = ia, *ip2 = NULL; /* 構造体初期化用のデータ */ int array1[] = {154100, 154110, 113700, 113701, 213220, 213222, 503230, 503231}; char *array2[] = { "がんこな汚れも,すっかりクリーン", "がんこな汚れも,すっかりクリーン(抗菌タイプ)", "しつこい汚れに,しっかりクリーン", "しつこい汚れに,しっかりクリーン(抗菌タイプ)", "とれない汚れに,これでもか!クリーン", "とれない汚れに,これでもか!クリーン(抗菌タイプ)", "また付く汚れに,どれどれ!クリーン", "また付く汚れに,どれどれ!クリーン(抗菌タイプ)", }; int array3[] = {12300, 11500, 2800, 2200, 6400, 5300, 7600, 7000}; int array4[] = {6, 6, 20, 20, 6, 6, 8, 8}; /* INVENTORYリストを初期化する */ for (i = 0; i < ARRAYSIZE; i++, ip++) { ip->bumber = array1[i]; ip->name = array2[i]; ip->volume = array3[i]; ip->leadtime = array4[i]; } /*/////////////////////////////////////*/ /* INVENTORYリストを表示する */ /* for (ip = ia; ip < ia + ARRAYSIZE; ip++) DispInventory(ip); */ /*/////////////////////////////////////*/ /* 一時ファイル名を生成する */ tmpnam(buff); /* 一時ファイル名を表示する */ printf("%s\n", buff); /* バイナリ読み取り書き込みモードで開く */ if ((ptemp = fopen(buff, "wb+")) == NULL) OperationError("入出力ファイルを開けませんでした.\n"); /* INVENTORYリストをファイルに格納する */ fwrite(ia, sizeof(INVENTORY), ARRAYSIZE, ptemp); /* 位置インジケータを先頭に戻す */ rewind(ptemp); /* 第1レコードから第3レコードまでを表示する */ for (i = 0; i < ARRAYSIZE - 5; i++) { fread(&work, sizeof(INVENTORY), 1, ptemp); DispInventory(&work); } /* 現在位置をsaveに保存する(これは第4レコードを意味する) */ fgetpos(ptemp, &save); /* 第5レコードを表示する(先頭基準) */ if (fseek(ptemp, 4 * sizeof(INVENTORY), SEEK_SET)) OperationError("ファイルのシークに失敗しました."); fread(&work, sizeof(INVENTORY), 1, ptemp); DispInventory(&work); /* saveの保存位置に移動する */ fsetpos(ptemp, &save); /* saveの保存位置の第4レコードを表示する */ fread(&work, sizeof(INVENTORY), 1, ptemp); DispInventory(&work); /* 第3レコードを表示する(現在位置基準) */ if (fseek(ptemp, -2 * (signed long)sizeof(INVENTORY), SEEK_CUR)) OperationError("ファイルのシークに失敗しました."); fread(&work, sizeof(INVENTORY), 1, ptemp); DispInventory(&work); /* 末尾レコードを表示する(終端基準) */ if (fseek(ptemp, -(signed long)sizeof(INVENTORY), SEEK_END)) OperationError("ファイルのシークに失敗しました."); fread(&work, sizeof(INVENTORY), 1, ptemp); DispInventory(&work); /* 一時ファイルを閉じる */ fclose(ptemp); /* 一時ファイルを削除する */ remove(buff); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include #include #define LINE_SIZE 80 /* 指定時間待機する独自のSleep()関数 */ void Sleep(int count) { /* 現在の経過時間 */ clock_t t = clock() * (1000/CLOCKS_PER_SEC); /* 終了用の経過時間 */ clock_t tterm = t + count; /* 終了用の経過時間までループする */ while (t < tterm) { t = clock() * (1000/CLOCKS_PER_SEC); /* tが(clock_t)-1でないことを診断する */ assert(t != (clock_t)-1); } } main () { int i; char fbuff[BUFSIZ * 2]; char lbuff[LINE_SIZE]; /* _IONBF(バッファなし)に設定する */ if (setvbuf(stdout, NULL, _IONBF, 0)) exit(1); printf("バッファなしに設定%c\n", 0x07); for (i = 0; i < 150; i++) { if (!((i + 1) % 15)) { printf("test\n"); Sleep(10); } else { printf("test "); Sleep(10); } } printf("\n"); /* バッファをフラッシュする */ fflush(stdout); /* _IOLBF(行バッファリング)に設定する */ printf("行バッファリングに設定%c\n", 0x07); if (setvbuf(stdout, lbuff, _IOLBF, LINE_SIZE)) exit(1); for (i = 0; i < 150; i++) { if (!((i + 1) % 15)) { printf("test\n"); Sleep(10); } else { printf("test "); Sleep(10); } } printf("\n"); /* バッファをフラッシュする */ fflush(stdout); /* _IOFBF(フルバッファリング)に設定する */ printf("フルバッファリングに設定%c\n", 0x07); if (setvbuf(stdout, fbuff, _IOFBF, BUFSIZ * 2)) exit(1); for (i = 0; i < 150; i++) { if (!((i + 1) % 15)) { printf("test\n"); Sleep(10); } else { printf("test "); Sleep(10); } } printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } /* 漢字第1文字を判定する関数 */ int IsKanji1st(int c) { /* 漢字文字列のchar型文字も取り扱えるようunsigned char型に変換する */ unsigned char uch = c; /* 漢字第1バイトかどうかを検証する */ if (uch >= 0x81 && uch <= 0x9f || uch >= 0xe0 && uch <= 0xfc) return 1; else return 0; } /* 文字列中の半角大文字を小文字に変換する関数 */ char *ToLowerStr(char *str) { int i; int len = strlen(str); for (i = 0; i < len; i++) { /* 漢字第1バイトを検証する */ if (IsKanji1st(str[i])) { i++; continue; } /* 大文字なら小文字に変換する */ if (isupper(str[i])) str[i] = tolower(str[i]); } return str; } /* 文字列中の半角小文字を大文字に変換する関数 */ char *ToUpperStr(char *str) { int i; int len = strlen(str); for (i = 0; i < len; i++) { /* 漢字第1バイトを検証する */ if (IsKanji1st(str[i])) { i++; continue; } /* 小文字なら大文字に変換する */ if (islower(str[i])) str[i] = toupper(str[i]); } return str; } int main(int argc, char *argv[]) { char buff[BUFSIZ]; char *pchar; int status = 0; /* ヘルプを表示する */ if (argc > 3 || argc == 1 || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")) { OperationError("大文字/小文字変換プログラム\n\n" "起動方法:ULConv Para [< 入力ファイル名 [> 出力ファイル名]]\n" "Para U:大文字変換 L:小文字変換\n"); } if (tolower(*argv[1]) == 'u') status = 1; else if (tolower(*argv[1]) == 'l') status = 2; else OperationError("大文字/小文字変換プログラム\n\n" "起動方法:ULConv Para [< 入力ファイル名 [> 出力ファイル名]]\n" "Para U:大文字変換 L:小文字変換\n"); /* gets()とputs()関数を使ったフィルタ処理 */ while ((pchar = gets(buff)) != NULL) if (status == 1) puts(ToUpperStr(pchar)); else puts(ToLowerStr(pchar)); return 0; } ------------------------------------------------------------- ☆☆Sample List 5.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* ここに,Sample List 5.7と同じく,OperationError(),IsKanji1st(), ToLowerStr(),ToUpperStr()の4つの関数を定義する */ int main(int argc, char *argv[]) { char buff[BUFSIZ]; char *pchar; int status = 0; /* ヘルプを表示する */ if (argc > 3 || argc == 1 || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")) { OperationError("大文字/小文字変換プログラム\n\n" "起動方法:ULConv2 Para [< 入力ファイル名 [> 出力ファイル名]]\n" "Para U:大文字変換 L:小文字変換\n"); } if (tolower(*argv[1]) == 'u') status = 1; else if (tolower(*argv[1]) == 'l') status = 2; else OperationError("大文字/小文字変換プログラム\n\n" "起動方法:ULConv2 Para [< 入力ファイル名 [> 出力ファイル名]]\n" "Para U:大文字変換 L:小文字変換\n"); /* fgets()とfputs()関数を使ったフィルタ処理 */ while ((pchar = fgets(buff, BUFSIZ, stdin)) != NULL) if (status == 1) fputs(ToUpperStr(pchar), stdout); else fputs(ToLowerStr(pchar), stdout); return 0; } ------------------------------------------------------------- ☆☆Sample List 6.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include /* 要素の小なり比較を行う比較関数(char型バージョン) */ int CharFuncLess(const void *key, const void *element) { /* char型として,key > elementの比較を行う */ return *(char *)key - *(char *)element; } /* 要素の大なり比較を行う比較関数(char型バージョン) */ int CharFuncGreater(const void *key, const void *element) { /* char型として,key < elementの比較を行う */ return *(char *)element - *(char *)key; } /* 要素の小なり比較を行う比較関数(int型バージョン) */ int IntFuncLess(const void *key, const void *element) { /* int型として,key > elementの比較を行う */ return *(int *)key - *(int *)element; } /* 要素の大なり比較を行う比較関数(int型バージョン) */ int IntFuncGreater(const void *key, const void *element) { /* int型として,key < elementの比較を行う */ return *(int *)element - *(int *)key; } main () { char ch1 = 'A', ch2 = 'B'; int n1 = 100, n2 = 200; /* 関数ポインタfuncを宣言する */ int (*func)(const void *key, const void *element); /* funcに,CharFuncLess()関数のアドレスを代入する */ func = CharFuncLess; /* 関数ポインタを使ってCharFuncLess()を呼び出す */ if (func(&ch1, &ch2) > 0) printf("比較結果は正である\n"); else printf("比較結果は正でない\n"); /* funcに,CharFuncGreater()関数のアドレスを代入する */ func = CharFuncGreater; /* 関数ポインタを使ってCharFuncGreater()を呼び出す */ if (func(&ch1, &ch2) > 0) printf("比較結果は正である\n"); else printf("比較結果は正でない\n"); /* funcに,IntFuncLess()関数のアドレスを代入する */ func = IntFuncLess; /* 関数ポインタを使ってIntFuncLess()を呼び出す */ if (func(&n1, &n2) > 0) printf("比較結果は正である\n"); else printf("比較結果は正でない\n"); /* funcに,IntFuncGreater()関数のアドレスを代入する */ func = IntFuncGreater; /* 関数ポインタを使ってIntFuncGreater()を呼び出す */ if (func(&n1, &n2) > 0) printf("比較結果は正である\n"); else printf("比較結果は正でない\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 6.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include /* 要素の小なり比較を行う比較関数(char型バージョン) */ int CharFuncLess(const void *key, const void *element) { /* char型として,key > elementの比較を行う */ return *(char *)key - *(char *)element; } /* 要素の大なり比較を行う比較関数(char型バージョン) */ int CharFuncGreater(const void *key, const void *element) { /* char型として,key < elementの比較を行う */ return *(char *)element - *(char *)key; } /* 要素の小なり比較を行う比較関数(int型バージョン) */ int IntFuncLess(const void *key, const void *element) { /* int型として,key > elementの比較を行う */ return *(int *)key - *(int *)element; } /* 要素の大なり比較を行う比較関数(int型バージョン) */ int IntFuncGreater(const void *key, const void *element) { /* int型として,key < elementの比較を行う */ return *(int *)element - *(int *)key; } /* 関数ポインタ型の仮引数を持つShowCompResult()関数の定義 */ void ShowCompResult(const void *key, const void *element, int (*func)(const void *key, const void *element)) { /* 関数ポインタ仮引数を使って関数を呼び出す */ if (func(key, element) > 0) printf("比較結果は正である\n"); else printf("比較結果は正でない\n"); } main () { char ch1 = 'A', ch2 = 'B'; int n1 = 100, n2 = 200; /* 関数ポインタfuncを宣言する */ /* int (*func)(const void *key, const void *element); */ /* funcに,CharFuncLess()関数のアドレスを代入する */ /* func = CharFuncLess; */ /* 関数ポインタを使ってCharFuncLess()を呼び出す */ ShowCompResult(&ch1, &ch2, CharFuncLess); /* funcに,CharFuncGreater()関数のアドレスを代入する */ /* func = CharFuncGreater; */ /* 関数ポインタを使ってCharFuncGreater()を呼び出す */ ShowCompResult(&ch1, &ch2, CharFuncGreater); /* funcに,IntFuncLess()関数のアドレスを代入する */ /* func = IntFuncLess; */ /* 関数ポインタを使ってIntFuncLess()を呼び出す */ ShowCompResult(&n1, &n2, IntFuncLess); /* funcに,IntFuncGreater()関数のアドレスを代入する */ /* func = IntFuncGreater; */ /* 関数ポインタを使ってIntFuncGreater()を呼び出す */ ShowCompResult(&n1, &n2, IntFuncGreater); return 0; } ------------------------------------------------------------- ☆☆Sample List 6.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { char key; int n = 0; printf("《サイコロプログラム》\n" "Enterキーを押せばサイコロの目を出します.【Q = 終了】\n"); /* 疑似乱数ジェネレータを初期化する */ srand(time(NULL)); /* 入力文字を読み取る */ while (scanf("%c", &key) != EOF) { /* 終了する */ if (key == 'Q' || key == 'q') { /* Enterキーの読み飛ばし */ scanf("%*c"); return 0; } /* その他のキーでも終了する */ if (key != '\n') { /* その他キーの読み飛ばし */ scanf("%*c"); return 0; } /* サイコロの目になるまで疑似乱数生成を繰り返す */ while ((n = rand()) > 6 || n == 0) ; /* サイコロの目を表示する */ printf("サイコロの目: %d\n", n); printf("Enterキーを押せばサイコロの目を出します.【Q = 終了】\n"); } return 0; } ------------------------------------------------------------- ☆☆Sample List 6.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* 要素の小なり比較を行う比較関数(char型バージョン) */ int CharFuncLess(const void *key, const void *element) { return *(char *)key - *(char *)element; } /* 要素の大なり比較を行う比較関数(char型バージョン) */ int CharFuncGreater(const void *key, const void *element) { return *(char *)element - *(char *)key; } /* 要素の小なり比較を行う比較関数(int型バージョン) */ int IntFuncLess(const void *key, const void *element) { return *(int *)key - *(int *)element; } /* 要素の大なり比較を行う比較関数(int型バージョン) */ int IntFuncGreater(const void *key, const void *element) { return *(int *)element - *(int *)key; } /* 要素の小なり比較を行う比較関数(double型バージョン) */ int DblFuncLess(const void *key, const void *element) { if (*(double *)key - *(double *)element > 0) return 1; else if (*(double *)key - *(double *)element < 0) return -1; else return 0; /* この記述は間違いである! return (int)(*(double *)key - *(double *)element); */ } /* 要素の大なり比較を行う比較関数(double型バージョン) */ int DblFuncGreater(const void *key, const void *element) { if (*(double *)element - *(double *)key > 0) return 1; else if (*(double *)element - *(double *)key < 0) return -1; else return 0; /* この記述は間違いである! return (int)(*(double *)element - *(double *)key); */ } /* 文字列の値の小なり比較を行う比較関数 */ int StrFuncLess(const void *key, const void *element) { int len1 = strlen((char *)key); int len2 = strlen((char *)element); int worklen = len1 < len2? len1:len2; return strncmp((char *)key, (char *)element, worklen); } /* 文字列の値の大なり比較を行う比較関数 */ int StrFuncGreater(const void *key, const void *element) { int len1 = strlen((char *)key); int len2 = strlen((char *)element); int worklen = len1 < len2? len1:len2; return strncmp((char *)element, (char *)key, worklen); } /* 長さを優先して,文字列の長さと値の小なり比較を行う比較関数 */ int StrlenFuncLess(const void *key, const void *element) { int worklen = strlen((char *)element); int len = strlen((char *)key) - worklen; if (len == 0) return strncmp((char *)key, (char *)element, worklen); else return len; } /* 長さを優先して,文字列の長さと値の大なり比較を行う比較関数 */ int StrlenFuncGreater(const void *key, const void *element) { int worklen = strlen((char *)key); int len = strlen((char *)element) - worklen; if (len == 0) return strncmp((char *)element, (char *)key, worklen); else return len; } main () { int i; char array[] = "BAJDEFICHG"; int narray[] = {300, 400, 100, 600, 200, 500}; double darray[] = {44.323, 2.55, 72.445, 11.333, 8.088}; char str[5][7] = {"ABCF", "ABADFG", "ACFHF", "AGB", "ABAFAG"}; /* char型の配列arrayを昇順に分類する */ qsort(array, sizeof(array) -1, sizeof(char), CharFuncLess); array[sizeof(array)] = '\0'; /* 配列の内容を表示する */ printf("array = %s\n", array); /* char型の配列arrayを降順に分類する */ qsort(array, sizeof(array) -1, sizeof(char), CharFuncGreater); /* 配列の内容を表示する */ array[sizeof(array)] = '\0'; printf("array = %s\n", array); /* int型の配列narrayを昇順に分類する */ qsort(narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncLess); /* 配列の内容を表示する */ printf("narray = "); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%d ", narray[i]); printf("\n"); /* int型の配列narrayを降順に分類する */ qsort(narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncGreater); /* 配列の内容を表示する */ printf("narray = "); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%d ", narray[i]); printf("\n"); /* double型の配列darrayを昇順に分類する */ qsort(darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncLess); /* 配列の内容を表示する */ printf("darray = "); for (i = 0; i < sizeof(darray)/sizeof(double); i++) printf("%f ", darray[i]); printf("\n"); /* double型の配列darrayを降順に分類する */ qsort(darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncGreater); /* 配列の内容を表示する */ printf("darray = "); for (i = 0; i < sizeof(darray)/sizeof(double); i++) printf("%f ", darray[i]); printf("\n"); /* char型文字列を昇順に分類する */ qsort(str, 5, 7, StrFuncLess); printf("内容優先の昇順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を降順に分類する */ qsort(str, 5, 7, StrFuncGreater); printf("内容優先の降順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を長さ優先で昇順に分類する */ qsort(str, 5, 7, StrlenFuncLess); printf("長さ優先の昇順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を長さ優先で降順に分類する */ qsort(str, 5, 7, StrlenFuncGreater); printf("長さ優先の降順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 6.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* ここに,Sample List 6.4のCharFuncLess(),IntFuncLess(), DblFuncLess(),StrFuncLess()の4つの関数を定義する */ main () { char array[] = "BAJDEFICHG"; int narray[] = {300, 400, 100, 600, 200, 500}; double darray[] = {44.323, 2.55, 72.445, 11.333, 8.088}; char str[5][7] = {"ABCF", "ABADFG", "ACFHF", "AGB", "ABAFAG"}; char ch = 'F'; char *pch; int n = 600; int *pn; double db = 2.55; double *pdb; char *pchar = "ACFHF"; /*///////////////////////////////////////////*/ /* char型の配列arrayを昇順にソートする */ qsort(array, sizeof(array) -1, sizeof(char), CharFuncLess); array[sizeof(array)] = '\0'; /* bsearch()を使って,「F」を2分探索する */ pch = (char *)bsearch((char *)&ch, array, sizeof(array) -1, sizeof(char), CharFuncLess); if (pch) printf("検出した文字 = %c\n", *pch); /* bsearch()を使って,「f」を2分探索する */ ch = 'f'; pch = (char *)bsearch((char *)&ch, array, sizeof(array) -1, sizeof(char), CharFuncLess); if (pch) printf("検出した文字 = %c\n", *pch); else printf("「%c」は見つからない\n", ch); /*///////////////////////////////////////////*/ /*///////////////////////////////////////////*/ /* int型の配列narrayを昇順にソートする */ qsort(narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncLess); /* bsearch()を使って,「600」を2分探索する */ pn = (int *)bsearch((int *)&n, narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncLess); if (pn) printf("検出した値 = %d\n", *pn); /* bsearch()を使って,「800」を2分探索する */ n = 800; pn = (int *)bsearch((int *)&n, narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncLess); if (pn) printf("検出した値 = %d\n", *pn); else printf("「%d」は見つからない\n", n); /*///////////////////////////////////////////*/ /*///////////////////////////////////////////*/ /* double型の配列darrayを昇順にソートする */ qsort(darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncLess); /* bsearch()を使って,「2.55」を2分探索する */ pdb = (double *)bsearch((double *)&db, darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncLess); if (pdb) printf("検出した値 = %lf\n", *pdb); /* bsearch()を使って,「3.141」を2分探索する */ db = 3.141; pdb = NULL; pdb = (double *)bsearch((double *)&db, darray, 5/*sizeof(darray)/sizeof(double)*/, sizeof(double), DblFuncLess); if (pdb) printf("検出した値 = %lf\n", *pdb); else printf("「%lf」は見つからない\n", db); /*///////////////////////////////////////////*/ /*///////////////////////////////////////////*/ /* char型文字列の配列strを昇順にソートする */ qsort(str, 5, 7, StrFuncLess); /* bsearch()を使って,「"ACFHF"」を2分探索する */ pch = (char *)bsearch((char *)pchar, str, 5, 7, StrFuncLess); if (pch) printf("検出した値 = %s\n", pch); /* bsearch()を使って,「"BBB"」を2分探索する */ pchar = "BBB"; pch = (char *)bsearch((char *)pchar, str, 5, 7, StrFuncLess); if (pch) printf("検出した値 = %s\n", pch); else printf("「%s」は見つからない\n", pchar); /*///////////////////////////////////////////*/ return 0; } ------------------------------------------------------------- ☆☆Sample List 6.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include /* 汎用型の要素シーケンスを昇順にソートするクイックソート関数 */ void QASort(void *base, size_t n, size_t size) { char temp; unsigned int i; /* 先頭要素の位置 */ char *forward = (char *)base; /* 末尾要素の位置 */ char *backward = (char *)((char *)base + (n - 1) * size); /* 軸(pivot)を最後の要素とする */ char *pivot = backward; /* backwardを1要素分後退する */ backward -= size; /* 要素が1個なら終了する */ if (n < 2) return; /* 要素をpivotを基準にして,左側に小のグループ, 右側に大のグループと振り分ける */ while (1) { /* 小グループならforwardを前進する */ while (*forward < *pivot) forward += size; /* 大グループならbackwardを後退する */ while (*pivot < *backward) backward -= size; /* forwardがbackwardと合流していれば配置換えを終える */ if (forward >= backward) break; /* forwardが前進できずbackwardが後退できないので,forward要素と backward要素は共にpivotに対し逆の大小関係にある */ /* forward要素とbackward要素を交換する */ for (i = 0; i < size; i++) { temp = forward[i]; forward[i] = backward[i]; backward[i] = temp; } forward += size; backward -= size; } /* pivot要素を所定の位置に置く */ for (i = 0; i < size; i++) { temp = pivot[i]; pivot[i] = forward[i]; forward[i] = temp; } /* 左側をソートする */ QASort(base, (forward - (char *)base)/ size, size); /* 右側をソートする */ QASort(forward, n - (forward - (char *)base)/ size, size); } main () { char array[] = "BAJDEFICHG"; /* 配列の内容を表示する */ printf("array = %s\n", array); /* char型の配列arrayを昇順にソートする */ QASort(array, sizeof(array) -1, sizeof(char)); array[sizeof(array)] = '\0'; /* 配列の内容を表示する */ printf("array = %s\n", array); return 0; } ------------------------------------------------------------- ☆☆Sample List 6.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* 比較関数を使って汎用型シーケンスをソートするクイックソート関数 */ void QSort(void *base, size_t n, size_t size, int (*fcomp)(const void *key, const void *element)) { char temp; unsigned int i; /* 先頭要素の位置 */ char *forward = (char *)base; /* 末尾要素の位置 */ char *backward = (char *)((char *)base + (n - 1) * size); /* 軸(pivot)を最後の要素とする */ char *pivot = backward; /* backwardを1要素分後退する */ backward -= size; /* 要素が1個なら終了する */ if (n < 2) return; /* 要素をpivotを基準にして,左側に小のグループ, 右側に大のグループと振り分ける */ while (1) { /* 小グループならforwardを前進する */ while (fcomp(forward, pivot) < 0) forward += size; /* 大グループならbackwardを後退する */ while (fcomp(pivot, backward) < 0) backward -= size; /* forwardがbackwardと合流していれば配置換えを終える */ if (forward >= backward) break; /* forwardが前進できずbackwardが後退できないので,forward要素と backward要素は共にpivotに対し逆の大小関係にある */ /* forward要素とbackward要素を交換する */ for (i = 0; i < size; i++) { temp = forward[i]; forward[i] = backward[i]; backward[i] = temp; } forward += size; backward -= size; } /* pivot要素を所定の位置に置く */ for (i = 0; i < size; i++) { temp = pivot[i]; pivot[i] = forward[i]; forward[i] = temp; } /* 左側をソートする */ QSort(base, (forward - (char *)base)/ size, size, fcomp); /* 右側をソートする */ QSort(forward, n - (forward - (char *)base)/ size, size, fcomp); } /* ここに,Sample List 6.4の以下の比較関数を定義する CharFuncLess(),CharFuncGreater(),IntFuncLess(), IntFuncGreater(),DblFuncLess(),DblFuncGreater(), StrFuncLess(),StrFuncGreater(),StrlenFuncLess(), StrlenFuncGreater() */ main () { int i; char array[] = "BAJDEFICHG"; int narray[] = {300, 400, 100, 600, 200, 500}; double darray[] = {44.323, 2.55, 72.445, 11.333, 8.088}; char str[5][7] = {"ABCF", "ABADFG", "ACFHF", "AGB", "ABAFAG"}; /* char型の配列arrayを昇順にソートする */ QSort(array, sizeof(array) -1, sizeof(char), CharFuncLess); array[sizeof(array)] = '\0'; /* 配列の内容を表示する */ printf("array = %s\n", array); /* char型の配列arrayを降順にソートする */ QSort(array, sizeof(array) -1, sizeof(char), CharFuncGreater); /* 配列の内容を表示する */ array[sizeof(array)] = '\0'; printf("array = %s\n", array); /* int型の配列narrayを昇順にソートする */ QSort(narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncLess); /* 配列の内容を表示する */ printf("narray = "); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%d ", narray[i]); printf("\n"); /* int型の配列narrayを降順にソートする */ QSort(narray, sizeof(narray)/sizeof(int), sizeof(int), IntFuncGreater); /* 配列の内容を表示する */ printf("narray = "); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%d ", narray[i]); printf("\n"); /* double型の配列darrayを昇順にソートする */ QSort(darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncLess); /* 配列の内容を表示する */ printf("darray = "); for (i = 0; i < sizeof(darray)/sizeof(double); i++) printf("%f ", darray[i]); printf("\n"); /* double型の配列darrayを降順にソートする */ QSort(darray, sizeof(darray)/sizeof(double), sizeof(double), DblFuncGreater); /* 配列の内容を表示する */ printf("darray = "); for (i = 0; i < sizeof(darray)/sizeof(double); i++) printf("%f ", darray[i]); printf("\n"); /* char型文字列を昇順にソートする */ QSort(str, 5, 7, StrFuncLess); printf("内容優先の昇順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を降順にソートする */ QSort(str, 5, 7, StrFuncGreater); printf("内容優先の降順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を長さ優先で昇順にソートする */ QSort(str, 5, 7, StrlenFuncLess); printf("長さ優先の昇順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); /* char型文字列を長さ優先で降順にソートする */ QSort(str, 5, 7, StrlenFuncGreater); printf("長さ優先の降順\n"); /* 配列の内容を表示する */ for (i = 0; i < 5; i++) printf("%s ", str[i]); printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { int n = -5000; long ln = -578834584L; double dn = -3.141592653589793; /* abs()を使ってint型整数の絶対値を求める */ printf("%dの絶対値 = %d\n", n, abs(n)); /* labs()を使ってlong型整数の絶対値を求める */ printf("%ldの絶対値 = %ld\n", ln, labs(ln)); /* fabs()を使ってdouble型浮動小数点数の絶対値を求める */ printf("%.16gの絶対値 = %.16g\n", dn, fabs(dn)); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { double darray1[] = {44.323, 2.55, 72.445, 11.333, 8.088}; double darray2[] = {0.323, 0.55, 0.445, 0.333, 0.088}; int i; for (i = 0; i < sizeof(darray1)/sizeof(double); i++) printf("%lf ", darray1[i]); /* ceil()を使って浮動小数点数値の切り上げ値を求める */ printf("\nceil()の切り上げ\n"); for (i = 0; i < sizeof(darray1)/sizeof(double); i++) printf("%lf ", ceil(darray1[i])); /* floor()を使って浮動小数点数値の切り捨て値を求める */ printf("\nfloor()の切り捨て\n"); for (i = 0; i < sizeof(darray1)/sizeof(double); i++) printf("%lf ", floor(darray1[i])); /* fmod()を使って浮動小数点数値の剰余値を求める */ printf("\nfmod()の剰余\n"); for (i = 0; i < sizeof(darray1)/sizeof(double); i++) printf("%lf ", fmod(darray1[i], darray2[i])); printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { double d = 0.001; /* ネイピアeの近似値 */ double napier = 2.718281828459045, nd = napier; int i; /* log10()を使う */ for (i = 0; i < 7; i++) { printf("log10(%g) = %g\n", d, log10(d)); d *= 10; } /* log()を使う */ for (i = 0; i < 8; i++) { printf("log(%.9lf) = %g\n", nd, log(nd)); nd *= napier; } /* exp()を使う */ for (i = 1; i < 9; i++) printf("exp(%d) = %.9lf\n", i, exp(i)); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { int i, n; double d, x = 0.003; /* frexp()の分割結果をldexp()で復元する */ for (i = 1; i < 6; i++) { /* 浮動小数点数を作成する */ d = ldexp(x * i, i); printf("最初の浮動小数点数 = %lf\n", d); /* frexp()を使って仮数部と指数部に分割する */ printf("仮数部 = %lf 指数部 = %d\n", d = frexp(d, &n), n); /* ldexp()を使って仮数部と指数部を合成する */ printf("合成した浮動小数点数 = %lf\n", ldexp(d, n)); } return 0; } ------------------------------------------------------------- ☆☆Sample List 7.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { int i; /* pow()を使って二乗した結果に,sqrt()を適用して平方根を求める */ for (i = 0; i < 10; i++) printf("pow(%d, 2) = %g sqrt(%g) = %g\n", i, pow(i, 2), pow(i, 2), sqrt(pow(i, 2))); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { /* パス文字列 */ char path[] = "temp"; /* system()用のコマンド文字列 */ char command[] = "type temp | more"; FILE *pf; /* 「rad × π = 180°」 ,「1rad ≒ 57.3°」*/ /* 57.3°の精度を高くした値 */ double ratio = 180 / 3.141592653589793238462643383; int i; /* 書き出し用にtempファイルを開く */ if ((pf = fopen(path, "w")) == NULL) { fprintf(stderr, "ファイルオープンエラー\n"); exit(1); } /* sin()を使ってサイン値を求める */ fputs("sin()関数を使ってサイン値を求める\n", pf); for (i = -90; i <= 90; i += 10) { /* 範囲外の値を使わないチェック */ if (sin(i / ratio) < -1.0 || sin(i / ratio) > 1.0) /* 度数をラジアンに変換してサイン値を求める */ fprintf(pf, "%d度:%.15lfラジアン\nサイン値 = %.15lf" " サインの逆サイン値 = 不可\n", i, i / ratio, sin(i / ratio)); else /* 度数をラジアンに変換してサイン値を求める */ fprintf(pf, "%d度:%.15lfラジアン\nサイン値 = %.15lf" " サインの逆サイン値 = %.15lf\n", i, i / ratio, sin(i / ratio), asin(sin(i / ratio))); } /* cos()を使ってコサイン値を求める */ fputs("cos()関数を使ってコサイン値を求める\n", pf); for (i = -90; i <= 90; i += 10) { /* 範囲外の値を使わないチェック */ if (sin(i / ratio) < -1.0 || sin(i / ratio) > 1.0) /* 度数をラジアンに変換してコサイン値を求める */ fprintf(pf, "%d度:%.15lfラジアン\nコサイン値 = %.15lf" " コサインの逆コサイン値 = 不可\n", i, i / ratio, cos(i / ratio)); else /* 度数をラジアンに変換してコサイン値を求める */ fprintf(pf, "%d度:%.15lfラジアン\nコサイン値 = %.15lf" " コサインの逆コサイン値 = %.15lf\n", i, i / ratio, cos(i / ratio), acos(cos(i / ratio))); } /* tan()を使ってタンジェント値を求める */ fputs("tan()関数を使ってタンジェント値を求める\n", pf); for (i = -80; i < 90; i += 10) { /* 度数をラジアンに変換してタンジェント値を求める */ fprintf(pf, "%d度:%.15lfラジアン\nタンジェント値 = %.15lf" " 逆タンジェント値 = %.15lf\n", i, i / ratio, tan(i / ratio), atan(tan(i / ratio))); } /* ファイルを閉じる */ fclose(pf); /* system()関数を使ってtempファイルを表示する */ system(command); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { /* パス文字列 */ char path[] = "temp"; /* system()用のコマンド文字列 */ char command[] = "type temp | more"; FILE *pf; /* 57.3°の精度を高くした値 */ double ratio = 180 / 3.141592653589793238462643383; int i; /* 書き出し用にtempファイルを開く */ if ((pf = fopen(path, "w")) == NULL) { fprintf(stderr, "ファイルオープンエラー\n"); exit(1); } /* sinh()を使って双曲線サイン値を求める */ fputs("sinh()関数を使って双曲線サイン値を求める\n", pf); for (i = -90; i <= 90; i += 10) { /* 浮動小数点数の双曲線サイン値を求める */ fprintf(pf, "%.15lfの双曲線サイン値 = %.15lf\n", i / ratio, sinh(i / ratio)); } /* cosh()を使って双曲線コサイン値を求める */ fputs("cosh()関数を使って双曲線コサイン値を求める\n", pf); for (i = -90; i <= 90; i += 10) { /* 浮動小数点数の双曲線コサイン値を求める */ fprintf(pf, "%.15lfの双曲線コサイン値 = %.15lf\n", i / ratio, cosh(i / ratio)); } /* tanh()を使ってタンジェント値を求める */ fputs("tanh()関数を使って双曲線タンジェント値を求める\n", pf); for (i = -80; i < 90; i += 10) { /* 浮動小数点数の双曲線タンジェント値を求める */ fprintf(pf, "%.15lfの双曲線タンジェント値 = %.15lf\n", i / ratio, tanh(i / ratio)); } /* ファイルを閉じる */ fclose(pf); /* system()関数を使って,tempファイルを表示する */ system(command); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 10進の総桁数を求める関数 */ int CountDigit(double x) { /* log10()を使う(負の数は扱えない) */ double digits, d = log10(fabs(x)); /* modf()を使う */ modf(d, &digits); /* ゼロは1桁の扱いとする */ return (int)digits + 1; } main () { /* テストデータ */ double narray[] = { -9, -99, 9.99, 9999, -99999, -999999, 9999999, 0, 1, 10, 100, -10.00, 10000, -100000, 1000000}; int i; /* CountDigit()関数を使う */ for (i = 0; i < sizeof(narray)/sizeof(double); i++) printf("narray[%d] = %f --->10進桁数:%d\n", i, narray[i], CountDigit(narray[i])); return 0; } ------------------------------------------------------------- ☆☆Sample List 7.9☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 点座標を表すPOINT型構造体 */ typedef struct { double x; double y; } POINT; /* 2点間の距離を求める関数 */ double Distance(POINT p1, POINT p2) { /* 2点間の距離を計算する */ return fabs(sqrt(pow(fabs(p2.x - p1.x), 2) + pow(fabs(p2.y - p1.y), 2))); } main () { POINT p1, p2; int i; /* Distance()関数を使って2点間の距離を表示する */ for (i = 0; i < 10; i++) { p1.x = p1.y = i; p2.x = p2.y = i + i * 2; printf("p1.x = %g p1.y = %g p2.x = %g p2.y = %g\n" "2点間の距離 = %g\n", p1.x, p1.y, p2.x, p2.y, Distance(p1, p2)); } return 0; } ------------------------------------------------------------- ☆☆Sample List 7.10☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* int型四捨五入除算関数 */ int Round45(int numer, int denom) { /* div_t型の構造体に除算結果を得る */ div_t dt = div(numer, denom); div_t dt2 = div(dt.rem * 10, denom); /* 余りを評価する */ if (dt2.quot > 4) return dt.quot + 1; else return dt.quot; } /* int型切り上げ除算関数 */ int RoundUp(int numer, int denom) { /* div_t型の構造体に除算結果を得る */ div_t dt = div(numer, denom); /* 余りを評価する */ if (dt.rem) return dt.quot + 1; else return dt.quot; } /* int型三捨四入除算関数 */ int Round34(int numer, int denom) { /* div_t型の構造体に除算結果を得る */ div_t dt = div(numer, denom); div_t dt2 = div(dt.rem * 10, denom); /* 余りを評価する */ if (dt2.quot > 3) return dt.quot + 1; else return dt.quot; } /* int型五捨六入除算関数 */ int Round56(int numer, int denom) { /* div_t型の構造体に除算結果を得る */ div_t dt = div(numer, denom); div_t dt2 = div(dt.rem * 10, denom); /* 余りを評価する */ if (dt2.quot > 5) return dt.quot + 1; else return dt.quot; } /* long型四捨五入除算関数 */ long LRound45(long numer, long denom) { /* ldiv_t型の構造体に除算結果を得る */ ldiv_t ldt = ldiv(numer, denom); ldiv_t ldt2 = ldiv(ldt.rem * 10, denom); /* 余りを評価する */ if (ldt2.quot > 4) return ldt.quot + 1; else return ldt.quot; } /* long型切り上げ除算関数 */ long LRoundUp(long numer, long denom) { /* ldiv_t型の構造体に除算結果を得る */ ldiv_t ldt = ldiv(numer, denom); /* 余りを評価する */ if (ldt.rem) return ldt.quot + 1; else return ldt.quot; } /* long型三捨四入除算関数 */ long LRound34(long numer, long denom) { /* ldiv_t型の構造体に除算結果を得る */ ldiv_t ldt = ldiv(numer, denom); ldiv_t ldt2 = ldiv(ldt.rem * 10, denom); /* 余りを評価する */ if (ldt2.quot > 3) return ldt.quot + 1; else return ldt.quot; } /* long型五捨六入除算関数 */ long LRound56(long numer, long denom) { /* ldiv_t型の構造体に除算結果を得る */ ldiv_t ldt = ldiv(numer, denom); ldiv_t ldt2 = ldiv(ldt.rem * 10, denom); /* 余りを評価する */ if (ldt2.quot > 5) return ldt.quot + 1; else return ldt.quot; } main () { int n = 32767, i; int narray[] = {1525, 2214, 520, 888, 737, 333, 1455, 589}; printf("切り捨て\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], n/narray[i]); printf("切り上げ\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], RoundUp(n, narray[i])); printf("四捨五入\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], Round45(n, narray[i])); printf("三捨四入\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], Round34(n, narray[i])); printf("五捨六入\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], Round56(n, narray[i])); return 0; } ------------------------------------------------------------- ☆☆Sample List 8.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { char *p; void *vp; /* malloc()を使って15バイトの領域を割り当てる */ p = (char *)malloc(15); /* 非voidポインタにvoidポインタを代入する */ if (p != NULL) { /* 割り当てた領域に文字列をコピーする */ strcpy(p, "ABCDEFGHIJKLMN"); /* voidポインタに非voidポインタを代入する */ vp = p; /* voidポインタに非voidポインタを代入する */ /* エラーとなる記述... vpの1バイト先を間接参照するつもり */ /* printf("%s\n", vp + 1); */ /* エラーとならない記述... vpの1バイト先を間接参照する */ printf("%s\n", (char *)vp + 1); } return 0; } ------------------------------------------------------------- ☆☆Sample List 8.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #define BUFFSIZE 50 /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } main () { char *p; /* malloc()を使って51バイトの領域を割り当てる */ if ((p = (char *)malloc(BUFFSIZE + 1)) == NULL) OperationError("メモリ割り当てエラー\n"); /* malloc()がヌルを返さなければポインタは使える */ /* memset()を使って,「?」文字で初期化する */ memset(p, '?', BUFFSIZE); /* 末尾にヌル文字を埋める */ p[BUFFSIZE] = '\0'; /* 文字列を表示する */ printf("%s\n", p); /* 割り当て済みの領域を解放する */ free(p); /* <--- 最後のfree()呼び出しはなくてもよい */ return 0; } ------------------------------------------------------------- ☆☆Sample List 8.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } main () { int narray[] = {1000, 2000, 3000, 4000, 5000}; int *pn = NULL, *pn2 = NULL, *pn3 = NULL; int i, size = sizeof(narray)/sizeof(int); /* calloc()を使ってメモリを割り当てる */ if ((pn = (int *)calloc(size, sizeof(int))) == NULL) OperationError("メモリ割り当てエラー\n"); /* 配列pnに配列narrayの要素をコピーする */ for (i = 0; i < size; i++) pn[i] = narray[i]; /* pn配列の要素を表示する */ for (i = 0; i < size; i++) printf("%d ", pn[i]); printf("\n"); /* realloc()を使ってサイズ変更する */ if ((pn2 = (int *)realloc(pn, sizeof(narray) * 2)) == NULL) OperationError("メモリ再割り当てエラー\n"); /* 成功すればpnポインタを使ってはいけない */ pn = NULL; /* 配列pn2の後半分に配列narrayの要素をコピーする */ for (i = size; i < size * 2; i++) pn2[i] = narray[i - size]; /* pn2配列全体の要素を表示する */ for (i = 0; i < size * 2; i++) printf("%d ", pn2[i]); printf("\n"); /* 配列pn2をrealloc()を使ってサイズ変更する*/ if ((pn3 = (int *)realloc(pn2, sizeof(narray))) == NULL) OperationError("メモリ再割り当てエラー\n"); /* 成功すればpn2ポインタを使ってはいけない */ pn2 = NULL; /* pn3配列全体の要素を表示する */ for (i = 0; i < size; i++) printf("%d ", pn3[i]); printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 8.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } main () { char array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int narray[] = {1000, 2000, 3000, 4000, 5000}; int *pn = NULL, *pn2 = NULL, *pn3 = NULL; int i, size = sizeof(narray)/sizeof(int); /* calloc()を使ってメモリを割り当てる */ if ((pn = (int *)calloc(size, sizeof(int))) == NULL) OperationError("メモリ割り当てエラー\n"); /* 配列pnに配列narrayの要素をコピーする */ memcpy(pn, narray, sizeof(narray)); /* pn配列の要素を表示する */ for (i = 0; i < size; i++) printf("%d ", pn[i]); printf("\n"); /* realloc()を使ってサイズ変更する */ if ((pn2 = (int *)realloc(pn, sizeof(narray) * 2)) == NULL) OperationError("メモリ再割り当てエラー\n"); /* 成功すればpnポインタを使ってはいけない */ pn = NULL; /* 配列pn2の後半分に配列narrayの要素をコピーする */ memcpy(pn2 + size, narray, sizeof(narray)); /* pn2配列全体の要素を表示する */ for (i = 0; i < size * 2; i++) printf("%d ", pn2[i]); printf("\n"); /* 配列pn2をrealloc()を使ってサイズ変更する*/ if ((pn3 = (int *)realloc(pn2, sizeof(narray))) == NULL) OperationError("メモリ再割り当てエラー\n"); /* 成功すればpn2ポインタを使ってはいけない */ pn2 = NULL; /* pn3配列全体の要素を表示する */ for (i = 0; i < size; i++) printf("%d ", pn3[i]); printf("\n"); /* memmove()を使って重なった要素を移動コピーする */ memmove(array, &array[5], 21); /* 配列arrayの内容を表示する */ printf("%s\n", array); return 0; } ------------------------------------------------------------- ☆☆Sample List 8.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #define ARRAYSIZE 8 /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { fprintf(stderr, pstr); exit(1); } /* 商品在庫管理用のINVENTORY構造体定義 */ typedef struct inventory { /* 商品番号 */ int bumber; /* 商品名 */ char *name; /* 在庫数量 */ int volume; /* 仕入れ日数 */ int leadtime; } INVENTORY; /* 商品在庫を表示する */ void DispInventory(INVENTORY *ip) { printf("商品名:%s\n", ip->name); printf("商品番号:%d ", ip->bumber); printf("在庫数量:%d ", ip->volume); printf("仕入れ日数:%d\n", ip->leadtime); printf("------------------\n"); } main () { int i; INVENTORY ia[ARRAYSIZE]; INVENTORY *ip = ia, *ip2 = NULL; int array1[] = {154100, 154110, 113700, 113701, 213220, 213222, 503230, 503231}; char *array2[] = { "がんこな汚れも,すっかりクリーン", "がんこな汚れも,すっかりクリーン(抗菌タイプ)", "しつこい汚れに,しっかりクリーン", "しつこい汚れに,しっかりクリーン(抗菌タイプ)", "とれない汚れに,これでもか!クリーン", "とれない汚れに,これでもか!クリーン(抗菌タイプ)", "また付く汚れに,どれどれ!クリーン", "また付く汚れに,どれどれ!クリーン(抗菌タイプ)", }; int array3[] = {12300, 11500, 2800, 2200, 6400, 5300, 7600, 7000}; int array4[] = {6, 6, 20, 20, 6, 6, 8, 8}; /* INVENTORYリストに値を登録する */ for (i = 0; i < ARRAYSIZE; i++, ip++) { ip->bumber = array1[i]; ip->name = array2[i]; ip->volume = array3[i]; ip->leadtime = array4[i]; } /*/////////////////////////////////////*/ /* INVENTORYリストを表示する */ /* for (ip = ia; ip < ia + ARRAYSIZE; ip++) DispInventory(ip); */ /*/////////////////////////////////////*/ /* calloc()を使ってメモリを割り当てる */ if ((ip2 = (INVENTORY *)calloc(sizeof(ia)/sizeof(INVENTORY), sizeof(INVENTORY))) == NULL) OperationError("メモリ割り当てエラー\n"); /* memcpy()を使ってコピーする */ memcpy(ip2, ia, sizeof(ia)); /* INVENTORYリストを表示する */ for (ip = ip2; ip < ip2 + ARRAYSIZE; ip++) DispInventory(ip); return 0; } ------------------------------------------------------------- ☆☆Sample List 8.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include main () { char array[30] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *pch = array; /* memmove()を使って重なった要素を移動コピーする */ memmove(&array[5], array, 21); /* memmove()を使って重なった要素を移動コピーする */ memmove(&array[10], array, 16); /* 配列arrayの内容を表示する */ printf("%s\n", array); pch = array; /* memchr()を使って文字「A」を探索する */ while (pch) { pch = (char *)memchr(pch, 'A', strlen(pch)); if (pch) { printf("要素%d = %c ", pch - array, *pch); if (!memcmp(pch, pch + 5, 5)) printf("後続の連続する5バイトは等しい\n"); else printf("後続の連続する5バイトは等しくない\n"); pch++; } } printf("\n"); return 0; } ------------------------------------------------------------- ☆☆Sample List 8.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include #include #define PARRAYSIZE 256 /* Clone()系関数が割り当てたメモリポインタを 管理するためのグローバル変数 */ char *parray[PARRAYSIZE]; int dyncount; /* Clone()系関数が割り当てたメモリを解放する関数 */ void FreeCloneAll() { /*////////////////////////////////*/ /* Clone()系関数が割り当てたすべての メモリを解放する */ while (dyncount) free(parray[dyncount-- -1]); /*////////////////////////////////*/ /* assert()を使ってdyncountを診断する dyncountは空でなければならない */ assert(!dyncount); } char *CloneAddStr(const char *str1, const char *str2) { /* 文字列str1とstr2の格納領域を割り当てる */ char *pstr = (char *)malloc(strlen(str1) + strlen(str2) + 1); /* 失敗した場合 */ if (pstr == NULL) return NULL; /*////////////////////////////////*/ /* 解放用にポインタを保存しておく */ parray[dyncount++] = pstr; /*////////////////////////////////*/ /* 先に文字列str1をコピーする */ strcpy(pstr, str1); /* 次にstr2を連結する */ strcat(pstr, str2); /* クローンへのポインタを返す */ return pstr; } /* 指定文字数の文字列のクローンを作成する関数 */ char *CloneStrn(const char *str, size_t n) { /* 文字列strの格納領域を割り当てる */ char *pstr = (char *)malloc(n + 1); /* 失敗した場合 */ if (pstr == NULL) return NULL; /*////////////////////////////////*/ /* 解放用にポインタを保存しておく */ parray[dyncount++] = pstr; /*////////////////////////////////*/ /* 割り当て領域に文字列strをコピーする */ strncpy(pstr, str, n); /* ヌル文字を付ける */ pstr[n] = '\0'; /* クローンへのポインタを返す */ return pstr; } /* ヌル文字付き文字列のクローンを作成する関数 */ char *CloneStr(const char *str) { /* 文字列strの格納領域を割り当てる */ char *pstr = (char *)malloc(strlen(str) + 1); /* 失敗した場合 */ if (pstr == NULL) return NULL; /*////////////////////////////////*/ /* 解放用にポインタを保存しておく */ parray[dyncount++] = pstr; /*////////////////////////////////*/ /* 割り当て領域に文字列strをコピーする */ strcpy(pstr, str); /* クローンへのポインタを返す */ return pstr; } /* 1桁の数値を10進の数字文字に変換する関数 */ int ToDigitNum(int c) { /* 1桁の数値であれば10進の数字文字に変換する */ if (c >= 0 && c <= 9) return (c + '0'); else return c; } /* long型数値を数字文字列に変換する関数(符号認識バージョン) */ int LToStr(long lval, char *str, size_t n) { int dval, index = 0, maxcolumn = 1000000000; unsigned int maxcol = 10; int flag = 0; /* 負の値を絶対値変換する */ if (lval < 0) { flag = 1; /* 絶対値に変換する */ lval = abs(lval); } /* 10進の総桁数を求める */ while (maxcolumn) { if (lval >= maxcolumn) { break; } maxcol--; maxcolumn /= 10; } /* バッファサイズが足りるかどうか(ヌル文字を含む) */ if (flag) { if (maxcol + 2 > n) /* 失敗した */ return 1; /* マイナス符号を付ける */ str[index++] = '-'; } else if (maxcol + 1 > n) /* 失敗した */ return 1; /* 上位桁から数字文字に変換する */ while (maxcolumn) { /* 上桁の10進の桁値を求める */ dval = lval / maxcolumn; /* ToDigitNum()関数を使って変換する */ str[index++] = ToDigitNum(dval); /* 上桁を削除する */ lval -= dval * maxcolumn; /* 下位桁に移行する */ maxcolumn /= 10; } /* 文字列を完成させる */ str[index] = '\0'; /* 成功した */ return 0; } /* 数値の10進表現の桁数を求める関数 */ int CountDigitNum(long val) { int count = 0; while (val) { val /= 10; count++; } return ++count; } /* LToStr()関数(符号認識バージョン)を使って クローン文字列を生成する関数 */ char *CloneLToStr(long lval) { /* LONG_MAXの10進桁数 + 1の大きさの文字列を格納 できるクローン領域を確保する */ char *pstr = (char *)malloc(CountDigitNum(LONG_MAX) + 1); /* 失敗した場合 */ if (pstr == NULL) return NULL; /* 確保した領域に文字列を生成する */ if (LToStr(lval, pstr, CountDigitNum(LONG_MAX) + 1)) { /* 失敗したのでメモリを解放する */ free(pstr); return NULL; } /*////////////////////////////////*/ /* 解放用にポインタを保存しておく */ parray[dyncount++] = pstr; /*////////////////////////////////*/ /* クローンへのポインタを返す */ return pstr; } main () { char array1[] = "これは"; char array2[] = "もとの"; char array3[] = "文字列"; char array4[] = "これは10進数字文字列 = "; char buff[100]; long l = 256000000; char *pch; /* CloneStrn()関数を使ってクローンを作成する */ printf("%s\n", CloneStrn(array1, 4)); printf("%s\n", CloneStrn(array2, 4)); printf("%s\n", CloneStrn(array3, 2)); /* CloneStr()関数を使ってクローンを作成する */ printf("%s\n", CloneStr(array1)); printf("%s\n", CloneStr(array2)); printf("%s\n", CloneStr(array3)); printf("%s\n", CloneStr("これは文字列定数のクローン")); /* long型のlを文字列変換したクローンを作成する */ printf("%s\n", CloneLToStr(l)); /* 文字列を連結したクローンを作成する */ printf("%s\n", CloneAddStr(array4, CloneLToStr(l))); /* 文字列を連結したクローンを作成する */ printf("%s\n", CloneAddStr(array1, array3)); /* 文字列を連結したクローンを作成する */ printf("%s\n", CloneAddStr(array2, array3)); /* クローンの割り当て領域をすべて解放する */ FreeCloneAll(); /* 文字列を連結したクローンを作成する */ printf("%s\n", CloneAddStr(CloneAddStr(array1, array2), array3)); /* 文字列を連結したクローンを作成する */ printf("%s\n", CloneAddStr(CloneAddStr(array1, "新しい"), array3)); /* 連結後の文字列を配列にコピーする */ strcpy(buff, CloneAddStr(CloneAddStr(array1, "新しい"), array3)); /*///////////////////////////////////////////////////////*/ /* 個別に解放する場合はparrayにNULLを代入しておく */ pch = CloneAddStr(CloneAddStr(array1, "新しい"), array3); /* 個別に解放する */ free(pch); /* NULLを代入する */ parray[dyncount -1] = NULL; /*///////////////////////////////////////////////////////*/ /* クローンの割り当て領域をすべて解放する */ FreeCloneAll(); /* 配列buffの内容を表示する */ printf("buff = %s\n", buff); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include main () { /* __FILE__マクロの文字列を表示する */ printf("__FILE__ = %s\n", __FILE__); /* __LINE__マクロの整数値を表示する */ printf("__LINE__ = %d\n", __LINE__); /* __DATE__マクロの文字列を表示する */ printf("__DATE__ = %s\n", __DATE__); /* __TIME__マクロの文字列を表示する */ printf("__TIME__ = %s\n", __TIME__); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* 可変個引数リストを持つ関数 */ void VarArg(int n, ...) { int i; /* va_list型の変数を宣言する */ va_list vl; /* va_start()マクロを使って,vlポインタを初期化する */ va_start(vl, n); /* va_arg()マクロを使って,順に引数を取得する */ for (i = 0; i < n; i++) { switch (i) { /* 第1引数では,本来は取り扱えないfloat型を取り扱う */ case 0: /* 引数リストの次の実引数を取得する */ printf("%g ", (float)va_arg(vl, double)); break; /* 第2引数では,本来は取り扱えないchar型を取り扱う */ case 1: /* 引数リストの次の実引数を取得する */ printf("%c ", (char)va_arg(vl, int)); break; /* 第3引数では,double型を取り扱う */ case 2: /* 引数リストの次の実引数を取得する */ printf("%g ", va_arg(vl, double)); break; /* 第4引数以降はすべてint型を取り扱う */ default: /* 引数リストの次の実引数を取得する */ printf("%d ", va_arg(vl, int)); } } /* リセットする */ va_end(vl); printf("\n"); } main () { int a1[] = {10, 20, 30, 40, 50}; char a2[] = {'A', 'B', 'C', 'D', 'E'}; float a3[] = {1.100, 2.200, 3.300, 4.400, 5.500}; double a4[] = {1.123456789, 2.123456789, 3.123456789, 4.123456789, 5.123456789}; /* 0個の可変引数を指定する */ printf("0個の可変引数を指定する ---> "); VarArg(0); /* 1個の可変引数を指定する */ printf("1個の可変引数を指定する ---> "); VarArg(1, a3[3]); /* 2個の可変引数を指定する */ printf("2個の可変引数を指定する ---> "); VarArg(2, a3[4], a2[2]); /* 3個の可変引数を指定する */ printf("3個の可変引数を指定する ---> "); VarArg(3, a3[2], a2[0], a4[3]); /* 4個の可変引数を指定する */ printf("4個の可変引数を指定する ---> "); VarArg(4, a3[0], a2[3], a4[2], a1[2]); /* 5個の可変引数を指定する */ printf("5個の可変引数を指定する ---> "); VarArg(5, a3[1], a2[2], a4[0], a1[3], a1[0]); /* 6個の可変引数を指定する */ printf("6個の可変引数を指定する ---> "); VarArg(6, a3[4], a2[4], a4[1], a1[0], a1[3], a1[4]); /* 7個の可変引数を指定する */ printf("7個の可変引数を指定する ---> "); VarArg(7, a3[0], a2[3], a4[3], a1[2], a1[1], a1[3], a1[2]); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define BUFFSIZE 256 main () { /* 実行するコマンド用の文字列 */ char str[] = "dir/w > temp"; char buff[BUFFSIZE + 1]; FILE *pf; /* system()を使ってコマンドプロセッサの存在を確かめる */ if (!system(NULL)) { fprintf(stderr, "コマンドプロセッサが使えない\n"); exit(1); } /* system()を使ってコマンドを実行する */ system(str); /* tempファイルを開く */ if ((pf = fopen("temp", "r")) == NULL) { fprintf(stderr, "ファイルオープンエラー\n"); exit(1); } else { /* tempファイルの内容を表示する */ while (!feof(pf)) { if (fgets(buff, BUFFSIZE + 1, pf) != NULL) printf("%s", buff); } } return 0; } ------------------------------------------------------------- ☆☆Sample List 9.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { /* getenv()を使ってPATH環境変数の情報を表示する */ printf("%s\n", getenv("PATH")); /* getenv()を使ってCOMSPEC環境変数の情報を表示する */ printf("%s\n", getenv("COMSPEC")); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* エラーメッセージを表示して異常終了する関数 */ void OperationError(char *pstr) { /* エラーメッセージを表示する */ fprintf(stderr, pstr); /* 後始末の後,正しい手続きとして異常終了する */ exit(1); } char str[] = "type temp"; /* プログラムの終了前に呼び出す関数 */ void DispTemp(void) { /* tempファイルを表示する */ system(str); } int main(int argc, char *argv[]) { char str[] = "dir/w > temp"; /* プログラムの引数用法を検証する */ if (argc > 1) OperationError( "引数を指定してプログラムが実行されました\n"); /* プログラム終了時に呼び出す関数を設定する */ atexit(DispTemp); printf("正しい用法でプログラムが起動されました.\n"); system(str); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include int RoundUp(int numer, int denom) { /* div_t型の構造体 */ div_t dt, dt2; /* ゼロ除算をアサートする */ /* assert(denom != 0); */ ///////////////////////////////////////////////// #ifndef NDEBUG if (denom == 0) { fprintf(stderr, "ゼロ除算が試みられたので,処理を中止します.\n" "ゼロ除算情報: 関数名RoundUp()の仮引数denom\n" "発生箇所:ファイル名 %s 行数 %d\n",__FILE__, __LINE__); /* アボートする */ abort(); } #endif ///////////////////////////////////////////////// dt = div(numer, denom); if (dt.rem) return dt.quot + 1; else return dt.quot; } /* int型三捨四入除算関数 */ int Round34(int numer, int denom) { /* div_t型の構造体 */ div_t dt, dt2; /* ゼロ除算をアサートする */ assert(denom != 0); dt = div(numer, denom); dt2 = div(dt.rem * 10, denom); if (dt2.quot > 3) return dt.quot + 1; else return dt.quot; } main () { int n = 32767, i; int narray[] = {0/*1525*/, 2214, 520, 888, 737, 333, 1455, 589}; printf("切り上げ\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], RoundUp(n, narray[i])); printf("\n三捨四入\n"); for (i = 0; i < sizeof(narray)/sizeof(int); i++) printf("%f ---> %d ", (double)n/narray[i], Round34(n, narray[i])); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include main () { /* errnoを初期設定する */ errno = 0; /* errnoに,EDOM(定義の範囲エラー)を設定させる */ acos(100); /* perror()を使って自動的にエラーメッセージを表示する */ perror("エラー内容"); /* strerror()を使ってエラーメッセージを取得し,表示する */ fprintf(stderr, "エラー内容: %s\n", strerror(errno)); /* errnoを初期設定する */ errno = 0; /* errnoに,ERANGE(結果の範囲エラー)を設定させる */ cosh(100000); /* perror()を使って自動的にエラーメッセージを表示する */ perror("エラー内容"); /* strerror()を使ってエラーメッセージを取得し,表示する */ fprintf(stderr, "エラー内容: %s\n", strerror(errno)); return 0; } ------------------------------------------------------------- ☆☆Sample List 9.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include void DispArgs(int argc, ...) { /* va_list型の変数を宣言する */ va_list vl; /* va_start()マクロを使って,vlポインタを初期化する */ va_start(vl, argc); switch (argc) { case 1: vprintf("プログラム名 = %s\n", vl); break; case 2: vprintf("プログラム名 = %s\n" "プログラムの引数1 = %s\n", vl); break; case 3: vprintf("プログラム名 = %s\n" "プログラムの引数1 = %s\n" "プログラムの引数2 = %s\n", vl); break; default: vprintf("プログラム名 = %s\n", vl); break; } /* va_end()マクロを使って,vlポインタをリセットする */ va_end(vl); } int main(int argc, char *argv[]) { switch (argc) { case 1: DispArgs(argc, argv[0]); break; case 2: DispArgs(argc, argv[0], argv[1]); break; case 3: DispArgs(argc, argv[0], argv[1], argv[2]); break; default: DispArgs(argc, argv[0]); break; } return 0; } ------------------------------------------------------------- ☆☆Sample List 9.9☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include /* 関数のプロトタイプ宣言 */ void Handler(int n); /* SIGINTのシグナルハンドラを設定する関数 */ void SetHandler(void) { /* signal()を使ってSIGINTシグナル用にHandlerを設定する */ if (signal(SIGINT, Handler) == SIG_ERR) { fprintf(stderr, "シグナルハンドラの設定に失敗\n"); abort(); } } /* シグナルを処理するシグナルハンドラ */ void Handler(int n) { static int x = 0; printf("\n割り込み発生 !!\n"); /* Bellを鳴らす */ printf("%c", 0x07); /* 5回目の「Ctrl + C」で終了する */ if (x++ >= 4) abort(); /* SIGINTのシグナルハンドラを設定する */ SetHandler(); } main () { int count = 0; while (1){ /* SIGINTのシグナルハンドラを設定する */ SetHandler(); while (1) { printf("main続行中... "); count++; /* countが10000になれば,SIGABRTをレイズする */ if (count > 10000) raise(SIGABRT); } } return 0; } ------------------------------------------------------------- ☆☆Sample List 9.10☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* jmp_bufバッファ */ jmp_buf curenv; /* 関数のプロトタイプ宣言 */ void Handler(int n); void SetHandler(void); /* SIGINTシグナルをレイズする */ void Raise() { /* シグナルハンドラを設定する */ SetHandler(); /* SIGINTシグナルをレイズする */ if (raise(SIGINT)) { fprintf(stderr, "シグナルのレイズに失敗\n"); abort(); } } /* SIGINTシグナルハンドラを設定する */ void SetHandler(void) { /* signal()を使ってシグナルハンドラを設定する */ if (signal(SIGINT, Handler) == SIG_ERR) { fprintf(stderr, "シグナルハンドラの設定に失敗\n"); abort(); } } /* SIGINTシグナルを処理するハンドラ */ void Handler(int n) { char key; static int x = 0; printf("SIGINT割り込み発生 !!\n"); printf("%c", 0x07); /* Enterキーを入力 */ printf("何かキーを入力してください.Qキーで終了"); scanf("%c", &key); if (key != '\n') /* キーの読み飛ばし */ scanf("%*c"); /* 「q」または「Q」で終了する */ if (toupper(key) == 'Q') exit(0); /* 偶数回にlongjmp()を呼び出す */ if (!(x++ % 2)) /* longjmp()を使ってジャンプする */ longjmp(curenv, 1); /* 奇数回は自動的な復帰に任せる */ } main () { while (1) { /* setjmp()を使ってjmp_bufバッファに 現在の情報を確保する */ if (setjmp(curenv)) { printf("第1復帰位置\n"); /* SIGINTシグナルをレイズする */ Raise(); } else { printf("第2復帰位置\n"); /* SIGINTシグナルをレイズする */ Raise(); } } return 0; } ------------------------------------------------------------- ☆☆Sample List 9.11☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include /* ネスト定義の子メンバを持つMyStruct構造体の定義 */ typedef struct mystruct { int n; /* 構造体のネスト定義 */ struct mychild { int n; /* 親構造体へのポインタ */ struct mystruct *pms; } MyChild; /* 子構造体へのポインタ */ struct mychild *pmc; } MyStruct; main () { /* MyStruct構造体型の変数を宣言,初期化する */ MyStruct myst = {200, {100, (struct mystruct *)((char *)&myst.MyChild -(char *)offsetof(MyStruct, MyChild))}, &myst.MyChild}; /* 親構造体のnメンバの値 */ printf("%d\n", myst.n); /* 子構造体のnメンバの値 */ printf("%d\n", myst.MyChild.n); /* 親構造体のnメンバの値 */ printf("%d\n", myst.MyChild.pms->n); /* 子構造体のnメンバの値 */ printf("%d\n", myst.pmc->n); /* myst変数のアドレス */ printf("mystのアドレス = %d\n", &myst); /* myst変数のMyChildメンバのアドレス */ printf("myst.MyChildのアドレス = %d\n", &myst.MyChild); /* MyStruct構造体型での親と子のオフセット値 */ printf("親と子のオフセット値 = %d\n", (char *)offsetof(MyStruct, MyChild)); /* pmcの指すアドレス */ printf("myst.pmc = %d\n", myst.pmc); /* pmsの指すアドレス */ printf("myst.MyChild.pms = %d\n", myst.MyChild.pms); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.1☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { /* time()を使ってtime_t型の現在時刻を得る */ time_t tnow = time(NULL); /* localtime()を使って,tm構造体型の情報を得る */ struct tm *ptmnow = localtime(&tnow); /* ctime()を使ってtime_t型のtnowを文字列変換する */ printf("現在の時刻 = %s", ctime(&tnow)); /* asctime()を使ってtm構造体情報を文字列変換する */ printf("現在の時刻 = %s", asctime(ptmnow)); /* tm構造体のメンバ情報を確認する */ /* 年度情報 */ printf("tm_year + 1900 = %d\n", ptmnow->tm_year + 1900); /* 月情報 */ printf("tm_mon = %d\n", ptmnow->tm_mon); /* 日情報 */ printf("tm_mday = %d\n", ptmnow->tm_mday); /* 曜日情報 */ printf("tm_wday = %d\n", ptmnow->tm_wday); /* 時間情報 */ printf("tm_hour = %d\n", ptmnow->tm_hour); /* 分情報 */ printf("tm_min = %d\n", ptmnow->tm_min); /* 秒情報 */ printf("tm_sec = %d\n", ptmnow->tm_sec); /* 通算日数情報 */ printf("tm_yday = %d\n", ptmnow->tm_yday); /* 夏時間情報 */ printf("tm_isdst = %d\n", ptmnow->tm_isdst); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.2☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { struct tm tmg, tmnow; /* time()を使ってtime_t型の現在時刻を得る */ time_t tgnew, tnew, tnow = time(NULL); /* localtime()を使って,tm構造体型の情報を得る */ tmnow = *localtime(&tnow); /* tm構造体tmnow時刻を表示する */ printf("現在のローカル時刻 = %s", asctime(&tmnow)); /* gmtime()を使って,tm構造体型の世界標準時刻情報を得る */ tmg = *gmtime(&tnow); /* tm構造体tmg時刻を表示する */ printf("現在の世界標準時刻 = %s", asctime(&tmg)); /* mktime()を使って,tmnowのtm構造体情報をtnewに変換する */ tnew = mktime(&tmnow); /* time_t型のtnewを表示する */ printf("現在のローカル時刻 = %s", ctime(&tnew)); /* mktime()を使って,tmgのtm構造体情報をtgnewに変換する */ tgnew = mktime(&tmg); /* time_t型のtgnewを表示する */ printf("現在の世界標準時刻 = %s", ctime(&tgnew)); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.3☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { clock_t t; int n = 1; /* しばらく時間を経過させる */ printf("計算の実行中...\n"); /* int型のnが一巡して負になるまで インクリメントを続ける */ while (n > 0) n++; /* ミリ秒単位のラップタイムを表示する */ t = clock() * (1000/CLOCKS_PER_SEC); /* ミリ秒単位表現の経過時間 */ printf("ミリ秒単位表現の経過時間 = %d\n", t); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.4☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include #include /* 指定時間待機する独自のSleep()関数 */ void Sleep(int count) { /* 現在の経過時間 */ clock_t t = clock() * (1000/CLOCKS_PER_SEC); /* 終了用の経過時間 */ clock_t tterm = t + count; /* 終了用の経過時間までループする */ while (t < tterm) { t = clock() * (1000/CLOCKS_PER_SEC); /* tが(clock_t)-1でないことを診断する */ assert(t != (clock_t)-1); /* if (t == (clock_t)-1) return; */ } } main () { /* toldに,現在の時刻を求める */ time_t tnew, told = time(NULL); /* しばらく時間を経過させる */ printf("10秒間待機する...\n"); /* 10秒間動作を停止する */ Sleep(10000); /* tnewに,現在の時刻を求める */ tnew = time(NULL); /* difftime()を使って秒数表現の時間差を求める */ printf("時間差 = %g秒\n", difftime(tnew, told)); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.5☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include main () { /* 変換時刻用 */ time_t told, tnew; /* tm構造体を用意して初期設定する */ struct tm tmold = {0}, tmnew = {0}; /* 年度情報を設定する */ tmold.tm_year = tmnew.tm_year = 2001 - 1900; /* 月情報を設定する */ tmold.tm_mon = tmnew.tm_mon = 6; /* 日付情報を設定する */ tmold.tm_mday = 5; tmnew.tm_mday = 10; /* mktime()を使ってtime_t型の情報を得る */ told = mktime(&tmold); tnew = mktime(&tmnew); /* difftime()を使って秒数表現の時間差を求める */ printf("時間差 = %g秒\n", difftime(tnew, told)); printf("時間差 = %g分\n", difftime(tnew, told)/60); printf("時間差 = %g時間\n", difftime(tnew, told)/3600); printf("時間差 = %g日\n", difftime(tnew, told)/86400); /* mktime()のふるまいを確認する */ printf("mktime()が再設定した後のtmold構造体のメンバ\n"); printf("tm_year + 1900 = %d\n", tmold.tm_year + 1900); printf("tm_mon = %d\n", tmold.tm_mon); printf("tm_mday = %d\n", tmold.tm_mday); printf("tm_wday = %d\n", tmold.tm_wday); printf("tm_hour = %d\n", tmold.tm_hour); printf("tm_min = %d\n", tmold.tm_min); printf("tm_sec = %d\n", tmold.tm_sec); printf("tm_yday = %d\n", tmold.tm_yday); printf("tm_isdst = %d\n", tmold.tm_isdst); printf("mktime()が再設定した後のtmnew構造体のメンバ\n"); printf("tm_year + 1900 = %d\n", tmnew.tm_year + 1900); printf("tm_mon = %d\n", tmnew.tm_mon); printf("tm_mday = %d\n", tmnew.tm_mday); printf("tm_wday = %d\n", tmnew.tm_wday); printf("tm_hour = %d\n", tmnew.tm_hour); printf("tm_min = %d\n", tmnew.tm_min); printf("tm_sec = %d\n", tmnew.tm_sec); printf("tm_yday = %d\n", tmnew.tm_yday); printf("tm_isdst = %d\n", tmnew.tm_isdst); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.6☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #define STRSIZE 256 main () { char buff[STRSIZE + 1]; char form[] = "現在の時刻: %Y年%m月%d日 %p %I時%M分%S秒"; /* 現在の時刻を得る */ time_t = time(NULL); /* 時刻情報をtm構造体情報に変換する */ struct tm tmtime = *localtime(&t); /* %cを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%c = %c", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* %#cを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%#c = %#c", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* 自分で書式整形する */ /* 時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, form, &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* %xと%Xを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%x %%X = %x %X", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* %#xと%#Xを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%#x %%#X = %#x %#X", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* %jを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%j = %j", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); printf("tmtime.tm_yday = %d\n", tmtime.tm_yday); /* %mを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%m = %m", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); /* %#mを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%#m = %#m", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); printf("tmtime.tm_mon = %d\n", tmtime.tm_mon); /* %wを使って,時刻情報を書式整形してbuffに書き出す */ strftime(buff, STRSIZE + 1, "%%w = %w", &tmtime); /* 整形した文字列を表示する */ printf("%s\n", buff); printf("tmtime.tm_wday = %d\n", tmtime.tm_wday); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.7☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include #include main () { char array[10]; struct tm tmg; time_t tans, tnow; char key = 'T'; int gmtdiff = 0, ret = 0; printf("《簡単な世界時計プログラム》\n" "次の都市のどれかをキー文字で指定してください.【Q = 終了】\n\n" "F = フランクフルト,L = ロンドン,M = メキシコ,N = ニューヨーク\n" "P = パリ,R = ローマ,S = シンガポール,T = 東京\n\nキー入力:"); /* 入力文字を読み取る */ while (scanf("%c", &key) != EOF) { /* アルファベットが入力されたケース */ if (isalnum(key)) /* Enterキーの読み飛ばし */ scanf("%*c"); /* 空打ちなどのケース */ else exit(0); /* 国別の時差情報を設定する */ switch (key) { /* フランクフルト */ case 'F': case 'f': gmtdiff = 1; strcpy(array, "フランクフルトの時刻 = "); break; /* ロンドン */ case 'L': case 'l': gmtdiff = 0; strcpy(array, "ロンドンの時刻 = "); break; /* メキシコ */ case 'M': case 'm': gmtdiff = -6; strcpy(array, "メキシコの時刻 = "); break; /* ニューヨーク */ case 'N': case 'n': gmtdiff = -5; strcpy(array, "ニューヨークの時刻 = "); break; /* パリ */ case 'P': case 'p': gmtdiff = 1; strcpy(array, "パリの時刻 = "); break; /* 終了する */ case 'Q': case 'q': exit(0); /* ローマ */ case 'R': case 'r': gmtdiff = 1; strcpy(array, "ローマの時刻 = "); break; /* シンガポール */ case 'S': case 's': gmtdiff = 8; strcpy(array, "シンガポールの時刻 = "); break; /* 東京 */ case 'T': case 't': strcpy(array, "東京の時刻 = "); gmtdiff = 9; break; /* 東京 */ default: strcpy(array, "現在の時刻 = "); gmtdiff = 9; } /* time()を使ってtime_t型の現在時刻を得る */ tnow = time(NULL); /* gmtime()を使ってtm構造体型の世界標準時刻情報を得る */ tmg = *gmtime(&tnow); /* 時差時間を強制加算する */ tmg.tm_hour += gmtdiff; /* mktime()を使って補正する */ tans = mktime(&tmg); printf("%s%s", array, ctime(&tans)); printf("キー入力:"); } return 0; } ------------------------------------------------------------- ☆☆Sample List 10.8☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include #include /* 指定時間待機する独自のSleep()関数 */ void Sleep(int count) { /* 現在の経過時間 */ clock_t t = clock() * (1000/CLOCKS_PER_SEC); /* 終了用の経過時間 */ clock_t tterm = t + count; /* 終了用の経過時間までループする */ while (t < tterm) { t = clock() * (1000/CLOCKS_PER_SEC); /* tが(clock_t)-1でないことを診断する */ assert(t != (clock_t)-1); /* if (t == (clock_t)-1) return; */ } } main () { clock_t t; /* パーマネントループ */ while (1) { /* 600ミリ秒の間,動作を停止する */ printf("600ミリ秒の間,待機する\n"); Sleep(600); /* ミリ秒単位のラップタイムを表示する */ t = clock() * (1000/CLOCKS_PER_SEC); /* ミリ秒単位表現の経過時間 */ printf("ミリ秒単位表現の経過時間 = %d\n", t); } return 0; } ------------------------------------------------------------- ☆☆Sample List 10.9☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* 指定文字数の文字列のクローンを作成する関数 */ char *CloneStrn(const char *str, size_t n) { /* 文字列strの格納領域を割り当てる */ char *pstr = (char *)malloc(n + 1); /* 失敗した場合 */ if (pstr == NULL) return NULL; /*////////////////////////////////*/ /* 解放用にポインタを保存しておく */ /* parray[dyncount++] = pstr; */ /*////////////////////////////////*/ /* 割り当て領域に文字列strをコピーする */ strncpy(pstr, str, n); /* ヌル文字を付ける */ pstr[n] = '\0'; /* クローンへのポインタを返す */ return pstr; } /* 時刻文字列を時刻情報に変換する関数 */ int AscToTime(time_t *dttime, struct tm *dtmt, const char *sstr) { char array26[26]; struct tm tmtime = {0}; char *p = NULL; int i = 0; char str[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; /* 文字列の長さをチェックする */ if (strlen(sstr) != 25) /* 失敗 */ return 1; /* 文字列をコピーする */ strcpy(array26, sstr); /* strtok()の初回の呼び出し */ p = strtok(array26, " "); /* 曜日情報は無視する */ /* strtok()の2回目の呼び出し */ p = strtok(NULL, " "); for (i = 0; i < 12; i++) { if (!strcmp(p, str[i])) break; } /* 月 */ tmtime.tm_mon = i; /* strtok()の3回目の呼び出し */ p = strtok(NULL, " "); /* 日 */ tmtime.tm_mday = atoi(p); /* strtok()の4回目の呼び出し */ /* 時刻情報 */ p = strtok(NULL, " "); /* 最初の2文字(時刻) */ tmtime.tm_hour = atoi(CloneStrn(p, 2)); p += 3; /* 3文字目からの2文字(分) */ tmtime.tm_min = atoi(CloneStrn(p, 2)); p += 3; /* 5文字目からの2文字(秒) */ tmtime.tm_sec = atoi(CloneStrn(p, 2)); /* strtok()の5回目の呼び出し */ p = strtok(NULL, " "); /* 年 */ tmtime.tm_year = atoi(p) -1900; /* mktime()を使って時間情報を完成する */ *dttime = mktime(&tmtime); *dtmt = tmtime; /* 成功 */ return 0; } main () { char array[] = "Wed Jun 20 00:17:02 2001\n"; struct tm tmtime = {0}; time_t ttime = 0; /* 最初の文字列を表示する */ printf("array = %s\n", array); /* AscToTime()を使って時間情報を得る */ AscToTime(&ttime, &tmtime, array); /* tmtimeの時間を表示する */ printf("tmtime = %s\n", asctime(&tmtime)); /* ttimeの時間を表示する */ printf("ttime = %s\n", ctime(&ttime)); return 0; } ------------------------------------------------------------- ☆☆Sample List 10.10☆☆ ------------------------------------------------------------- /* (C) 2001 Shyozo Kashihara */ #include #include #include #include /* ここに,Sample List 10.9のCloneStrn()関数定義を記述する */ /* ここに,Sample List 10.9のAscToTime()関数定義を記述する */ /* 2つの時刻文字列から差異日数を求める関数 */ int StrCalcDays(const char *nstr, const char *ostr) { struct tm tmtime1 = {0}, tmtime2 = {0}, tmwork = {0}; time_t ttime1 = 0, ttime2 = 0; int years = 0, days = 0; /* AscToTime()を使ってnstrの時間情報を得る */ AscToTime(&ttime1, &tmtime1, nstr); /* AscToTime()を使ってostrの時間情報を得る */ AscToTime(&ttime2, &tmtime2, ostr); /* 負のケースをエラーとする */ if (tmtime1.tm_year < tmtime2.tm_year) return -1; /* 同じ年度のケース */ if (tmtime1.tm_year == tmtime2.tm_year) return (tmtime1.tm_yday - tmtime2.tm_yday); /* 異なる年度のケース */ else { years = tmtime1.tm_year - tmtime2.tm_year; /* 新しい方の通算日数 */ days = tmtime1.tm_yday + 1; /* 1を加算する */ /*/////////////////////////////*/ /* printf("テスト%d\n", days); */ /*/////////////////////////////*/ /* 古い方の年度の残り日数 */ tmwork = tmtime2; tmwork.tm_mon = 11; /* 12月 */ tmwork.tm_mday = 31; /* 31日 */ /* tmworkの情報を更新する */ mktime(&tmwork); /* 求めた年度の残り日数を加算する. これは,減算なので「+1」しない */ days += tmwork.tm_yday - tmtime2.tm_yday; /*/////////////////////////////*/ /* printf("テスト%d\n", days); */ /*/////////////////////////////*/ /* 中間年度の各年度日数を加算する */ while (years > 1) { if (!((2000 - 1900 - ++(tmtime2.tm_year)) % 4)) /* 閏年のケース */ days += 366; else /* 平年のケース */ days += 365; years--; /*/////////////////////////////*/ /* printf("テスト%d\n", days); */ /*/////////////////////////////*/ } return days; } } main () { char array1[] = "Wed Jun 20 00:17:02 2001\n"; char array2[] = "000 Jan 15 00000000 1998\n"; printf("新しい時刻情報の文字列 = %s", array1); printf("古い時刻情報の文字列 = %s", array2); /* StrCalcDays()を使って,差異日数を求める */ printf("差異日数 = %d\n", StrCalcDays(array1, array2)); return 0; } -------------------------------------------------------------