条件始终为真。我的代码中有错误,还是 IDE 中有错误?

标签 c

我一直在做《C 编程语言》(第二版)中的一些练习,我现在处于 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,如果是,为什么?因为我没发现有什么问题。

最佳答案

正如评论中所述,这作为 switch 语句更容易调试。我将其转换为开关,最终 if/else 条件的问题消失了。

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

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

我认为让人们知道这是一个预处理器会很有帮助,它只是简单地删除旧式 C 注释 /*..*/ 而不是 //... from code,然后输出剥离的代码。

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

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

有时,当更“简单”地编写代码而不是弄清楚为什么编译器认为某个条件始终为真更容易时,最好遵循最佳实践并进行简化。

#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;
        }
    }
}

关于条件始终为真。我的代码中有错误,还是 IDE 中有错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55777855/

相关文章:

c - 如何释放指向 int 的指针,使其成为指向函数结果的指针?

c - 回文程序无法运行

c - bool 方法的段错误 11

c - MPI IO读写 block 循环矩阵

c - 如何确定两个相似函数的效率更高

c - 为什么我的编码没有读取\n

c - gethostbyaddr : Success 上出现错误

c - 全局结构不起作用

c - 如何从用户 ID 中检索用户名

c - 为什么在 SortedMerge() 中用 **s 替换 *s 会导致程序崩溃?