Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中检查字符是否在注释范围内_C_Comments - Fatal编程技术网

如何在C中检查字符是否在注释范围内

如何在C中检查字符是否在注释范围内,c,comments,C,Comments,我必须编写一个程序,计算在文件中找到返回变量(&)地址的运算符的次数 我使用这个简单的循环来实现这一点(不介意!feof(p)引起一些问题): 然而,这并不能满足我的需要。例如,如果找到AND运算符(&&),我的循环会将变量“n”增加两次,但不能增加一次。另一件事是,如果在单行或多行注释的范围内找到&运算符,则不应将其计算在内 我的问题是如何确保给定的字符/字符串(在我的例子中是“&”运算符)是否在注释中?以及如何确保它确实是一个“&”运算符,而不是“&&”或字符串的一部分?正如在注释中提到的,

我必须编写一个程序,计算在文件中找到返回变量(&)地址的运算符的次数

我使用这个简单的循环来实现这一点(不介意!feof(p)引起一些问题):

然而,这并不能满足我的需要。例如,如果找到AND运算符(&&),我的循环会将变量“n”增加两次,但不能增加一次。另一件事是,如果在单行或多行注释的范围内找到&运算符,则不应将其计算在内


我的问题是如何确保给定的字符/字符串(在我的例子中是“&”运算符)是否在注释中?以及如何确保它确实是一个“&”运算符,而不是“&&”或字符串的一部分?

正如在注释中提到的,这不是一个可以用几行代码编写的简单任务。您需要的是一个解析器。该解析器需要处理许多不同的情况。以下是一个(可能并非详尽无遗)列表:

  • 单行注释:
    //这是一条注释
  • 多行注释:
    /*这是一条注释*/
  • 字符:
    charc='&'
  • 字符串文本:
    strcmp(str,“一个包含&的字符串”)
  • 按位运算符:
    inta=mask&b
您还需要决定如何处理不正确的输入。程序应该能够检测不正确的c代码,还是应该假设所有输入都是正确的?另一个需要考虑的问题是如何处理<代码>包含< <代码> >。是否也要计算包含文件中出现的次数?(我想不会,但这说明了一个问题)

如果您希望它在查找地址运算符时100%准确,那么它远远超出您的知识范围。(OP在下面的评论中写道:“这是一个只具备基础知识的第一学期学生要解决的问题。”

如果允许你走捷径,有更简单的方法

这里有一个完整的例子,可以省去一些麻烦。它处理注释和字符串,包括转义字符。但是,它不处理按位运算符

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