文字、文字列探索

strchrや、strstrは、string.hをインクルードすれば、利用できます。
しかし正しく利用するには、その関数がどのように作られたものかを理解する必要があります。 以下では、これら関数の定義例と利用例を紹介します。

文字の探索関数 strchr

文字列の中から文字を探して、見つかった文字コードが存在するアドレス (char *)型を返します。
内部では、文字列の先頭から後方を順番に調べる繰り返しが行なわれます。 文字列の終端まで見つからない場合は、NULLを返します。
以下に定義例と実行例を示します。    の部分が出力結果です。

#include <stdio.h>
char * strchr(char * s, int c)
{
	while( *s != '\0' && *s != c) {/* 終端でなく、また、文字が見つからない間、繰り返す */
		s++;
	}
	if( *s == c ) { /* c の文字が見つかった */
	
		return s;	/* 見つかった位置のポインタを返す */
		
	}
	return NULL;/* 見つからない */
}
main()
{
	char a[] = "Abc0 abc1 abc2";
	
	char * p = strchr( a , 'a');	/* aが指し示す文字列から 'a' の文字を探す */

	puts( p );		/* 見つかった位置から表示 	abc1 abc2	*/
	p = strchr( p+1, 'a');	/* 見つかった次の位置から探す */
	puts( p );		/* 見つかった位置から表示 	abc2		*/
}

見つからない場合に、NULLを返す関数です。NULLは、どこも指し示していないポインタなので、 本来はその場合のifやwhileなど制御構造を使ったプログラミングが必要です。
(NULLが記憶されるpを使って、puts( p )を実行すれば、実行エラーです


文字列の探索関数 strstr

文字を探す場合は、探したい文字列全体の等価チェックができません。
そこでまず、探したい文字列の1文字で探します。 以下では、探したい文字列先頭の文字 *cpがsの文字列中にあるか調べています。
次に見つかったら、残りの部分が合っているかを調べる処理を行ないます。
以下では、先頭文字が見つかったs1と、cpが記憶されるs2で、 cpが指し示す全ての文字が合っているか調べる繰り返し
です。

#include <stdio.h>
char * strstr(char * s, char * cp)
{
	char *s1, *s2;

	if( *cp == '\0') return s; /* cp の文字列長が0なら s を返す */ 

	while( *s != '\0'){
		while(*s != '\0' && *s != *cp) {/* 終端でなく、また、文字が見つからない間、繰り返す */
			s++;
		}
		if(*s == '\0') return NULL;/* 見つからない */
		s1 = s;
		s2 = cp;
		while ( *s1 == *s2 && *s1 != '\0'){ /* s1とcpの部分文字列が一致するか */
			s1++;
			s2++;
		}
		if( *s2 == '\0'){/* cp の文字列は、全て一致した */
			return s;
		}
		s++; /* 次の位置から、調べ直す */
	}
	return NULL;/* 見つからない */
}
main()
{
	char a[] = "Abc0 abc1 abc2";
	
	char * p = strstr( a , "bc");	/* aが指し示す文字列から 'a' の文字を探す */

	puts( p );		/* 見つかった位置から表示 	bc0 abc1 abc2	*/
	p = strstr( p+1, "bc"); /* 見つかった次の位置から探す */
	puts( p );		/* 見つかった位置から表示 	bc1 abc2	*/
	p = strstr( p+1, "bc"); /* 見つかった次の位置から探す */
	puts( p );		/* 見つかった位置から表示 	bc2		*/
}

C言語では、文字列の一部を比較するstrncmp関数があり、strcmp関数に対して比較文字(byte)数を 与える引数が1つ多い関数です。
strcmp関数は、終端の'\0'まで合っているか調べるますが、strncmp関数は、 比較文字(byte)数nが、文字列より小さい時、その範囲内だけで比較結果が得られます。
このstrncmp関数と、strchr関数を利用した場合のstrstr関数定義例を示します。
strchr関数で、探したい文字列先頭の文字 *cpがsの文字列中にあるか調べ、 見つかった位置から、残りの部分文字列が合っているかsrncmp関数で調べています

char * strstr(char * s, char * cp)
{
	int n = strlen(cp);
	char *s1;

	if( n == 0 ) return s; /* cp の文字列長が0なら s を返す */ 

	while( *s != '\0'){
		s1 = strchr(s , *cp);	/* cp先頭文字を見つける */
		if( s1 == NULL ) return NULL;/* 見つからない時のreturn */

		if(strncmp(s1 , cp , n ) == 0){/* s1とcpの部分文字列が一致するか */
			return s1;
		}
		s++; /* 次の位置から、調べ直す */
	}
	return NULL;/* 見つからない */
}

なお文字列探索は、もっと高速に調べるアルゴリズムがあるので、実際は上記のような作りでない可能性があります。 上記は、単純な考え方で作る方法です。

引数のポインタ変数を変更しないstrstr定義例

上記strstrと同じ機能を行なわせる別の定義例を、以下に示します。
*のポインタ演算子を使わずに、[]の配列演算子を使う変更をしてください。つまり、添え字で位置を指定する形態です。
上記プログラムの char *s1, *s2; の代わりに、int i1, i2 , i = 0 と宣言しました。 s1の役割をi1、s2の役割をi2で行なわせてください。また、sを変更しない代わりにiで制御ください。 (なお添え字変更は、後置インクリメントを使ってください)

←編集 入力後に クリックください。