条件永远是真实的。我的代码中的错误,还是我的IDE中的错误?

时间:2019-04-20 21:20:33

标签: c

我一直在进行“ The C Programming language”(第二版)中的一些练习,我现在是1-23,您需要在其中开发一个程序以删除注释。

这是我到目前为止所拥有的:

#include <stdio.h>

#define CODE 0
#define START_COMMENT 1
#define END_COMMENT 2
#define COMMENT 3
#define INQUOTE 4

/* this is a test */

/* this is a *** comment maybe / but still testing */

main() {
    char c;
    char state=CODE;
    while ((c = getchar()) != EOF) {

        if(state == CODE) {
            if (c == '/') {
                state = START_COMMENT; /* this works? */
            }
            else if (c == '"' || c == '\'') {
                state = INQUOTE;
                putchar(c);
            }
            else {
                putchar(c);
            }
        }
        else if(state == INQUOTE) {
            if (c == '"' || c == '\'') {
                state = CODE;
                putchar(c);
            }
            else {
                putchar(c);
            }
        }
        else if(state == START_COMMENT) {
            if (c == '*') {
                state = COMMENT;
            }
            else {
                putchar('/');
                putchar(c);
                state = CODE;
            }
        }
        else if(state == COMMENT) {
            if (c == '*') {
                state = END_COMMENT;
            }
        }
        else if(state == END_COMMENT) {
            if (c == '/') {
                state = CODE;
            }
            else
                state = COMMENT;
        }
    }
}

我在Mac上使用CLion,它抱怨第54行始终评估为“ true”。这是底部的那一行:

else if(state == END_COMMENT) {

尽管如此,该程序到目前为止仍然可以运行...

该行是否总是计算为true,如果是,为什么?因为我没有发现任何问题。

1 个答案:

答案 0 :(得分:1)

如注释中所述,这很容易作为switch语句进行调试。我将其转换为一个开关,最终if / else条件的问题消失了。

我也在Mac上使用CLion,看到了您看到的警告。

尽管有以上注释,您的代码仍正确处理c样式'/ * .... * /注释。

让人们知道这是一个预处理器,它只是从代码中剥离旧的c注释/*..*/而不是//...,然后取出剥离的代码,这很有帮助。

状态机作为switch语句更容易阅读,也更容易调试。

请注意,在一处,您正在检查两个字符之一,这允许在switch语句之一中使用插入样式。

有时候,当更容易“更简单”地编写代码而不是弄清楚为什么编译器认为条件始终为真时,最好遵循最佳实践并进行简化。希望可以满足您的目的。

如有任何疑问,请告诉我。

#include <stdio.h>

const char CODE = 0;
const char START_COMMENT = 1;
const char END_COMMENT = 2;
const char COMMENT = 3;
const char INQUOTE = 4;

// Preprocessor which discards comments
int main() {
    int c;
    char state = CODE;
    while (EOF != (c = getchar())) {

        switch (state) {
            case CODE:

                switch (c) {
                    case '/':  // If we are in a comment, we will strip this section of the code
                        // check if this is the start of a comment:
                        state = POTENTIAL_COMMENT;
                        break;
                    case '"':
                    case '\'':
                        state = INQUOTE;
                        putchar(c);
                        break;
                    default:
                        putchar(c);
                }
                break;
            case INQUOTE:
                if (c == '"' || c == '\'') {
                    state = CODE;
                }
                putchar(c);
                break;
            case POTENTIAL_COMMENT:
                switch (c) {
                    case '*':   // We saw the '/', so now we se the '*' and we are in a comment, just eat the char
                        state = COMMENT;
                        break;
                    case '/':
                        state = LINE_COMMENT;
                        break;
                    default:
                        putchar('/');  // we saw a '/' before, but it wasn't really the start of a comment, so put the '/' back and the current char
                        putchar(c);
                        state = CODE;
                }
            case COMMENT:
                if (c == '*') {
                    state = END_COMMENT;
                }
                break;
            case LINE_COMMENT:
                if (c == '\n')
                    state = CODE;
                break;
            case END_COMMENT:
                if (c == '/') {
                    state = CODE;
                } else
                    state = COMMENT;
        }
    }
}