我有这个代码。代码的目的是打印<img>
之前的所有内容以及</img>
之后的所有内容。不应打印<img>
和</img>
之间的所有内容。但是,我有 2 个问题。
- 代码正在Windows(gcc编译器(上编译,但是当我运行它时,它只是说"程序停止工作"?
- 代码正在打印所有内容。它甚至正在打印
<img>
,</img>
以及介于两者之间的一切。
我 #includes:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
法典:
void replacer_and_print(FILE *fp) {
char* line;
size_t len;
ssize_t read;
bool found_tag = false;
int line_storer;
char* before_tag;
char* after_tag;
while ((read = getline(&line, &len, fp)) != -1) {
if (
((before_tag = strstr(line, "<img>")) != NULL) &&
((after_tag = strstr(line, "</img>")) != NULL)
) {
line_storer = before_tag - line;
printf("%.*s", line_storer, line);
printf("The Image use to be heren");
line_storer = after_tag - line + strlen("</img>");
printf("%s", line + line_storer);
} else if ((before_tag = strstr(line, "<img>")) != NULL) {
line_storer = before_tag - line;
printf("%.*s", line_storer, line);
found_tag = true;
} else if((after_tag = strstr(line, "</img>")) != NULL) {
found_tag = false;
line_storer = after_tag - line + strlen("</img>");
printf("%s", line + line_storer);
} else if(!found_tag) {
printf("%s", line);
}
}
fclose(fp);
}
测试.html:
<b>This is a test page</b>
<div class=back1>Some more text here for more testing!!!!</div>
<img>www.website.com/image.png</img>
<i>More words</i>
<u><i><b>TESTING 123</u></i></b>
输出:
<b>This is a test page</b>
<div class=back1>Some more text here for more testing!!!!</div>
The Image use to be here
<i>More words</i>
<u><i><b>TESTING 123</u></i></b>
假设:
There will only be one <img>
There will only be one </img>. The </img> tag will always be after the <img>
您需要在首次调用getline()
之前设置len = 0
。
char *line = NULL;
size_t len = 0;
从getline
的手册页...
如果 *lineptr 设置为 NULL,并且 *n 在调用之前设置为 0,则 getline(( 将分配一个缓冲区来存储该行。 即使 getline(( 失败,用户程序也应该释放此缓冲区。
len
是堆栈分配的 - 因此除非您初始化它,否则它可以包含任何值。
此外,您应该在完成之前free()
line
。
free(line);
fclose(fp);
最后,您应该检查fopen()
的返回值。
if (!fp) {
perror("fopen");
// Handle error and return if appropriate
}
getline()
和窗口
我怀疑你在Windows上遇到的问题是因为Windows没有实现getline()
功能。(它不是 C 标准的一部分 - 它是一个 POSIX 函数。
作为替代方案,您可以尝试使用fgets()
.下面是示例。
注:注:请注意,在这种情况下,line
的内存不是动态分配的。
char line[128] = {' '};
while (fgets(line, sizeof(line), fp) != NULL) {
// etc..
}
// Do NOT call free(line) at end of scope in this case!
代码中存在多个问题:
line
必须初始化为NULL
并len
初始化为0
。如果不进行初始化,由于line
和len
具有自动存储(也称为在堆栈上(,因此您的代码具有未定义的行为,在您的情况下会导致提前终止。- HTML
<img>
通常具有诸如src=URL
你做了一些假设,这些假设不是必需的,实际上会使你的代码复杂化: * 每行仅删除第一张图片。 * 如果<img>
标记和</img>
位于不同的行上,则在无关的打开标记之前,可能会在同一行上出现一个关闭标记。您的第一次测试会被这种情况愚弄并产生不正确的输出。
下面是带有嵌套循环的更正版本:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
int main() {
FILE *fp;
char *line, *p, *q;
size_t len;
bool found_tag;
fp = fopen("test.html", "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %sn", "test.html");
return 1;
}
line = NULL;
len = 0;
found_tag = false;
while (getline(&line, &len, fp) != -1) {
for (p = line;;) {
if (found_tag) {
q = strstr(p, "</img>");
if (q == NULL) {
/* skip the rest of the line */
break;
}
found_tag = false;
p = q + strlen("</img>");
} else {
q = strstr(p, "<img");
if (q == NULL) {
fputs(p, stdout);
break;
}
printf("%.*s%s", (int)(q - p), p,
"The Image used to be heren");
found_tag = true;
p = q + strlen("<img");
}
}
}
free(line);
fclose(fp);
return 0;
}