4

I tried to parse a string like:

"12 13 14   16"

for 5 numbers in an array.

I use strtok(string_above, " "), but strtok() will take these three blank characters as one. What can I do to prevent it?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
KennyYang
  • 235
  • 2
  • 13
  • 7
    By not using strtok. strtok will treat a series of delimiters the same as a single delimiter. – interjay Dec 01 '15 at 15:46
  • 3
    Use `strchr()` instead. Read [`strchr(3)`](http://man7.org/linux/man-pages/man3/strchr.3.html). You will have a lot of control on the tokenization. – Iharob Al Asimi Dec 01 '15 at 15:49
  • 4
    What is the expected result? An array with `{12, 13, 14, 0, 16}`? – M Oehm Dec 01 '15 at 15:49
  • does the array not have any initialised value for that space? I mean if the array is responsible for this string. – Naman Dec 01 '15 at 15:50
  • Why don't you use the `strtok` in a loop until it returns `NULL` ? See this http://www.cplusplus.com/reference/cstring/strtok/ – Uchia Itachi Dec 01 '15 at 15:52
  • yes, I expect the array should look like {12, 13, 14, 0 ,16}, but I want to print out an alert if that one is blank. – KennyYang Dec 01 '15 at 15:52
  • @KennyYang : and what is the expected output? – Naman Dec 01 '15 at 15:53
  • 2
    So there are really three blanks. The first and last ones are delimiters and the one in between means zero? That's not a sane format. What if the string contains just two blanks in a row? – M Oehm Dec 01 '15 at 15:55
  • I expect to parse this string one by one, so it would only show one alert. And I can use a for loop to print out: 12, 13, 14, 0, 16. – KennyYang Dec 01 '15 at 15:56
  • 4
    Even though you can do this, I don't recommend it. Using a blank as a separator and as a blank simultaneously is not a good thing because it's very ambiguos. – Iharob Al Asimi Dec 01 '15 at 15:57
  • Yes, go for `strchr()`. – alk Dec 01 '15 at 15:57
  • 1
    Possibly a duplicate to http://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c – Naman Dec 01 '15 at 15:59
  • I might assume there will no 2 blanks in my case. – KennyYang Dec 01 '15 at 15:59
  • 2
    At the minimum, you should look at [What are the differences between `strtok()` and `strsep()` in C?](https://stackoverflow.com/questions/7218625/) However, if you blithely applied `strsep()`, you'd find it thinks you have two empty fields sandwiched between the three spaces, rather than one field consisting of only a blank — because the blanks are separators and not field values. What you're seeking is somewhat outside the normal behaviour; you'll likely have to roll your own code — probably using `strchr()` (or perhaps `strcspn()` or `strpbrk()`). – Jonathan Leffler Dec 01 '15 at 16:00
  • 2
    @nullpointer: I think the SO 9210528 question is only loosely related and does not cover the specific case in this question. – Jonathan Leffler Dec 01 '15 at 16:05
  • @JonathanLeffler : http://stackoverflow.com/a/9210560/1746118 the answer reads about consecutive delimiters in strtok() – Naman Dec 01 '15 at 16:07

1 Answers1

2

I did enjoy doing this, this might be what you need. I didn't test it extensively but it passed a simple test.

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

int
main(void)
{
    char string[] = "12 13 14   16";
    char *current;
    char *next;
    int done;
    current = string;
    done = 0;
    while (done == 0)
    {
        next = strchr(current, ' ');
        if (next == NULL)
            next = strchr(current, '\0');
        // If there are no more tokens, current[0] will be 
        // equal to 0 and (end == current) too
        done = (current[0] == '\0');
        if ((next != current) && (done == 0))
        {
            // We nul terminate it (replace the delimiter with nul)
            // so now, current is the token.
            next[0] = '\0';
            // Display the token
            printf("--%s--\n", current);
            // Restore the character
            next[0] = ' ';
            // Advance to the next characeter (for the next strchr())
            current = next + 1;
        }
        else if (*next++ == ' ') // If the next character is a space, 
        {                        // it's a delimiter
            int spaces;
            int count;

            // Count the number of spaces to see 
            // if the space is a delimiter or a token
            spaces = 1;
            // Count the number of tokens
            count = 1;
            // While the current character is a space, we seek for a non-space
            while (isspace((unsigned char) *next) != 0)
            {
                next++;
                if (spaces % 2 == 0) // If it's an even space (it's a token)
                    count += 1;
                spaces++;
            }
            // If the spaces variable is not even 
            // there was no delimiter for the last
            // token consider this an input error
            if (spaces % 2 != 0)
                return -1;
            // Print the blanks as 0's
            for (int i = 0 ; i < count ; ++i)
                printf("--0--\n");
            // Advance to the next characeter (for the next strchr())
            current = next;
        }
    }
    return 0;
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • This is pretty close to what I need, but I have thought there will be a much easy way solve it. Very appreciate that, thanks! – KennyYang Dec 01 '15 at 16:44