【问题标题】:Remove contents of <img></img> tag删除 <img></img> 标签的内容
【发布时间】:2018-11-25 23:59:42
【问题描述】:

我有这个代码。代码的目的是打印&lt;img&gt; 之前的所有内容以及&lt;/img&gt; 之后的所有内容。不应打印&lt;img&gt;&lt;/img&gt; 之间的所有内容。但是,我有 2 个问题。

  1. 代码正在 windows 上编译(gcc 编译器),但是当我运行它时,它只是说“程序停止工作”?
  2. 代码正在打印所有内容。它甚至打印&lt;img&gt;&lt;/img&gt; 以及介于两者之间的所有内容。

我的#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>

【问题讨论】:

  • 欢迎来到 StackOverflow!在大多数情况下,这是一篇不错的第一篇文章;但是,您应该在帖子中包含您不会帮助解决的任何错误。您声明代码无法在 Windows 上编译,能否包含编译器错误?
  • @c1moore 完全没有错误。它编译得很好。但是,当我运行它时,它就会停止工作,
  • 那你为什么在你的帖子中包含#1?
  • @c1moore 措辞错误,抱歉。编辑了帖子
  • 提示:当输出有问题时,用&lt;&gt; 等标记围绕字符串 输出,并用\n 结束每个输出。它更好地暴露了过多的空白、换行、回车问题。例如。 printf("%.*s", line_storer, line); --> printf("&lt;%.*s&gt;\n", line_storer, line);

标签: c string getline


【解决方案1】:

您需要在第一次调用getline() 之前设置len = 0

char *line = NULL;
size_t len = 0;

来自getline 的手册页...

如果在调用之前 *lineptr 设置为 NULL 并且 *n 设置为 0,那么 getline() 将分配一个缓冲区来存储该行。即使 getline() 失败,用户程序也应释放此缓冲区。

len 是堆栈分配的 - 所以除非你初始化它,否则它可以包含任何值。

另外,你应该在完成之前free()ing line

free(line);
fclose(fp);

最后,你应该检查fopen()的返回值。

if (!fp) {
    perror("fopen");
    // Handle error and return if appropriate
}

getline() 和 Windows

我怀疑您在 Windows 上遇到的问题是因为 Windows 没有实现 getline() 函数。 (它不是 C 标准的一部分 - 它是一个 POSIX 函数。)

您也可以尝试使用fgets()。下面的例子。

注意请注意,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!

【讨论】:

  • 添加了这两个东西,仍然没有打印任何东西,但现在它至少没有崩溃。由于某种原因,它不满足 while 循环条件。所以它不会进入while循环。
  • @SarahChan:在您的问题中,您声明“代码正在打印everything”。现在你说反了。你能澄清一下吗?
  • @SarahChan:我无法访问mingw 或Windows 机器。但是,您确定文件是否已正确打开?我问是因为您没有检查fopen() 的返回值。
  • @SarahChan:如果您还没有这样做,我认为现在是使用调试器的好时机(我认为mingw 提供了gdb)。在 while() 循环的开头放置一个断点,并且 - 一旦到达 - 检查 linelen*fp 的内容。然后使用next 逐步检查程序 - 定期检查上述变量。
  • @SarahChan:我怀疑你的系统上没有实现getline()。我已经更新了我的答案,建议改用fgets()
【解决方案2】:

您的代码存在多个问题:

  • line 必须初始化为 NULLlen 必须初始化为 0。如果没有初始化,由于 linelen 具有自动存储(又名在堆栈上),您的代码具有未定义的行为,在您的情况下会导致提前终止。
  • HTML &lt;img&gt; 通常具有src=URL 等属性

您做了一些不必要的假设,实际上会使您的代码复杂化: * 每行只删除第一张图片。 * 如果&lt;img&gt; 标记和&lt;/img&gt; 位于不同的行,则在不相关的打开标记之前可能有一个关闭标记出现在同一行。您的第一次测试会被这种情况所迷惑并产生错误的输出。

这是一个带有嵌套循环的更正版本:

#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;
}

【讨论】:

  • 我将在哪里将&lt;img&gt;everything inside&lt;/img&gt; 替换为The Image use to be here。就像在我的输出示例中一样。 html 的东西也只是一个例子(我知道它不是有效的 html)。
  • @SarahChan:我更新了答案以输出图像占位符"The Image used to be here\n"
猜你喜欢
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多