我一直在进行“ 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,如果是,为什么?因为我没有发现任何问题。
答案 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;
}
}
}