-1

I am currently reading a file in C that contains a list of songs in the format

Track ID<SEP>Song ID<SEP>Artist Name<SEP>Song Title

I am struggling to understand on how to use strtok() to get just the song artist and song title after the <SEP>.

Any help will be appreciated.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • Posting the code you have so far and what its problem is, along with a few lines from the data file, might help to solve your problem. – Weather Vane Apr 06 '15 at 22:23
  • Going to have to be more specific than that. Any code? Example line, or string to parse? What have you tried so far? – ryyker Apr 06 '15 at 22:24
  • Track IDSong IDArtist NameSong Title. This is format of the song. I just noticed that the tags were removed – Kemoy Campbell Apr 06 '15 at 22:27
  • 1
    is the '' a single character? – user3629249 Apr 06 '15 at 22:30
  • Yeah. I need to look through for "<>" and take only the artist name and song title. – Kemoy Campbell Apr 06 '15 at 22:32
  • I would use `strstr()` to look for the separaters. But previous question about `strtok()` here http://stackoverflow.com/questions/3889992/how-does-strtok-split-the-string-into-tokens-in-c – Weather Vane Apr 06 '15 at 22:36
  • Weather, I dont need every <> I just need the one at artist name and song title that is all. The reason why I post here because I could not figure out how to do just that. I am not asking how strok work or what it does but how to just extract specific part instead of the whole <> – Kemoy Campbell Apr 06 '15 at 22:38
  • I apologise. Since your question asks "I am struggling on understanding on how to use strtok", I thought that is the question. – Weather Vane Apr 06 '15 at 22:42
  • but i specified stated, how to use strok to get just the song artist and song title after the the problem is that stack overflow removed the tag in the question. – Kemoy Campbell Apr 06 '15 at 22:44
  • You can't, you use `strtok()` to parse the string until you reach the fields you want, as the below answer. – Weather Vane Apr 06 '15 at 22:45

2 Answers2

2

If I understand you are reading each line from a file, and then tokenizing them to retrieve the song, artist and title, calling strtok in a for loop while keeping a field index will do what you need:

#define MAXS 128
#define MAXL 1024
...
char song[MAXS] = {0};
char artist[MAXS] = {0};
char title[MAXS] = {0};
char buf[MAXL] = {0};
...

while ((fgets (buf, 254, file)) != NULL)
{
    char *p = buf;
    fldidx = 0;     /* field index */

    for (p = strtok (buf, <sep>); p != NULL; p = strtok (NULL, <sep>))
    {
        if (fldidx == 1) strncpy (song, p, strlen (p)+1);
        if (fldidx == 2) strncpy (artist, p, strlen (p)+1);
        if (fldidx == 3) strncpy (title, p, strlen (p)+1);

        fldidx++;
    }
}

Adjust MAXS, MAXL as needed. (quit changing the # and order of fields :)

Note: <sep> is a generic placeholder that must be replaced by a valid delimiter string for strtok.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • your post confirm that using an index is the way to go. I have index in my original code but I was not sure if there is a more efficient way of dealing with strtok extraction. – Kemoy Campbell Apr 06 '15 at 22:56
  • Not really any more efficient way. When you get a large number of fields, you can either continue with the `if`'s or just `switch (fldidx)` and the act on the `case`(s) you need. – David C. Rankin Apr 06 '15 at 22:58
  • `strncpy` used this way is the same as `memcpy` and does not copy the final '\0'. output may become incorrect for all but the first line. `strtok` is bogus here too: if you fix the syntax, it will stop at '<', 's', 'e', 'p' and '>', not quite what is expected. – chqrlie Apr 06 '15 at 23:38
  • 1
    The `` is a generic representation of some separator to he supplied by the OP. (unless he changed the question again) Good catch on `strncpy`. – David C. Rankin Apr 06 '15 at 23:43
1

after getting the line into a buffer...

char *TrackId = strtok( buffer, "<sep>" );
if( NULL != TrackId )
{
    char *SongID = strtok( NULL, "<sep>: );
    if( NULL != SongID )
    {
        char *ArtistName = strtok( NULL, "<sep>" );
        if( NULL != ArtistName )
        {
            char *SongTitle = strtok( NULL, "<sep>" );
            if( NULL != SongTitle )
            { // then have extracted all fields from line
                // process those fields
            }
         }
     }
  }
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • I already have the lines in buffer and all that. I dont need song id, trackid just artist name and song title that is all – Kemoy Campbell Apr 06 '15 at 22:42
  • 1
    Well discard the rest. – Weather Vane Apr 06 '15 at 22:44
  • You seem to make a confusion between `strtok` and `strstr`. `strtok` does not work the way you think. It is a pretty bad choice anyway for parsing this XML snipplet, `strstr` would be much more appropriate. – chqrlie Apr 06 '15 at 23:29