A tokenizer can track whether it is outside or inside a word.

tokenizer The state changes when the scan crosses between spaces and word characters.
count The count increases only when the machine enters a word.

Token State

useLong
token_state.c
Replay: real traced execution (multi-file project)
#include <stdio.h>

enum TokenState {
    TOKEN_OUTSIDE,
    TOKEN_INSIDE
};

int countWords(const char *text) {
    enum TokenState state = TOKEN_OUTSIDE;
    int count = 0;

    for (int i = 0; text[i] != '\0'; i++) {
        char ch = text[i];
        if (ch == ' ') {
            state = TOKEN_OUTSIDE;
        } else if (state == TOKEN_OUTSIDE) {
            count++;
            state = TOKEN_INSIDE;
        }
    }

    return count;
}

int main(void) {
    int useLong = 0;
    const char *text = useLong ? "red blue green" : "red blue";
    int words = countWords(text);

    printf("useLong=%d words=%d\n", useLong, words);
    return 0;
}
#include <stdio.h>

enum TokenState {
    TOKEN_OUTSIDE,
    TOKEN_INSIDE
};

int countWords(const char *text) {
    enum TokenState state = TOKEN_OUTSIDE;
    int count = 0;

    for (int i = 0; text[i] != '\0'; i++) {
        char ch = text[i];
        if (ch == ' ') {
            state = TOKEN_OUTSIDE;
        } else if (state == TOKEN_OUTSIDE) {
            count++;
            state = TOKEN_INSIDE;
        }
    }

    return count;
}

int main(void) {
    int useLong = 1;
    const char *text = useLong ? "red blue green" : "red blue";
    int words = countWords(text);

    printf("useLong=%d words=%d\n", useLong, words);
    return 0;
}
  1. useLong ← 0, text ← red blue

    25int main(void) {26    int useLong→ 0 = 0; //@useLong=127    const char *text→ red blue = useLong0 ? "red blue green" : "red blue";28    int words = countWords(textred blue);
  2. int countWords(const char *text)

    8int countWords(const char *textred blue) {9    enum TokenState state = TOKEN_OUTSIDE;
  3. ch ← r

    pass 1 of 8
    12for (int i0 = 0; text[i]r != '\0'; i++) {13    char ch→ r = text[i]r;14    if (ch == ' ') {
    All 8 passes — pass 1 is the card above
    passitext[i]TOKEN_OUTSIDETOKEN_INSIDEchcountstate
    10r01r0 10 1
    21ee
    32dd
    43 0 1 0
    54b01b1 20 1
    65ll
    76uu
    87ee
  4. count ← 1, state ← 1

    pass 1 of 2
    15    state = TOKEN_OUTSIDE;16} else if (state0 == TOKEN_OUTSIDE0) {17    count→ 1++;18    state→ 1 = TOKEN_INSIDE1;19}
  5. state ← 0

    13char ch = text[i];14if (ch  == ' ') {15    state→ 0 = TOKEN_OUTSIDE0;16} else if (state == TOKEN_OUTSIDE) {
  6. count ← 2, state ← 1

    pass 2 of 2
    15    state = TOKEN_OUTSIDE;16} else if (state0 == TOKEN_OUTSIDE0) {17    count→ 2++;18    state→ 1 = TOKEN_INSIDE1;19}
  7. return count;

    22    return count2;23}
  8. words ← 2

    27    const char *text = useLong ? "red blue green" : "red blue";28    int words→ 2 = countWords(textred blue);2930    printf("useLong=%d words=%d\n", useLong0, words2);31    return 0;32}
    outputuseLong=0 words=2
  1. useLong ← 1, text ← red blue green

    25int main(void) {26    int useLong→ 1 = 1;27    const char *text→ red blue green = useLong1 ? "red blue green" : "red blue";28    int words = countWords(textred blue green);
  2. int countWords(const char *text)

    8int countWords(const char *textred blue green) {9    enum TokenState state = TOKEN_OUTSIDE;
  3. ch ← r

    pass 1 of 14
    12for (int i0 = 0; text[i]r != '\0'; i++) {13    char ch→ r = text[i]r;14    if (ch == ' ') {
    14 passes — pass 1 is the card above
    passitext[i]TOKEN_OUTSIDEchstate
    10rr
    21ee
    32dd
    43 0 1 0
    54bb
    65ll
    76uu
    87ee
    98 0 1 0
    ⋯ 3 more passes ⋯
    1312ee
    1413nn
  4. count ← 1, state ← 1

    pass 1 of 3
    15    state = TOKEN_OUTSIDE;16} else if (state0 == TOKEN_OUTSIDE0) {17    count→ 1++;18    state→ 1 = TOKEN_INSIDE1;19}
    All 3 passes — pass 1 is the card above
    passchcountstate
    1 0 10 1
    2 1 20 1
    32 30 1
  5. state ← 0

    pass 1 of 2
    13char ch = text[i];14if (ch  == ' ') {15    state→ 0 = TOKEN_OUTSIDE0;16} else if (state == TOKEN_OUTSIDE) {
  6. state ← 0

    pass 2 of 2
    13char ch = text[i];14if (ch  == ' ') {15    state→ 0 = TOKEN_OUTSIDE0;16} else if (state == TOKEN_OUTSIDE) {
  7. return count;

    22    return count3;23}
  8. words ← 3

    27    const char *text = useLong ? "red blue green" : "red blue";28    int words→ 3 = countWords(textred blue green);2930    printf("useLong=%d words=%d\n", useLong1, words3);31    return 0;32}
    outputuseLong=1 words=3