【问题标题】:Finding substrings in c(Question 8.16 from C how to program)在 c 中查找子字符串(C 中的问题 8.16 如何编程)
【发布时间】:2025-12-27 22:00:07
【问题描述】:

我正在尝试实现 C 如何编程中的问题 8.16。问题如下:

(搜索子字符串)编写一个程序,从键盘输入一行文本和一个搜索字符串。使用函数 strstr,在文本行中定位搜索字符串的第一个匹配项,并将该位置分配给 char * 类型的变量 searchPtr。如果找到搜索字符串,则打印以搜索字符串开头的文本行的剩余部分。然后,再次使用 strstr 在文本行中定位搜索字符串的下一个匹配项。如果找到第二次出现,则打印从第二次出现开始的文本行的其余部分。 [提示:对 strstr 的第二次调用应包含 searchPtr + 1 作为其第一个参数。]。

这是我的代码:

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

#define SIZE 128

int main(void){
    char s[SIZE], search_string[SIZE];
    char *searchPtr;
    fgets(s, SIZE, stdin);
    fgets(search_string, SIZE, stdin);
    
    searchPtr = strstr(s, search_string);
    //printf("%s", searchPtr);

    if(searchPtr){
        printf("%s%s\n", "The text line beginning with the first occurrence of: ", search_string);
        searchPtr = strstr(searchPtr+1, search_string);
        if(searchPtr){
            printf("%s%s\n","The text line beginning with the second occurrence of: ", search_string);  
        } else{
            printf("%s", "The string to be searched just appeared once.\n"); 
        }
    } else {
        printf("Search string is not found in the string.");
    }
}

这是我对字符串 s 的输入:

你好世界

这是我对 search_string 的输入:

世界

这是我的输出

从第一次出现的文本行开始:world 要搜索的字符串只出现过一次。

但输出应该是

以第一次出现的世界开头的文本行

以第一次出现的世界开头的文本行

【问题讨论】:

  • 这工作正常兄弟。谢谢。但您最好将您的 cmets 添加为答案,我会将其标记为有用。

标签: c string substring c-strings


【解决方案1】:

在完成fgets之后,我们必须去掉换行符(\n)。

否则,search_string 将在末尾有它并且搜索将失败[除非该字符串出现在要搜索的字符串的 end]。

对于一行/缓冲区中的 [最多] 两个匹配,代码是“硬连线”的。这可以概括为使用循环计算任意数量的匹配。

这要求将searchPtr 初始化为s 并传递给strstr


请注意,原始代码将 searchPtr 递增 1 以查找后续匹配项。

这比增加search_string 的长度

但是,如果(例如)要搜索的字符串为:

,则增加字符串长度会产生不同的结果:
aa

而且,要在其中搜索的字符串是(例如):

aaaaaa
  1. 按字符串长度递增将产生 3 个匹配项。
  2. 增加一个字符将产生 5 个匹配项。

这是重构后的代码。

我添加了代码以允许 多个 搜索字符串和行进行搜索。它们之间用空行分隔。

我已经注释了:

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

#define SIZE        1000

// dosearch -- perform a single search
// RETURNS: 1=more to do, 0=EOF
int
dosearch(void)
{
    char s[SIZE];
    char search_string[SIZE];
    char *searchPtr;
    int match;
    int moreflg;

    do {
        // get search string -- stop on EOF
        moreflg = (fgets(search_string, SIZE, stdin) != NULL);
        if (! moreflg)
            break;

        // strip newline and get string length
        size_t len = strcspn(search_string,"\n");
        search_string[len] = 0;

        // show the [small] string we wish to search for
        printf("\n");
        printf("String to search for is: %s\n",search_string);

        // skipping by one char is slow -- we could skip by the length
        // of the search string but this would work differently with:
        //   search string: aa
        //   buffer: aaaaaa
        // skipping by string length would produce 3 matches
        // skipping by one char would produce 5 matches
        // so, better to use 1
#if 1
        len = 1;
#endif

        while (1) {
            // get line to search -- stop on EOF
            moreflg = (fgets(s, SIZE, stdin) != NULL);
            if (! moreflg)
                break;

            // strip newline
            s[strcspn(s,"\n")] = 0;

            // blank line means start new search -- caller will loop for us
            if (s[0] == 0)
                break;

            printf("String to search within is: %s\n",s);

            match = 0;

            // point to start of line buffer
            searchPtr = s;

            while (1) {
                // search for next occurence of string
                searchPtr = strstr(searchPtr,search_string);
                if (searchPtr == NULL)
                    break;

                // increase the number of matches
                ++match;

                printf("Match #%d found at: %s\n",match,searchPtr);

                // skip over the match we just made
                searchPtr += len;
            }

            printf("A match occurred %d times\n",match);
        }
    } while (0);

    return moreflg;
}

int
main(void)
{

    while (1) {
        if (! dosearch())
            break;
    }
}

这里是一些示例输入数据:

world
hello world world
world is not enough
world

quick
the quick brown fox jumped over lazy dogs quickly

aa
aaaaaa

这是程序输出:


String to search for is: world
String to search within is: hello world world
Match #1 found at: world world
Match #2 found at: world
A match occurred 2 times
String to search within is: world is not enough
Match #1 found at: world is not enough
A match occurred 1 times
String to search within is: world
Match #1 found at: world
A match occurred 1 times

String to search for is: quick
String to search within is: the quick brown fox jumped over lazy dogs quickly
Match #1 found at: quick brown fox jumped over lazy dogs quickly
Match #2 found at: quickly
A match occurred 2 times

String to search for is: aa
String to search within is: aaaaaa
Match #1 found at: aaaaaa
Match #2 found at: aaaaa
Match #3 found at: aaaa
Match #4 found at: aaa
Match #5 found at: aa
A match occurred 5 times

【讨论】: