我是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;
}
是否有其他人能够在代码中找到我的错误?
答案 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;
}
忘记提及此代码不会与字符串文字一起播放,这些代码需要有自己的状态。