Menu

Category

Archive

logo


C言語の文字列関数

2014-05-05 12:30:00 +0900
  • このエントリーをはてなブックマークに追加

C言語における文字列に関連した関数のまとめ。strcmp(), strcat(), strlen(), strcpy() 等の一般的なもの以外をまとめてみました。

strchr() / strrchr()

この2つの関数は文字列から特定の文字を探し出します。strchr は前(左)から、strrchr は後ろ(右)から検索。もし検索している文字が文字列の中にない場合は、NULLを返します。発見した場合には、その文字へのポインタを返します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	char s1[] = "I am the one, the only one.";
    char *ptr1, *ptr2;
    
    ptr1 = strchr(s1, 'o');
    ptr2 = strrchr(s1, 'o');
    
    printf("String starting at leftmost  'o' is: %s\n", ptr1);
    printf("String starting at rightmost 'o' is: %s\n", ptr2);
    
    /* Find all the o's in s1. Print their addresses. */
    printf("Address of beginning of s1 is: %p\n", s1);
    for (ptr1 = s1; (ptr1 = strchr(ptr1, 'o')) != NULL; ptr1++)
    {
        printf("Address of current 'o' is %p\n", ptr1);
    }
    
    /*=====
     
     String starting at leftmost  'o' is: one, the only one.
     String starting at rightmost 'o' is: one.
     Address of beginning of s1 is: 0x7fff5fbff840
     Address of current 'o' is 0x7fff5fbff849
     Address of current 'o' is 0x7fff5fbff852
     Address of current 'o' is 0x7fff5fbff857
     Program ended with exit code: 0
     
     =====*/

strstr()

strstr() は文字列の中から他の文字列を探し出します。例えば、cat が concatenate に含まれているのかを判断します。 strchr() / strrchr() と同じように、発見した場合にはそのアドレスを返し、そうでない場合には、NULL を返します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    char a[] = "cat";
    char b[] = "cattle";
    char c[] = "concatenate";
    char d[] = "fooboar";
    
    printf("Address of b = %p\n", b);
    printf("Address of c = %p\n", c);
    printf("Address of d = %p\n", d);
    
    printf("Address of a in b = %p\n", strstr(b, a));
    printf("Address of a in c = %p\n", strstr(c, a));
    printf("Address of a in d = %p\n", strstr(d, a));
    
    /*=====
     
     Address of b = 0x7fff5fbff859
     Address of c = 0x7fff5fbff84d
     Address of d = 0x7fff5fbff845
     Address of a in b = 0x7fff5fbff859
     Address of a in c = 0x7fff5fbff850
     Address of a in d = 0x0    // NULL. No cat in foobar
     Program ended with exit code: 0
     
     =====*/

strspn() / strcpn()

この2つの関数は、ある文字セットがある文字列に含まれているかを判断します。例えば、ある文字列が全て数字であるかを判断する際に、役に立ちます。そして、いくつの文字を文字列の中からチェックしたかを返します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  	char sentence[] = "Hello, I am Kazuya!";
    char nonsense[] = "~*%#";
    char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                      abcdefghijklmnopqrstuvwxyz";
    
    int numskipped;
    
    numskipped = strcspn(sentence, letters);
    printf("%d chars skipped over untill a letter was found.\n", numskipped);
    
    numskipped = strspn(sentence, letters);
    printf("%d chars skipped over until a non-letter was found.\n", numskipped);
    
    numskipped = strcspn(sentence, nonsense);
    printf("%d chars skipped over untill a nonsense character was found.\n", numskipped);
    
    
    /*=====
     
     0 chars skipped over untill a letter was found.
     5 chars skipped over until a non-letter was found.
     19 chars skipped over untill a nonsense character was found.
     Program ended with exit code: 0
     
     =====*/

strspn()は与えられた文字セットの要素が、文字列にあるかぎり、文字列の中の次の文字をチェックします。もし、文字セットに含まれていない文字に出くわしたら、そこで何個の文字をスキップしたのかを返します。strscpn()はその逆です。文字セットに含まれていないものをスキップします。

strpbrk()

この関数は、strcspn()と似ています。文字セットに含まれている文字を発見するまで、文字列を検索します。strcspn()と違うのは、いくつの文字をスキップしたのかを返すのではなく、その発見した文字へのポインタを返します。この関数は、区切り文字の位置を見つけたりする際に使われます。strchr()は、一度の検索にある文字1つを検索しますが、strpbrk()は、文字セットの中の全ての文字を検索することができます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 	int num_sentences;
    int count_sentences();
    
    num_sentences = count_sentences();
    printf("Your file had %d sentences in it!\n", num_sentences);
    
    /*=====
     
     19 chars skipped over untill a nonsense character was found.
     Your file had 5 sentences in it!
     Program ended with exit code: 0
          
     Input file is like: 
     
     This is a sentence. I am Kazuya!!! This sentence has the
     number 3.5 in it and it also runs along for more thatn one
     line until it comes to an untimely end. Do you know what
     I mean, Jelly Bean?? Thta's all I've got to say.
     
     =====*/

int count_sentences()
{
    char line[BIGLINE];
    char *mover;
    FILE *fp;
    int num_sentences = 0;
    
    fp = fopen("a.txt", "r");
    
    while (fgets(line, BIGLINE-1, fp))
    {
        for (mover = line; (mover = strpbrk(mover, "?!.")); mover++)
        {
            if (!isdigit(mover[1])) num_sentences++;
            for (; mover[1] == '?' || mover[1] == '!'; mover++) ;
        }
    }
    
    return num_sentences;
    
}

上記のプログラムは、ある文章の中にいくつの文があるかを計算するプログラムです。文は !?. のいずれかで終わると仮定します。. があった場合には、小数点の点の可能性があるので、. の後に数字があるかチェック。また、! と ? で文が終わるケースには、いくつかの !? が続くことも考慮します。

strtok()

strtok()関数は便利な関数です。ユーザーのインプットがカンマ区切りで入力されているような場合に、よく使われます。tokとはトークンのことです。私達が求めているものをトークンと呼ぶようです。下のコードの例では、出力する数字です。strtok()はターゲットの文字列とdelimitersを指定し、delimitersで区切られたトークンを取得します。トークンを見つけることができない(文字列がdelimitersか’\0'しか含まない)場合には、NULLを返します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	char s[] = ",,,,10  , 35, 40";
    char *ptr1 = strtok(s, ",\040\t");
    char *ptr2 = strtok(NULL, ",\040\t");
    char *ptr3 = strtok(NULL, ",\040\t");
    char *ptr4 = strtok(NULL, ",\040\t");
    
    printf("ptr1: %s\n", ptr1);
    printf("ptr2: %s\n", ptr2);
    printf("ptr3: %s\n", ptr3);
    printf("ptr4: %s\n", ptr4);
    
    /*=====
     
     ptr1: 10
     ptr2: 35
     ptr3: 40
     ptr4: (null)
     
     *=====/

strtoke() がはじめに呼ばれた際には、先立つ delimiters をスキップし、token の一番後ろにある delimiters を ‘\0’ にオーバーライトします。そして、token の最初の文字へのポインタを返します。ターゲットとなる文字列を修正してしまうという面で危険な処理ですが、きれいな token を返してくれるということで大変役に立ちます。同じ文字列を続けて処理する際には、ターゲット文字列の指定は NULL です。strtoke() の中で static 変数が使われ処理されています。