web-dev-qa-db-ja.com

strsep()の使用法とその代替

_#include <stdio.h>
#include <string.h>

int main() {

char *slogan = "together{kaliya} [namak]";
char *slow_gun = strdup(slogan);

char *token = strsep(&slow_gun, "{");

printf ("\n slow_gun: %s\n token: %s\n", slow_gun, token);

return 0;
}
_

私がそれを実行するとき:

_$ cc -o try try_strsep.c
$ ./try

 slow_gun: kaliya} [namak]
 token: together  
_

しかし、とき、私はchar * sloganを次のように変更します。

_char *slogan = "kalia} [namak]";
_

同じプログラムを実行します。

_$ vi try_strsep.c 
$ cc -o try try_strsep.c
$ ./try

 slow_gun: (null)
 token: kalia} [namak]
_

私のQuestionなので、strsep()を使用していて、入力文字列に探しているパターンがない場合、strsep()の戻り値はwrongです。 strsep()がパターンを見つけられなかったかどうかを検証できる唯一の方法は、if (slow_gun == NUll)をチェックすることです。

_char *slogan = "together{"_がある場合、strseptokenを正常に返しますが、_slow_gun_を空白に戻します(nullではありません)

_$ cc -o try try_strsep.c
$ ./try

 slow_gun: 
 token: together
_

このIFチェックを回避し、関数に依存してsubstrを返し、存在しない場合はNULLを返す方法はありますか?

6
hari

いいえ、チェック_slow_gun == NULL_を回避する方法はありません。 ここに説明がありますstrsepの動作の:

_char *strsep(char **stringp, const char *delim);
_

[〜#〜]説明[〜#〜]
_*stringp_がNULLの場合、strsep()関数はNULLを返し、他には何もしません。それ以外の場合、この関数は文字列_*stringp_の最初のトークンを検索します。ここで、トークンは文字列delimの記号で区切られます。このトークンは、区切り文字をヌルバイト(_'\0'_)で上書きすることによって終了し、_*stringp_はトークンを通過するように更新されます。区切り文字が見つからなかった場合、トークンは文字列全体_*stringp_と見なされ、_*stringp_はNULLになります。

戻り値
strsep()関数は、トークンへのポインターを返します。つまり、_*stringp_の元の値を返します。

したがって、一致するものが見つからない場合、strsepは元の文字列へのポインタを返し、_slow_gun_入力をNULLに設定します。

区切り文字が文字列の最後の文字である場合、その文字は「\ 0」で上書きされ、_slow_gun_は次の文字に設定されます。これはたまたま元の文字列を終了する「\ 0」です。これが、printステートメントが空の文字列を出力する理由です。

[〜#〜] note [〜#〜]strdupを誤って使用しているため、発信者はfreeその関数によって返されるポインタ。

12
Praetorian

strsep()の戻りが間違っている

そうではありません。 strsep()は、最初に見つかったトークンを返します。文字列の先頭は、定義上、最初のトークンです。この場合、トークンを終了する区切り文字が見つからなかっただけです(したがって、文字列の残りの部分がトークンになります)。

strsep()は、「パターンの検索」に使用するためのものではありません。区切り文字のセットに基づいてトークンを区切るために使用されます。文字を検索する場合は、strchr()またはstrpbrk()を使用します。

7
Michael Burr

strsepは正しく動作しています manページ から:

strsep()関数は、_*stringp_によって参照される文字列内で、文字列delim(または終了する_\0_文字)内の任意の文字の最初の出現を検索し、それを_\0_。区切り文字(または文字列の終わりに達した場合はNULL)の次の文字の位置は、_*stringp_に格納されます。 _*stringp_の元の値が返されます。

2番目のケースは正しい-区切り文字が見つからないため、最初のパラメーターはNULLを指すように設定され、元の文字列は戻ってきた。あなたが言うように、これを検出するにはif (slow_gun == NUll)をチェックする必要があります。

(ちなみに、それは変数名のひどく紛らわしい選択です)。

2
John Carter