用于从输入中删除注释的C函数

时间:2017-06-26 14:52:42

标签: c function comments

我是C新手并试图在C中编写自己的函数来清除给定输入代码中的注释。但是我的逻辑存在一些错误,因为结果甚至不是很理想。

我的代码如下:

char *removeComments(char *in)
{
    int i;
    int multipleLineFlag = 0;
    int singleLineFlag = 0;
    int n = strlen(input);
    char* output = malloc(n * sizeof(char));

    for (i=0; i<n; i++)
    {
        if (in[i] == '/' && in[i+1] == '*')
        {
            i++;
            multipleLineFlag = 1;
        }
        else if (multipleLineFlag == 1 && in[i] == '*' && in[i+1] == '/')
        {
            i++;
            multipleLineFlag = 0;
        }
        else if (in[i] == '/' && in[i+1] == '/')
        {
            i++;
            singleLineFlag = 1;
        }
        else if (singleLineFlag == 1 && in[i] == '\n')
        {
            singleLineFlag = 0;
        }
        else if (multipleLineFlag == 0 && singleLineFlag == 0)
        {
            out[i] = in[i];
        }
        i++;
    }    
    free(in);
    return out;
}

是否有其他人能够在代码中找到我的错误?

4 个答案:

答案 0 :(得分:1)

您的代码存在一个明显的问题:

out[i] = in[i];

您需要使用2个不同的变量来跟踪您在输入和输出字符串中的位置,因为它们会有所不同。例如,如果输入字符串包含&#34; foo / * test * / bar&#34;,则输出应包含&#34; foo bar&#34;,但您当前实际获得的是&# 34; foo [10个未定义的字符] bar&#34;。如果你很幸运,那些未定义的字符将是NUL。

另一个问题是你没有在输出结尾添加NUL。如果你没有分配足够的空间而输入中没有任何注释,那么你很难做到这一点 - 以及最后添加了NUL,你还需要分配比你更多的char。目前。

答案 1 :(得分:1)

除了Chris和Antti发现的问题之外,你应该知道你不能只解析注释语法来从C源代码中删除注释,你还必须解析字符串语法以避免在字符串文字中发生错误匹配。

还有这种特殊情况:

if ("yn".Contains(myChar)) {
    ...
}

这一个:

// this is a single line comment\
broken on 2 lines

状态机似乎是解决此问题的正确方法,但状态机可能非常难以抛光。

另外一点需要记住:块注释应该替换为单个空格字符,否则您可能会使旧样式标记粘贴不正确:

/\ *\ This is a block comment *\ / 应扩展为int/**/res;,而不是int res;

答案 2 :(得分:0)

您为输入和输出共享相同的索引 - 这意味着out[0]out[strlen("/* Hello World program */" - 1]未初始化,并且可能malloc只提供归零内存 - 因此out中的第一个字符将是终止字符串的NUL字符。

实际上你根本就不应该使用索引,只需使用指针。

char *result = malloc(n);
char *out = result;

...
    * out++ = in[i];
... 
// finally terminate the output
*out = '\0';
return result;

同样,我更喜欢只使用指针编写代码的in部分。

答案 3 :(得分:0)

通常我会使用状态机来完成这样的任务。

以下是我所讨论的一个未经测试的例子:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
  CODE,
  SLASH,
  SINGLELINE,
  MULTILINE,
  MULTILINE_ASTER
} state_t;

char* remove_comments(char const*in) {
  size_t len = strlen(in);
  char *out = malloc(len + 1);
  memset(out, 0, len+1);
  char c;
  state_t state = CODE;
  size_t opos = 0;
  while ((c = *in++)) {
    switch (state) {
    case CODE:
      if (c == '/') {
        state = SLASH;
      } else {
        out[opos++] = c;
      }
      break;
    case SLASH:
      switch (c) {
      case '/':
        state = SINGLELINE;
        break;
      case '*':
        state = MULTILINE;
        break;
      default:
        // this is a syntax error
        break;
      }
      break;
    case SINGLELINE:
      if (c == '\n') {
        state = CODE;
      }
      break;
    case MULTILINE:
      if (c == '*') {
        state = MULTILINE_ASTER;
      }
      break;
    case MULTILINE_ASTER:
      switch (c) {
      case '/':
        state = CODE;
        break;
      case '*':
        break;
      default:
        state = MULTILINE;
      }
    }
  }
  return out;
}

int main() {
  printf("%s", remove_comments("/********************************\n\
        * main function\n\
        * argc - number of arguments passed\n\
        * argv - pointer tgo arguments array\n\
        ********************************************/\n\
        int main(int argc, char **argv) {\n\
          // return number of arguments as return code\n\
          return argc;\n\
        }\n"));
  return 0;
}

忘记提及此代码不会与字符串文字一起播放,这些代码需要有自己的状态。