2

I am having problems using the strsep() function in C. I want to split a string into two parts. The string contains info about the currently playing song, in ARTIST - TITLE format, so artist and title are separated by one space, one dash and again one space. I want to separate it by this, " - ". "-" won't work because some artists have a dash in their name.

When I try this code with, for example, "Michel Telo - Ai Se Eu Te Pego":

// String is in tmp
while ((token = strsep(&tmp, " - ")) != NULL)
{
    printf("%s\n", token);
}

I get this:

[root@runeaudio ~]# ./board
Michel
Telo


Ai
Se
Eu
Te
Pego

Instead of this:

[root@runeaudio ~]# ./board
Michel Telo
Ai Se Eu Te Pego

Seems like strsep() is dividing delimiter into 3 characters: " ", "-", " " and using OR between them, but I want it to look for " - " as it is. Any idea how to fix this?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
XploD
  • 367
  • 3
  • 15
  • 2
    The separator argument for `strsep`, just as for `strtok`, is a list of characters that are considered delimiters. – M Oehm May 16 '15 at 16:51
  • 1
    Use `strstr()` instead and find the occurrance of the exact `" - "`. – Iharob Al Asimi May 16 '15 at 16:52
  • 1
    [See here](http://stackoverflow.com/questions/29847915/implementing-strtok-whose-delimiter-has-more-than-one-character/29848367#29848367), for example. I'm sure there are more examples of multi-char `strtok` implementations on SO. – M Oehm May 16 '15 at 16:54

2 Answers2

4

The following code, demonstrate how you can split the string, it's not very useful because it does nothing with the tokens except for printing them, but you can see how it works and implement a version that does what you need.

char string[] = "Michel Telo - Ai Se Eu Te Pego";
char *separator = strstr(string, " - ");
if (separator != NULL)
 {
     separator[0] = '\0';
     printf("%s\n", string);

     separator[0] = ' ';
     printf("%s\n", separator + 3);
 }

You can of course use strdup() or similar function to create new strings with the contents of the "tokens".

This is of course not robust, because nothing can ensure that there wont be an artist with " - " in it's name, if it's in the song name however, it's not so bad.

This is a working version, if you don't have strdup() on your platform there will surely be an implementation of it with a different name

#include <string.h>

void extractArtistAndTitle(char *string, char **artist, char **title)
 {
    char *separator;

    if ((string == NULL) || (artist == NULL) || (title == NULL))
        return;
    separator = strstr(string, " - ");
    if (separator != NULL)
     {
        size_t length;

        length  = separator - string;
        *artist = malloc(1 + length);
        if (*artist != NULL)
        {
            memcpy(*artist, string, length);
           (*artist)[length] = '\0';
        }
        *title = strdup(separator + 3);
     }
 }

int main()
{
    char string[] = "Michel Telo - Ai Se Eu Te Pego";
    char *artist;
    char *title;

    extractArtistAndTitle(string, &artist, &title);
    if (artist != NULL)
        printf("Artist: %s\n", artist);
    if (title != NULL)
        printf("Title : %s\n", title);
    free(artist);
    free(title);

    return 0;
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • And it has the additional benefit of being portable - Windows has no `strsep` afaik. – user4520 May 16 '15 at 16:55
  • 4
    @szczurcio: `strsep()` indeed is not a Standard C function. – chqrlie May 16 '15 at 17:02
  • Thank you, your solution works! I know that it's not really robust but so far, there's nothing I can do. I'm using Raspberry Pi as network music player and I'm getting current track info from MPD, which returns song info like this, all in one line in ARTIST - TITLE format and I want to split it to show it on a 2-line LCD display, artist in first line and song name in second line. – XploD May 16 '15 at 17:49
  • if the malloc fails, then this line: '(*artist)[length] = '\0';' will be modifying a byte at a small offset from zero. This will cause a seg fault event. Suggest including all the (*artist) statements within the 'if (NULL == artist)' code block – user3629249 May 16 '15 at 20:02
  • @user3629249 what line? why don't you use a user name the one can remember? – Iharob Al Asimi May 16 '15 at 20:03
  • @iharob, as with many things on these web sites. (at least *I*) I have not found any explanation of how to change that name from the default. Usable info would be appreciated. – user3629249 May 16 '15 at 20:06
  • @chqrlie, I'm running ubuntu linux 14.04 and strsep() came with it. the prototype is in the string.h header file. – user3629249 May 16 '15 at 20:08
  • @user3629249 thanks, I didn't notice that, and yes `glibc()` has a `strsep()` it's not **standard** though. – Iharob Al Asimi May 16 '15 at 20:11
  • @iharob, my comment references the next to last code statement in the function: 'extractArtistAndTitle()' posted with this answer – user3629249 May 16 '15 at 20:14
  • @iharob, my fumble fingers. I meant the code block beginning with: ''if (NULL != artist)'' – user3629249 May 20 '15 at 00:38
0

Here is a code using which you will only get the strings depending on the '-'

#include <stdio.h>

int main()
{
    char token[100];
    int i,j=0,flag=0;
    char tmp[]="Michel Telo - Ai Se Eu Te Pego";
    for(i=0;tmp[i]!='\0';i++)
    {
        if((tmp[i]>='a' && tmp[i]<='z') || (tmp[i]>='A' && tmp[i]<='Z') || (tmp[i]==32 && !isalpha(tmp[i+1])))
        {
            flag=0;
            token[j++]=tmp[i];
            continue;
        }
        else if(flag==0 && tmp[i]=='-')
        {
            token[j]='\0';
            j=0;
            flag=1;
            printf("%s\n",token);
        }
    }
    token[j]='\0';
    printf("%s\n",token);
    return 0;
}
Subinoy
  • 478
  • 7
  • 22