Linux講座にようこそ。このページは「C言語プログラミング入門 - 第14章.ライブラリ関数 - 文字列処理ライブラリ」です。

C言語プログラミング入門

14. ライブラリ関数(15/36) - 文字列処理ライブラリ(4/5)

14.22 文字セットから成る文字列か否かのチェック関数

14.22.1 strspn関数

strspn関数は文字列の先頭からの文字が、指定された文字の組み合わせ(文字セット)から成る文字列か否かをチェックします。

【表14-2-16】 strspn関数
形式#include <string.h>
size_t strspn(const char *str, const char *keyset);
返り値文字セットと一致した文字の数を返します。一致しなかった場合は0を返します。
引数
const char *str
チェック対象の文字列を指定します。
const char *keyset
文字セットを指定します。

14.22.2 strcspn関数

trcspn関数は文字列の先頭からの文字が、指定された文字の組み合わせ(文字セット)以外から成る文字列か否かをチェックします。

【表14-2-17】 strcspn関数
形式#include <string.h>
size_t strcspn(const char *str, const char *keyset);
返り値文字セット以外と一致した文字の数を返します。一致しなかった場合は0を返します。
引数
const char *str
チェック対象の文字列を指定します。
const char *keyset
文字セットを指定します。

14.22.3 例題

テキストファイル中の英字(a〜z、A〜Z、半角スペース)の部分だけを抽出して表示します。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define LINE_MAX    1024
  4.  
  5. int main(void)
  6. {
  7.     char *SubStr(char *Str, int Start, int Length);
  8.  
  9.     FILE    *fp;
  10.     char    in_file[] = "./DATA/ex14_2_6.dat";
  11.     char    line[LINE_MAX];
  12.     char    key_set[] ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ";
  13.     char    *p_line;
  14.     int     len;
  15.  
  16.     if((fp = fopen(in_file, "r")) != NULL)
  17.     {
  18.         /* EOFでない間、繰り返す */
  19.         while(fgets(line, LINE_MAX, fp) != NULL)
  20.         {
  21.             /* 行の最後まで */
  22.             for(p_line = line; *p_line != '\0'; )
  23.             {
  24.                 /* 英字とスペースのチェック */
  25.                 len = strspn(p_line, key_set);
  26.                 if(len > 0)
  27.                 {
  28.                     /* 英字とスペースから成る文字列を表示 */
  29.                     printf("%s\t", SubStr(p_line, 0, len));
  30.                     p_line += len;
  31.                 }
  32.                 else
  33.                 {
  34.                     ++p_line;
  35.                 }
  36.             }
  37.             printf("\n");
  38.         }
  39.         fclose(fp);
  40.     }
  41.     else
  42.     {
  43.         printf("%sがオープン出来ませんでした。", in_file);
  44.     }
  45.  
  46.     return 0;
  47. }
  48.  
  49. /* 文字列中の指定された位置の文字列を取り出す */
  50. char *SubStr(char *pStr, int pStart, int pLength)
  51. {
  52.     static char buff[LINE_MAX];
  53.     char       *p_buff = buff;
  54.  
  55.     for(pStr += pStart; *pStr != '\0' && pLength > 0; --pLength)
  56.     {
  57.         *(p_buff++) = *(pStr++);
  58.     }
  59.     *p_buff = '\0';
  60.  
  61.     return buff;
  62. }
$ cat ./DATA/ex14_2_6.dat
1,Merry Husky,67,188,A
2,Kuma Mix,98,176.5
3,Hana Shiba,43.2,156.5,AB
4,ken Mix,55.5,167.5
5,Taro Bull,75.7,166.5,A
$
$ ./ex14_2_7.prg
Merry Husky     A
Kuma Mix
Hana Shiba      AB
ken Mix
Taro Bull       A
$
25行目
入力した文字列が英字とスペース(文字セット)から成る文字列かをチェックします。
29行目
文字セットと一致した文字列を表示します。

14.23 文字列のロケールに基づく比較及び、変換関数

14.23.1 strcoll関数

strcoll関数は現在のロケール(地域情報)に従い二つの文字列を比較します。半角文字や全角の英数字・ひらがな・カタカナの場合はstrcmp関数やstrncmp関数と結果は同じになります。これは、文字セット中での文字の順序が辞書式の文字の順序(コードの値による順序)と同じだからです。

strcoll関数は日本語の漢字のように、文字セット中での文字の順序が辞書式の文字の順序と異なる場合がありかつ、文字セット中での文字の順序により大小関係を得たい場合に使用します。単に、等しいか否かを判定したい場合は、strcmp関数やstrncmp関数を使用した方がよいでしょう。

また、ロケールのデフォルト(プログラムの起動時)は「C」が設定されており、この状態ではstrcmp関数やstrncmp関数と同じ結果になります。従って、strcoll関数を使用する前に、setlocale関数でロケール(LC_COLLATEカテゴリ)を設定しておく必要が有ります。

【表14-2-18】 strcoll関数
形式#include <string.h>
int strcoll(const char *str1, const char *str2);
返り値strcmp関数やstrncmp関数と同じく、比較結果を次のような値で返します。
  • str1がstr2よりも小さい場合は負の整数値を返します。
  • str1とstr2が等しい場合は0を返します。
  • str1がstr2よりも大きい場合は正の整数値を返します。
引数
const char *str1
比較する文字列を指定します。
const char *str2
比較する文字列を指定します。

14.23.2 strxfrm関数

strxfrm関数はstrcoll関数とstrcmp関数(又は、strncmp関数)で比較した結果が同じになるように文字列を変換します。変換はstrcoll関数と同じくロケールに従います。

【表14-2-20】 strxfrm関数
形式#include <string.h>
size_t strxfrm(char *dest, const char *src, size_t n);
返り値変換後の文字列(dest)のヌル文字を含まない文字数を返します。第3引数nより大きな値の場合は結果は不定です。
引数
char *dest
変換結果を格納する文字列領域を指定します。
const char *src
変換する文字列を指定します。
size_t n
変換結果の文字数を指定します。(第1引数destに代入する文字数です。)

14.23.3 例題

2つの文字を入力して、strcoll関数とstrcmp関数で比較して、その結果を表示します。実行結果を見ていただくと分かる通り、同じ文字でも結果が異なることが有ります。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <locale.h>
  4. #define BUFFSIZE    10
  5.  
  6. int main(void)
  7. {
  8.     char    str1[BUFFSIZE];
  9.     char    str2[BUFFSIZE];
  10.     int     cmp;
  11.  
  12.     /* ロケールの設定 */
  13.     if(setlocale(LC_COLLATE, "ja_JP.UTF-8") == NULL)
  14.     {
  15.         printf("ロケールの設定が出来ませんでした。");
  16.         return 1;
  17.     }
  18.  
  19.     printf("1文字目を入力してください ==> ");
  20.     scanf("%s", str1);
  21.     printf("2文字目を入力してください ==> ");
  22.     scanf("%s", str2);
  23.  
  24.     /* strcoll関数で比較 */
  25.     cmp = strcoll(str1, str2);
  26.     printf("strcoll : ");
  27.     if (cmp == 0)
  28.     {
  29.         printf("%s = %s\n", str1, str2);
  30.     }
  31.     else if (cmp > 0)
  32.     {
  33.         printf("%s > %s\n", str1, str2);
  34.     }
  35.     else
  36.     {
  37.         printf("%s < %s\n", str1, str2);
  38.     }
  39.  
  40.     /* strcmp関数で比較 */
  41.     cmp = strcmp(str1, str2);
  42.     printf("strcmp  : ");
  43.     if (cmp == 0)
  44.     {
  45.         printf("%s = %s\n", str1, str2);
  46.     }
  47.     else if (cmp > 0)
  48.     {
  49.         printf("%s > %s\n", str1, str2);
  50.     }
  51.     else
  52.     {
  53.         printf("%s < %s\n", str1, str2);
  54.     }
  55.  
  56.     return 0;
  57. }
$ ./ex14_2_8.prg
1文字目を入力してください ==> 
2文字目を入力してください ==> 
strcoll : あ < い
strcmp  : あ < い
$
$ ./ex14_2_8.prg
1文字目を入力してください ==> 
2文字目を入力してください ==> 
strcoll : 阿 < 哀 ← 「阿」の方が小さい
strcmp  : 阿 > 哀 ← 「阿」の方が大きい
$
$ ./ex14_2_8.prg
1文字目を入力してください ==> 
2文字目を入力してください ==> 
strcoll : 哀 < 愛
strcmp  : 哀 < 愛
$
$ ./ex14_2_8.prg
1文字目を入力してください ==> 
2文字目を入力してください ==> 
strcoll : ♂ < ♀
strcmp  : ♂ > ♀
$
13行目
ロケールの設定を行います。ここではFedoraの標準の「ja_JP.UTF-8」を指定しています。
25行目
strcoll関数で比較して、結果を変数cmpに代入します。
41行目
strcmp関数で比較して、結果を変数cmpに代入します。