C项目赢得';不要删除占据整行的注释

C项目赢得';不要删除占据整行的注释,c,C,因此,我正在阅读K&RCBook,我的代码中有一个我无法理解的bug 程序应该删除C程序中的所有注释。显然我只是在用标准输入法 #include <stdio.h> int getaline (char s[], int lim); #define MAXLINE 1000 //maximum number of characters to put into string[] #define OUTOFCOMMENT 0 #define INASINGLECOMMENT 1 #

因此,我正在阅读K&RCBook,我的代码中有一个我无法理解的bug

程序应该删除C程序中的所有注释。显然我只是在用标准输入法

#include <stdio.h>

int getaline (char s[], int lim);

#define MAXLINE 1000 //maximum number of characters to put into string[]

#define OUTOFCOMMENT 0
#define INASINGLECOMMENT 1
#define INMULTICOMMENT 2

int main(void)
{
    int i;
    int isInComment;
    char string[MAXLINE];

    getaline(string, MAXLINE);

    for (i = 0; string[i] != EOF; ++i) {
        //finds whether loop is in a comment or not
        if (string[i] == '/') {
            if (string[i+1] == '/')
                isInComment = INASINGLECOMMENT;
            if (string[i+1] == '*')
                isInComment = INMULTICOMMENT;
        }
        //fixes the problem of print messing up after the comment
        if (isInComment == INASINGLECOMMENT && string[i] == '\0')
            printf("\n");

        //if the line is done, restates all the variables
        if (string[i] == '\0') {
            getaline(string, MAXLINE);
            i = 0;
            if (isInComment != INMULTICOMMENT)
                isInComment = OUTOFCOMMENT;
        }

        //prints current character in loop
        if(isInComment == OUTOFCOMMENT && string[i] != EOF)
            printf("%c", string[i]);

        //checks to see of multiline comment is over
        if(string[i] == '*' && string[i+1] == '/' ) {
            ++i;
            isInComment = OUTOFCOMMENT;
        }

    }
    return 0;

}
在注释开始之前没有任何内容,它将打印该注释,即使它不应该打印

我以为我取得了很好的进步,但这个错误真的阻碍了我。我希望这不是我错过的超简单的事情

编辑:忘记getaline函数

//puts line into s[], returns length of that line
int getaline(char s[], int lim)
{
    int c, i;

    for (i = 0; i < lim-1 && (c = getchar()) != '\n'; ++i)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}
//将行放入s[],返回该行的长度
int getaline(字符s[],int lim)
{
int c,i;
对于(i=0;i
当您开始一个新行时,您将
i
初始化为0。但在下一次迭代中:

for (i = 0; string[i] != EOF; ++i)
i
将递增,因此您将以索引
1
开始新行。因此,当该行以
/
开头时会出现错误

您可以看到,如果您改为编写以下内容,它将解决问题:

    if (string[i] == '\0') {
        getaline(string, MAXLINE);
        i = 0;
        if (isInComment != INMULTICOMMENT)
            isInComment = OUTOFCOMMENT;
    }

尽管通常认为在循环内修改
循环索引的
是不好的风格。您可以以更具可读性的方式重新设计实现。

代码中存在许多问题:

  • isInComment
    未在函数
    main
    中初始化

  • 正如其他人指出的,
    string[i]!=EOF
    错误。您需要更精确地测试文件结尾,尤其是对于不以换行符结尾的文件。仅当
    char
    类型为有符号且
    EOF
    为有效的
    signed char
    值时,此测试才有效。然而,它会错误地停在一个零散的
    \377
    字符上,这在字符串或注释中是合法的
  • 当检测到行尾时,您读取另一行并将
    i
    重置为
    0
    ,但在再次测试单行注释之前,for循环将增加i。。。这就是臭虫
  • 您不处理特殊情况,例如
    /*/*/
    //*
  • 您不处理字符串。这不是注释:
    “/*”
    ,也不是注释:
    “//”
  • 在行尾(转义换行符)不处理
    \
    。这可以用来扩展单行注释、字符串等。还有一些更微妙的情况与
    \
    处理有关,如果您确实想要完整性,您也应该处理三角图
  • 您的实现对行大小有限制,这是不需要的

分配给你的问题有点棘手。与其读取和解析行,不如一次读取一个字符,并实现一个状态机来解析转义换行、字符串和这两种注释样式。如果使用此方法正确,代码就不会太难。

getaline函数中有什么?
string[i]!=EOF
似乎不正确。我想应该是
string[I]!='\0'
字符串[i]!=EOF-->
字符串[i]!=0;用于start.Dang。我需要修改我的代码。谢谢你指出了所有的缺点。一开始就这么糟糕是正常的吗?非常令人沮丧。别担心,你正在解决的问题实际上相当困难。这里有一个复制品:但他们也没有弄对。
for (i = 0; string[i] != EOF; ++i)
    if (string[i] == '\0') {
        getaline(string, MAXLINE);
        i = 0;
        if (isInComment != INMULTICOMMENT)
            isInComment = OUTOFCOMMENT;
    }