strsep() usage and its alternative
Asked Answered
L

3

6
#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;
}

when I execute it:

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

 slow_gun: kaliya} [namak]
 token: together  

But when, I change the char *slogan to:

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

and execute the same program:

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

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

My Question is, so when I use strsep() and input string does not have the pattern I am looking for, the return of strsep() is wrong. The only way I can validate whether strsep() could not find the pattern is to check if (slow_gun == NUll).

If I have char *slogan = "together{" then strsep would successfully return token but returns slow_gun to blank (not null)

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

 slow_gun: 
 token: together

Is there a way I could avoid this IF check and rely on the function to return me the substr and if its not there, return NULL?

Lykins answered 28/7, 2011 at 21:29 Comment(4)
You need to free the string returned by strdupChelyabinsk
@Praetorian: You had me into tears. I agree to you but is that going to help me with my question?Lykins
Helping someone avoid memory leaks always helps :-) My answer below should help you with your question.Chelyabinsk
You made me think of this talk goo.gl/ks0Oe :)Peugia
C
14

No, there's no way to avoid the check slow_gun == NULL. Here's a description of strsep's behavior:

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

DESCRIPTION
If *stringp is NULL, the strsep() function returns NULL and does nothing else. Otherwise, this function finds the first token in the string *stringp, where tokens are delimited by symbols in the string delim. This token is terminated by overwriting the delimiter with a null byte ('\0') and *stringp is updated to point past the token. In case no delimiter was found, the token is taken to be the entire string *stringp, and *stringp is made NULL.

RETURN VALUE
The strsep() function returns a pointer to the token, that is, it returns the original value of *stringp.

So, if no match is found strsep returns a pointer to the original string and sets the slow_gun input to NULL.

If the delimiter is the last character in the string, that character is overwritten by '\0' and slow_gun is set to the following character, which happens to be the '\0' terminating the original string. This is why print statement prints an empty string.

NOTE You're using strdup incorrectly, the caller is responsible for calling free on the pointer returned by that function.

Chelyabinsk answered 28/7, 2011 at 21:43 Comment(0)
T
7

the return of strsep() is wrong

That's not right. strsep() returns the first token it finds - the beginning of the string is by definition the first token. It's just that no delimiter has been found to terminate the token in this case (so the remainder of the string is the token).

strsep() is not intended to be used to 'find a pattern' - it's used to separate tokens based on a set of delimiters. If you want to find a character, use strchr() or strpbrk().

Taxpayer answered 28/7, 2011 at 21:41 Comment(0)
S
2

strsep is behaving correctly - from the man page:

The strsep() function locates, in the string referenced by *stringp, the first occurrence of any character in the string delim (or the terminating \0 character) and replaces it with a \0. The location of the next character after the delimiter character (or NULL, if the end of the string was reached) is stored in *stringp. The original value of *stringp is returned.

The second case is correct - since the delimeter isn't found the first parameter is set to point at NULL and the original string is returned. As you say, you need to check for if (slow_gun == NUll) to detect this.

(incidentally, that's a horribly confusing choice of variable names).

Soviet answered 28/7, 2011 at 21:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.