删除<img/>标记的内容

时间:2018-06-16 11:21:25

标签: c string getline

我有这个代码。代码的目的是打印<img>之前的所有内容以及</img>之后的所有内容。不应打印<img></img>之间的所有内容。但是,我有两个问题。

  1. 代码是在windows(gcc编译器)上编译但是当我运行它时,它只是说“程序停止工作”?
  2. 代码正在打印所有内容。它甚至打印<img></img>以及介于两者之间的一切。
  3. 我的#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>
    

2 个答案:

答案 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必须初始化为NULLlen0。在没有初始化的情况下,由于linelen具有自动存储(在堆栈上也称为 ),因此您的代码具有未定义的行为,在您的情况下导致提前终止。
  • 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 %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;
}