c - 我正在尝试在 C 中创建一个代码抛光程序
问题描述
我正在尝试创建函数delete_comments()
。给出了read_file()
和main
函数。
实现
char *delete_comments(char *input)
从存储在输入处的程序中删除 C 注释的功能。输入变量指向动态分配的内存。该函数返回指向抛光程序的指针。您可以为输出分配一个新的内存块,或者直接在输入缓冲区中修改内容。您需要处理两种类型的评论:
/*
由和分隔的传统块注释*/
。这些注释可能跨越多行。您应该只删除开始/*
和结束的字符*/
,例如,保持任何后续换行符不变。行注释从
//
换行符开始。在这种情况下,也必须删除换行符。调用的函数
delete_comments()
仅处理来自delete_comments()
. 它不为任何指针分配内存。实现delete_comments()
函数的一种方法是为目标字符串分配内存。但是,如果分配了新内存,则输入中的原始内存必须在使用后释放。
我无法理解为什么我目前的方法是错误的,或者我得到奇怪输出的具体问题是什么。我通过尝试创建一个新数组来解决问题,在该数组中使用新规则复制输入字符串。
#include "source.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Remove C comments from the program stored in memory block <input>.
* Returns pointer to code after removal of comments.
* Calling code is responsible of freeing only the memory block returned by
* the function.
*/
char *delete_comments(char *input)
{
input = malloc(strlen(input) * sizeof (char));
char *secondarray = malloc(strlen(input) * sizeof (char));
int x, y = 0;
for (x = 0, y = 0; input[x] != '\0'; x++) {
if ((input[x] == '/') && (input[x + 1] == '*')) {
int i = 0;
while ((input[x + i] != '*') && (input[x + i + 1] != '/')) {
y++;
i++;
}
}
else if ((input[x] == '/') && (input[x + 1] == '/')) {
int j = 0;
while (input[x + j] != '\n') {
y++;
j++;
}
}
else {
secondarray[x] = input[y];
y++;
}
}
return secondarray;
}
/* Read given file <filename> to dynamically allocated memory.
* Return pointer to the allocated memory with file content, or
* NULL on errors.
*/
char *read_file(const char *filename)
{
FILE *f = fopen(filename, "r");
if (!f)
return NULL;
char *buf = NULL;
unsigned int count = 0;
const unsigned int ReadBlock = 100;
unsigned int n;
do {
buf = realloc(buf, count + ReadBlock + 1);
n = fread(buf + count, 1, ReadBlock, f);
count += n;
} while (n == ReadBlock);
buf[count] = 0;
return buf;
}
int main(void)
{
char *code = read_file("testfile.c");
if (!code) {
printf("No code read");
return -1;
}
printf("-- Original:\n");
fputs(code, stdout);
code = delete_comments(code);
printf("-- Comments removed:\n");
fputs(code, stdout);
free(code);
}
解决方案
您的程序存在基本问题。
它无法对输入进行标记。注释开始序列可以出现在字符串文字中,在这种情况下,它们不表示注释:
"/* not a comment"
。你有一些基本的错误:
if ((input[x] == '/') && (input[x + 1] == '*')) { int i = 0; while ((input[x + i] != '*') && (input[x + i + 1] != '/')) { y++; i++; } }
在这里,当我们进入循环时, with
i = 0
仍然input + x
指向开头的/
。我们没有跳过开头*
,并且已经在寻找结尾*
。这意味着该序列/*/
将被识别为完整的评论,但事实并非如此。此循环还假定每个
/*
评论都已正确关闭。它不检查可以终止输入的空字符,因此如果注释未关闭,它将超出缓冲区的末尾。C 有续行。在 ISO C 翻译阶段 2 中,删除所有反冲换行序列,将一个或多个物理行转换为逻辑行。这意味着
//
注释可以跨越多个物理行:// this is an \ extended comment
顺便说一句,您可以看到 StackOverflow 的语法高亮自动语言检测器做得很好!
行延续独立于标记化,直到翻译阶段 3 才会发生。这意味着:
/\ /\ this is an extended \ comment
那个已经打败了 StackOverflow 的语法高亮。此外,任何记号都可能发生续行,可能发生多次:
"\ this is a string literal\ "
推荐阅读
- javascript - 如何在节点js中定义模型,如对象
- swift - 如何从 webkit swiftUI 中的文本字段中搜索自定义文本
- android - Android 无障碍服务:打开无障碍菜单
- reactjs - 服务器响应状态为 404(未找到)问题
- pandas - 将数据集重新整形为长格式
- angular - 最初为输入提供值时,电话屏蔽不起作用
- python - 使用kali linux在python中遇到问题
- android - 无法在 android 中使用 AsyncTask 从 url 获取内容?
- linux - 使用参数访问 JQ 变量
- sqlite - 烧瓶应用程序中的 SQL Alchemy Query 用于多对多关系