Jav
Jav

Reputation: 1607

sscanf parse formatted string

I would like to read a string containing a undefined amount of suffixes, all separated by ;

example 1: « .txt;.jpg;.png »

example 2: « .txt;.ods;_music.mp3;.mjpeg;.ext1;.ext2 »

I browsed the web and wrote that piece of code that doesn't work:

char *suffix[MAX]; /* will containt pointers to the different suffixes */
for (i = 0; i < MAX ; i++)
{
    suffix[i] = NULL;
    if (suffix_str && sscanf(suffix_str,"%[^;];%[^\n]",suffix[i],suffix_str) < 1)
        suffix_str = NULL;
}

After the first iteration, the result of sscanf is 0. Why didn't it read the content of the string?

How should be parsed a string containing an undefined number of elements? Is sscanf a good choice?

Upvotes: 2

Views: 632

Answers (2)

WhozCraig
WhozCraig

Reputation: 66194

First, as covered in general comment, you're invoking undefined behavior by using the same buffer as both a source input and destination target for sscanf. Per the C standard, that isn't allowed.

The correct function to use for this would likely be strtok. A very simply example appears below.

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

int main()
{
    char line[] = ".txt;.ods;_music.mp3;.mjpeg;.ext1;.ext2";
    size_t slen = strlen(line); // worst case
    char *suffix[slen/2+1], *ext;
    size_t count=0;

    for (ext = strtok(line, ";"); ext; ext = strtok(NULL, ";"))
        suffix[count++] = ext;

    // show suffix array entries we pulled
    for (size_t i=0; i<count; ++i)
        printf("%s ", suffix[i]);
    fputc('\n', stdout);
}

Output

.txt .ods _music.mp3 .mjpeg .ext1 .ext2 

Notes

  • This code assumes a worst-case suffix count to be half the string length, thereby a list of single character suffixes split on the delimiter.
  • The suffix array contains pointers into the now-sliced-up original line buffer. The lifetime of usability for those pointers is therefore only as long as that of the line buffer itself.

Hope it helps.

Upvotes: 3

askmish
askmish

Reputation: 6674

There are several ways to tokenize from a C string. In addition to using strtok and sscanf you could also do something like this:

char *temp = suffix_str;
char *suffix[i];
for (int i = 0; i < MAX; i++)
{
    int j = 0;
    char buf[32];
    while (*temp != '\0' && *temp != '\n' && *temp != ';')
    {
        buf[j++] = *temp;
        temp++;
    }
    buf[j] = 0;

    if (*temp == ';') temp++;

    suffix[i] = malloc((strlen(buf) + 1) * sizeof(char));
    //handle memory allocation error
    strcpy(suffix[i], buf);
}

Upvotes: 0

Related Questions