Skip to content

Another Solution to Exercise 1-23 #86

@ChenZhongPu

Description

@ChenZhongPu

The state machine based solution is easy-to-understood.

#include <stdio.h>

/**
 * An improved version of a comment-removal program, inspired by K&R Exercise 1-23.
 *
 * This version uses an explicit state machine, which is a more standard and
 * extensible pattern for this kind of parsing, while retaining the concise and
 * clever style of the original. It also adds support for // line comments.
 */

// State definitions
#define NORMAL 0
#define SAW_SLASH 1           // State: Just saw a '/', might be a comment.
#define IN_BLOCK_COMMENT 2
#define SAW_ASTERISK 3        // State: Inside a block comment, just saw a '*'.
#define IN_LINE_COMMENT 4
#define IN_STRING 5
#define SAW_ESCAPE_IN_STRING 6
#define IN_CHAR 7
#define SAW_ESCAPE_IN_CHAR 8

int main() {
    int c;
    int state = NORMAL;

    while ((c = getchar()) != EOF) {
        if (state == NORMAL) {
            if (c == '/') {
                state = SAW_SLASH;
            } else if (c == '"') {
                putchar(c);
                state = IN_STRING;
            } else if (c == '\'') {
                putchar(c);
                state = IN_CHAR;
            } else {
                putchar(c);
            }
        } else if (state == SAW_SLASH) {
            if (c == '*') {
                state = IN_BLOCK_COMMENT;
            } else if (c == '/') {
                state = IN_LINE_COMMENT;
            } else {
                putchar('/'); // It was just a division operator.
                putchar(c);
                state = NORMAL;
            }
        } else if (state == IN_BLOCK_COMMENT) {
            if (c == '*') {
                state = SAW_ASTERISK;
            }
        } else if (state == SAW_ASTERISK) {
            if (c == '/') {
                state = NORMAL;
            } else if (c != '*') {
                state = IN_BLOCK_COMMENT; // False alarm.
            }
            // if c is '*', stay in this state (e.g. /*******/)
        } else if (state == IN_LINE_COMMENT) {
            if (c == '\n') {
                putchar(c);
                state = NORMAL;
            }
        } else if (state == IN_STRING) {
            putchar(c);
            if (c == '\\') {
                state = SAW_ESCAPE_IN_STRING;
            } else if (c == '"') {
                state = NORMAL;
            }
        } else if (state == SAW_ESCAPE_IN_STRING) {
            putchar(c);
            state = IN_STRING;
        } else if (state == IN_CHAR) {
            putchar(c);
            if (c == '\\') {
                state = SAW_ESCAPE_IN_CHAR;
            } else if (c == '\'') {
                state = NORMAL;
            }
        } else if (state == SAW_ESCAPE_IN_CHAR) {
            putchar(c);
            state = IN_CHAR;
        }
    }
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions