我有这个代码。代码的目的是打印<img>
之前的所有内容以及</img>
之后的所有内容。不应打印<img>
和</img>
之间的所有内容。但是,我有两个问题。
<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 here\n");
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);
}
的test.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>
答案 0 :(得分:2)
您需要在第一次调用len = 0
之前设置getline()
。
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上遇到的问题是因为Windows没有实现getline()
功能。 (它不是C标准的一部分 - 它是POSIX功能。)
作为替代方案,您可以尝试使用fgets()
。示例如下。
N.B。请注意,在这种情况下,line
的内存 是动态分配的。
char line[128] = {'\0'};
while (fgets(line, sizeof(line), fp) != NULL) {
// etc..
}
// Do NOT call free(line) at end of scope in this case!
答案 1 :(得分:1)
您的代码中存在多个问题:
line
必须初始化为NULL
和len
至0
。在没有初始化的情况下,由于line
和len
具有自动存储(在堆栈上也称为 ),因此您的代码具有未定义的行为,在您的情况下导致提前终止。<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 %s\n", "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 here\n");
found_tag = true;
p = q + strlen("<img");
}
}
}
free(line);
fclose(fp);
return 0;
}