[英]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.