Использование strsep () и его альтернатива - PullRequest
5 голосов
/ 29 июля 2011
#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 * на:

char *slogan = "kalia} [namak]";

и выполняю ту же программу:

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

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

Мой Вопрос , поэтому, когда я использую strsep (), а входная строка не имеет искомого шаблона, возвращаемое значение strsep () равно неправильно .Единственный способ проверить, не удалось ли strsep () найти шаблон, - это проверить if (slow_gun == NUll).

Если у меня char *slogan = "together{", то strsep успешно вернет token, но вернет slow_gun впусто (не null)

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

 slow_gun: 
 token: together

Есть ли способ, которым я мог бы избежать этой проверки IF и полагаться на функцию, чтобы вернуть мне substr, а если его нет, вернуть NULL?

Ответы [ 3 ]

12 голосов
/ 29 июля 2011

Нет, нет способа избежать проверки 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 для указателя, возвращенного этой функцией.

7 голосов
/ 29 июля 2011

возвращение strsep () неверно

Это неправильно.strsep() возвращает первый найденный токен - начало строки по определению является первым токеном.Просто в этом случае не было найдено разделителя для завершения токена (поэтому оставшаяся часть строки является токеном).

strsep() не предназначен для использования для «поиска шаблона» - этоиспользуется для разделения токенов на основе набора разделителей.Если вы хотите найти персонажа, используйте strchr() или strpbrk().

2 голосов
/ 29 июля 2011

strsep ведет себя корректно - из справочной страницы :

Функция strsep() находит в строке, на которую ссылается *stringp, первое вхождение любого символа в строке разделителя (или завершает символ \0) и заменяет его на \0. Расположение следующий символ после символа разделителя (или NULL, если конец строка была достигнута) сохраняется в *stringp. Первоначальная стоимость *stringp возвращается.

Второй случай является правильным - поскольку разделитель не найден, первый параметр имеет значение NULL и возвращается исходная строка. Как вы говорите, вы должны проверить if (slow_gun == NUll), чтобы обнаружить это.

(кстати, это ужасно запутанный выбор имен переменных).

...