【问题标题】:Applying strstr() multiple times on same string in C在 C 中对同一字符串多次应用 strstr()
【发布时间】:2015-05-02 14:59:59
【问题描述】:

我正在尝试编写一个代码,使用 strstr 提取和标记之间的所有单词/字符串。但似乎它只是停留在提取的第一个字符串上,即“快速”。提取第一个字符串后如何让代码继续运行?

#include <stdio.h>
#include <string.h>

int main()
{

    char feed[] = "The <item> quick </item> brown <item> fox </item> jumps <item> over </item> the <item> lazy dog </item>";


    const char needle[] = "<item>";
    const char popo[] = "</item>";
    char *ret;
    char *ter;
    int n;
    n = 0;

    while (feed[n] != '\0')
    {
        ret = strstr(feed, needle)+6;
        ter = strstr(ret, popo);
        size_t len = ter - ret;
        char *res = (char*)malloc(sizeof(char)*(len+1));
        strncpy(res, ret, len);
        res[len] = '\0';

        printf("%s",res);
        n++;
    }
    return 0;
}

【问题讨论】:

  • 返回键很重 - 空格键没那么重 - 缩进代码!
  • Do not cast malloc()。这 ret = strstr(feed, needle)+6; 是危险的,如果 strstr() reutrns NULL 你最终得到 (void *)0x06 而不是 (void *)0x00 并且取消引用是一个问题。另外,请使用memcpy() 而不是strncpy(),如memcpy(res, ret, len),并在此之前检查res != NULL
  • 如果我删除 +6,输出将包含字符串“”。
  • 你可以在查看ret != NULL后添加&lt;item&gt;的长度,查看我的答案。

标签: c arrays string strstr strstream


【解决方案1】:

您需要使ret 指针指向字符串中的当前位置,并在每次迭代时按长度递增,并将ret 传递给第一个strstr() 而不是feed,查看这个实现

#include <stdio.h>
#include <string.h>

int main()
{

    char       feed[]   = "The <item> quick </item> brown <item> fox </item> "
                          "jumps <item> over </item> the <item> lazy dog </item>";
    const char needle[] = "<item>";
    const char popo[]   = "</item>";
    char      *head;
    int n;
    n = 0;

    head = feed;
    while (feed[n] != '\0')
    {
        char  *tail;
        char  *copy;
        size_t length;

        head = strstr(head, needle);
        /*            ^ always start at the current position. */
        if (head == NULL)
         {
            fprintf(stderr, "Invalid input...???\n");
            return -1;
         }
        tail   = strstr(head, popo);
        length = tail - head - 6;
        head  += 6;
        if (length < 0)
         {
            fprintf(stderr, "Invalid input...???\n");
            return -1;
         }
        copy = malloc(length + 1);
        if (copy != NULL)
         {
            memcpy(copy, head, length);
            copy[length] = '\0';

            printf("*%s*\n", copy);
            /* If you are not going to keep it, free it */
            free(copy);
         }
        head += length; /* <-- this is the imprtant thing */
        n++;
    }
    return 0;
}

【讨论】:

  • 非常感谢您的帮助
  • 请问,程序是从哪个变量、哪个部分提取第一个单词并得到结果的?我想将每个字符串放在一个数组中,以便稍后在代码中使用
  • 您可以在/* If you are not going to keep it, free it */ 中做到这一点,方法是不释放指针并将其存储在某处。
  • 当我做 memcpy(meti[a].item, copy, length);复制后[长度] ='\0';它只复制程序的最后一个结果,或者换句话说,最后一个 标记中包含的最后一个字符串。为什么直接到最后?我需要将提取的每个字符串从第一个到最后一个复制到一个数组中,以便稍后打印它们。请帮忙
【解决方案2】:

在这一行:

ret = strstr(feed, needle)+6;

您总是从feed 字符串的开头开始搜索。您需要将不同的起点传递给 strstr,您已经在 ter 中拥有该起点。所以你应该能够做这样的事情:

ter = feed;
while (ter != NULL) 
{
     ret = strstr(ter, needle) + 6;
...

这样,您的搜索开始将继续沿着feed 字符串向下移动。

您的代码中还有一些其他问题:

  1. strstr() 如果找不到匹配项,则可以返回 NULL - 你需要检查它,否则你的程序会崩溃。
  2. 你需要free()你的内存malloc()
  3. 正如@iharob 指出的“Do not cast malloc()

【讨论】:

  • 非常感谢您的帮助
猜你喜欢
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多