计算C中注释行中的字符数

时间:2012-11-14 15:17:17

标签: c counting

我需要计算来自C程序的注释中的字符,这是作为标准输入提供的。这是我的功能,但由于某种原因它不算数。你能帮帮我吗?

int characters(FILE *file)
{
     int i=0;
     char ch[500], *p;
     while (fgets(ch, sizeof(ch),file)!=NULL)
     {
        p=ch;
        while (*p)
        { 
           if (*p=='/')
           { 
              p++;
              if (*p=='*')
              {
                 p++;
                 while (*p!='*' && *(p++)!='/')
                 {
                    i++;
                    p++;
                 }
              }
           }
           else
              p++;

         }


   return i;
}

5 个答案:

答案 0 :(得分:5)

我认为问题出在最里面的循环中:

while (*p!='*' && *(p++)!='/')

应该是

while (*p!='*' && *(p+1)!='/')

但如果它看到这样的事情,这将会破裂:

/* comment * */

因为条件*p!='*'的第一部分在第一个星号处是假的,所以你可以这样做:

while (!(*p=='*' && *(p+1)=='/')) {
   p++;
   i++;
}

注意:如果该行被破坏,您将收到分段错误:

    /* comment * \n
    */

你仍然要处理这个问题,但是你应该在内循环中添加*p

while (*p && !(*p=='*' && *(p+1)=='/')) {
   p++;
   i++;
}

答案 1 :(得分:1)

我怀疑这是你的问题:

while (*p!='*' && *(p++)!='/')

请记住p++在增量之前评估p 的值;实际上,测试是

while (*p != '*' && *p != '/')

因此如果*p评估为*,则测试将失败。将其更改为

while (*p != '*' && *(++p) != '/')

答案 2 :(得分:1)

你的代码吓到了我。

有很多指针正在进行,嵌套循环。

在那里很容易弄错逻辑,如果你需要进行更改,代码很难扩展。

我可以提出不同的解决方案吗?

A state machine

我们将在文件中一次读取一个字符并跟踪机器所处的状态。然后我们将使用它来决定我们是否在评论中。

#include <cstdio>
#define S_CODE          1
#define S_ONESLASH      2
#define S_LINECOMMENT   3
#define S_BLOCKCOMMENT  4
#define S_BLOCKSTAR     5

int characters(FILE *file){
    int ccount=0;
    char ch;
    int state=S_CODE;
     while ((ch=fgetc(file))!=EOF){
        switch(state){
            case S_CODE:
                if (ch=='/')
                    state=S_ONESLASH;
                break;

            case S_ONESLASH:
                if (ch=='/')
                    state=S_LINECOMMENT;
                else if (ch=='*')
                    state=S_BLOCKCOMMENT;
                else
                    state=S_CODE;
                break;

            case S_LINECOMMENT:
                if (ch=='\n')
                    state=S_CODE;
                else
                    ccount++;
                break;

            case S_BLOCKCOMMENT:
                if (ch=='*')
                    state=S_BLOCKSTAR;
                ccount++;
                break;

            case S_BLOCKSTAR:
                if (ch=='/')
                    state=S_CODE;
                else if (ch=='*')
                    state=S_BLOCKSTAR;
                else
                    state=S_CODE;
                ccount++;
                break;
        }
    }
    return ccount;
}

int main(int argc, char **argv){
    FILE *fin=fopen(argv[1],"r");
    printf("%d\n",characters(fin));
}

注意我们如何使用字符/*以及\n来标记机器不同状态之间的转换以及在某些状态下我们如何增加注释字符计数器,但在其他状态中不。我认为跟踪这里发生的事情要容易得多。

答案 3 :(得分:0)

如前所述,问题在于while (*p!='*' && *(p++)!='/') 在这种情况下,语句的第二部分(*(p++)!='/')仅在第一部分&#34;触发&#34;时被评估,因此如果找到星号则增加p

答案 4 :(得分:0)

似乎有效

int characters(FILE *file)
{
    int i = 0;
    char ch[500], *p;
    fread(ch, sizeof(char), 500, file);
    p = ch;
    while (*p)
    {
        if (*p=='/' && *(p+1) == '*')
        { 
            while (*p && (*p != '*' && *(p+1) != '/')) 
                ++p;
            ++i;
        }
        ++p;
    }
    return i;
}