如何检查字符是否在C中的注释范围内[关闭]

问题描述 投票:1回答:2

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

我使用这个简单的循环来做到这一点(不要介意提出一些问题的!feof(p)):

while (!feof(p)){   
c = fgetc(p);
if (c=='&') n++; }

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

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

c comments
2个回答
-1
投票

要覆盖C语言中的所有案例都会非常困难,你可能需要一个合适的解析器,但是如果你打算用它来进行例外工作 - 在问题中描述的情况下进行工作,你可以实现像这个:

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

当然,这不是一个完美的解决方案,但可以提供如何克服一些问题的想法。


0
投票

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

  • 一行评论:// This is a comment
  • 多行评论:/* This is a comment */
  • 人物:char c='&'
  • 字符串文字:strcmp(str, "A string with a & in it")
  • 按位运算符:int a = mask & b

您还需要决定如何处理不正确的输入。程序是否应该能够检测到错误的c代码,或者它应该假设所有输入都是正确的?另一件需要考虑的事情是如何处理#include。您是否也要计算包含文件中出现的次数? (我假设没有,但这证明了一个问题)

如果您希望它仅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);
}

它有点像这样:当它看到评论的开始时,它会读取并抛弃所有内容,直到评论结束或EOF。它对字符串也是如此。

在此输入:

// 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 */

它会报告预期结果2.如果打印1会更好,但正如我所提到的,它无法处理按位运算符,因此将其计为地址运算符。解决这个问题会让事情变得复杂得多。

是的,我正在使用goto,因为在这种情况下它非常方便。在C ++中,我使用异常,但这不是C中的选项。

© www.soinside.com 2019 - 2024. All rights reserved.