如何在C中检查字符是否在注释范围内
我必须编写一个程序,计算在文件中找到返回变量(&)地址的运算符的次数 我使用这个简单的循环来实现这一点(不介意!feof(p)引起一些问题): 然而,这并不能满足我的需要。例如,如果找到AND运算符(&&),我的循环会将变量“n”增加两次,但不能增加一次。另一件事是,如果在单行或多行注释的范围内找到&运算符,则不应将其计算在内如何在C中检查字符是否在注释范围内,c,comments,C,Comments,我必须编写一个程序,计算在文件中找到返回变量(&)地址的运算符的次数 我使用这个简单的循环来实现这一点(不介意!feof(p)引起一些问题): 然而,这并不能满足我的需要。例如,如果找到AND运算符(&&),我的循环会将变量“n”增加两次,但不能增加一次。另一件事是,如果在单行或多行注释的范围内找到&运算符,则不应将其计算在内 我的问题是如何确保给定的字符/字符串(在我的例子中是“&”运算符)是否在注释中?以及如何确保它确实是一个“&”运算符,而不是“&&”或字符串的一部分?正如在注释中提到的,
我的问题是如何确保给定的字符/字符串(在我的例子中是“&”运算符)是否在注释中?以及如何确保它确实是一个“&”运算符,而不是“&&”或字符串的一部分?正如在注释中提到的,这不是一个可以用几行代码编写的简单任务。您需要的是一个解析器。该解析器需要处理许多不同的情况。以下是一个(可能并非详尽无遗)列表:
- 单行注释:
//这是一条注释
- 多行注释:
/*这是一条注释*/
- 字符:
charc='&'
- 字符串文本:
strcmp(str,“一个包含&的字符串”)
- 按位运算符:
inta=mask&b
#include <stdio.h>
#include <stdlib.h>
#define INPUT "input.c"
int main()
{
FILE *f;
if ((f = fopen(INPUT, "r")) == NULL)
{
perror (INPUT);
return (EXIT_FAILURE);
}
char c, p=0;
int n=0;
while((c = fgetc(f)) != EOF)
{
if(c == '/' && p == '/') {
while((c = fgetc(f)) != EOF) {
// If we read // then we throw away the rest of the line
if( c == '\n' ) {
break;
}
}
if( c == EOF) {
goto end;
}
}
else if(c == '*' && p == '/') {
// If we read /* then we throw away everything until we have read */
while((c = getc(f)) != EOF) {
if( c == '*' ) {
if((c = getc(f)) != EOF)
if( c == '/')
break;
}
} if ( c == EOF) {
goto end;
}
}
else if(c == '"') {
// Read until end of string
while((c = getc(f)) != EOF) {
if(c == '\\') {
if((c = getc(f)) == EOF)
goto end;
}
else if(c == '"')
break;
}
}
else if(c == '\'') {
while((c = getc(f)) != EOF) {
if(c == '\\') {
if((c = getc(f)) == EOF)
goto end;
}
else if(c == '\'')
break;
} if ( c == EOF)
goto end;
}
else if(c == '&') {
printf("hej");
if(p == '&')
n--;
else
n++;
}
p=c;
}
end:
printf("\n\nExited at pos %ld\n", ftell(f));
printf("Number of address operators: %d\n", n);
}
它报告了预期的结果2。如果它打印1会更好,但正如我提到的,它不能处理按位运算符,因此将其作为地址运算符计算。解决这个问题会使事情变得更加复杂
是的,我使用的是
goto
,因为在这种情况下它非常方便。在C++中,我会使用异常,但是在C语言中,这不是一个选项,用以覆盖C语言中的所有情况都是很困难的,你可能需要一个合适的解析器,但是如果你只想用它来进行ExcSISE,在这个问题中描述的例子中,你可以实现这样的事情:
char previous = 0;
int single_line_comment = 0;
int multi_line_comment = 0;
int in_string = 0;
int in_char = 0;
while (!feof(p)){
c = fgetc(p);
if (c == '&' && !single_line_comment && !multi_line_comment && !in_string && !in_char)
{
if(previous == '&')
n--;
else
n++;
}
else if(c == '/' && prev == '/' && !multi_line_comment && !in_string && !in_char)
single_line_comment = 1;
else if(prev == '/' && c == '*' && !single_line_comment && !in_string && !in_char)
multi_line_comment = 1;
else if(c == '\n' && !multi_line_comment && !in_string && !in_char)
single_line_comment = 0;
else if(prev == '*' && c == '/' && !single_line_comment && !in_string && !in_char)
multi_line_comment = 0;
else if(c = '"' && !single_line_comment && !multi_line_comment && !in_char)
in_string = !in_string;
else if(c = '\'' && !single_line_comment && !multi_line_comment && !in_string)
in_char = !in_char;
previous = c;
}
当然,这不是一个完美的解决方案,但可以提供如何克服某些问题的想法。更一般地说,这里需要一个真正的解析器。(假设您正在解析C,您需要处理的另一种情况是二进制
&
运算符。或者字符串文本中的&
)可能存在@Dmitry的重复-但这不是最直接的问题。您可能可以使用状态机。否则,我认为奥利弗是对的,你需要一个真正的解析器。也许piggy会放弃像Clang这样的编译器。谢谢!我想我问得太多了,但不是有一个简单的方法吗?这是一个只有基本知识的第一学期学生才能解决的问题。@MiroslavBozhkov我对答案进行了一些更新,以回答您的评论。“检测注释中未包含的所有单个事件”是一项相当简单的任务,但如您所见,如果您只想计算地址运算符,则该任务并非100%准确。谢谢!为什么人们似乎不喜欢你的方法?可能是因为它不完整,或者是因为我使用了而(!feof(p))
这不好,但我只是编辑了你的代码,解决了这个问题是另一个问题。更多信息:@MiroslavBozhkov通过将答案标记为正确(勾选答案旁边的复选标记)来感谢某人。这将给您的代表一个+2提升。此代码将使行/“
触发字符串中的,//*
也将触发多行注释
// Test &
/* Also
&
test */
// "
int main()
{
/* " //
*/
// /*
char str[]="hej&\"";
char c='&';
char k='\'';
int a, b;
int * p;
p=&a;
int c=a&b;
int q=a&&b;
}
// Test &
/* Also
&
test */
char previous = 0;
int single_line_comment = 0;
int multi_line_comment = 0;
int in_string = 0;
int in_char = 0;
while (!feof(p)){
c = fgetc(p);
if (c == '&' && !single_line_comment && !multi_line_comment && !in_string && !in_char)
{
if(previous == '&')
n--;
else
n++;
}
else if(c == '/' && prev == '/' && !multi_line_comment && !in_string && !in_char)
single_line_comment = 1;
else if(prev == '/' && c == '*' && !single_line_comment && !in_string && !in_char)
multi_line_comment = 1;
else if(c == '\n' && !multi_line_comment && !in_string && !in_char)
single_line_comment = 0;
else if(prev == '*' && c == '/' && !single_line_comment && !in_string && !in_char)
multi_line_comment = 0;
else if(c = '"' && !single_line_comment && !multi_line_comment && !in_char)
in_string = !in_string;
else if(c = '\'' && !single_line_comment && !multi_line_comment && !in_string)
in_char = !in_char;
previous = c;
}