繁体   English   中英

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

[英]Counting the number of characters in comments line in C

我需要计算来自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;
}

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

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

我怀疑这是你的问题:

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

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

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

因此,如果*p计算为* ,则测试将失败。 改为

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

你的代码吓到了我。

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

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

我可以建议一个不同的解决方案吗?

一台状态机

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

#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来标记机器不同状态之间的转换,以及在某些状态下我们如何增加注释字符计数器,但在其他状态下则不是。 我认为跟踪这里发生的事情要容易得多。

正如已经陈述的那样,问题在于while (*p!='*' && *(p++)!='/')在这种情况下,语句的第二部分( *(p++)!='/' )仅在第一部分“触发”时才进行评估,因此如果找到星号则p递增。

它似乎有效

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM