【问题标题】:Search string not matching the input text properly搜索字符串与输入文本不匹配
【发布时间】:2020-06-17 18:18:18
【问题描述】:

我有一个程序可以正确匹配输入字符串中的搜索字符串(以一个点开头),但不适用于两个或更多点。

主要功能:

int main()
{
    int position;
    char input[255], pattern[255];

    printf("Please enter a line of text of up to 255 characters:\n");
    fgets(input,sizeof(input),stdin);
    input[strcspn(input, "\n")] = 0;

    printf("Please enter the search text of up to 255 characters:\n");
    fgets(pattern,sizeof(pattern),stdin);
    pattern[strcspn(pattern, "\n")] = 0;
    cmp(input, pattern);
    return 0;
}

cmp函数:

char cmp(char input[],char pattern[])
{

    int i, pattern_position, input_position;


    for(int pattern_position = 0; pattern_position < strlen(pattern); pattern_position++) {

        if(pattern[pattern_position] == '.'){
            char letter_space_comma[54] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', ' ', 'a', 'b', 'c', 'd', 'e', 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
            for (int  letter_space_comma_position= 0; letter_space_comma_position < 54; letter_space_comma_position++){
                pattern[pattern_position] = letter_space_comma[letter_space_comma_position];
                char *pos = strstr(input, pattern);
                if (pos) {
                    printf("Matches at position %ld.", pos-input);
                    goto end;
                }
            }
        }
    }

    char *pos = strstr(input, pattern);
    if (pos) {
        printf("Matches at position %ld.", pos-input);
    } else {
        printf("No match.");
    }

    end:
        return 0;
}

输入 1(1 个点):

Please enter a line of text of up to 255 characters: The cat sat on the mat.
Please enter the search text of up to 255 characters: .at

输出 1(正确):

Matches at position 4.

输入 2(3 个点):

Please enter a line of text of up to 255 characters: The cat sat on the mat.
Please enter the search text of up to 255 characters: ...

我的输出 2:

No match.

预期输出 2:

Matches at position 0.

【问题讨论】:

  • 这似乎是学习如何使用调试器的好时机。使用调试器,您可以在监视变量及其值的同时逐句执行代码。这样可以很容易地查看出现问题的时间和地点。

标签: c pattern-matching


【解决方案1】:

按照 cmets 的建议,您应该使用调试器并检查 pattern 字符串在 cmp 函数中采用的不同值:

for (int  letter_space_comma_position= 0; letter_space_comma_position < 54; letter_space_comma_position++){
    pattern[pattern_position] = letter_space_comma[letter_space_comma_position];

    /* HERE */ 

    char *pos = strstr(input, pattern);

当你有一个“任何字符”时,你就可以很好地测试所有的可能性。

当你有两个时,例如..t,你测试a.tb.t...z.t,然后zatzbt...zzt


一种简单的方法是使用递归:

  1. 准备一个新模式来测试找到的第一个 '.' 字符
  2. 将此新模式发送到depeer call。

但假设您的 cmp 函数发生了一些变化:

  • 必须告诉(通过返回值)它是否找到匹配项
  • 找不到匹配的时候一定不能打印(因为会被调用很多次)
  • 它不能修改传递的pattern参数:它必须有自己的副本。

考虑到这些元素,一种实现可能是:

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

char * cmp(char input[],char pattern[])
{
    int i, pattern_position, input_position;

    for(int pattern_position = 0; pattern_position < strlen(pattern); pattern_position++) {

        if(pattern[pattern_position] == '.'){

            /* make a local copy of pattern */
            char * pat = strdup(pattern);
            char * ret;

            char letter_space_comma[54] = {'A', 'B', 'C', ... 's','t','u','v','w','x','y','z'};
            for (int  letter_space_comma_position= 0; letter_space_comma_position < 54; letter_space_comma_position++){
                pat[pattern_position] = letter_space_comma[letter_space_comma_position];


                ret = cmp(input, pat);
                if (ret)
                    /* if some match, do not test other possibilities:
                     * exist for loop, but not the function: you must free pat */
                    break;

            }
            /* free the local copy */
            free(pat);

            if (ret)
                /* match happened and mem freed: we can leave the function*/
                return ret;
        }
    }

    char *pos = strstr(input, pattern);
    if (pos) {
        printf("match at %ld\n", pos - input);
        return pos;
    }

    end:
        return 0;
}

我自愿没有对你的代码做太多改动,所以你仍然可以继续学习:

  • cmp 中删除printf 并显示main 中的最终结果(“匹配”/“不匹配”)
  • make letter_space_comma 常量和静态:它们不是设置这么多时间的理由。
  • 更改cmp 原型以防止修改inputpattern 字符串。
  • 简化(去掉无用的变量,备注cmp可以直接返回strstr的结果......)

【讨论】:

  • 我如何使它适用于不区分大小写的输入?因为这适用于区分大小写的输入,但不适用于不区分大小写的输入。
  • @wei1999 将所有输入转换为小写,例如tolower
猜你喜欢
  • 2015-01-18
  • 2017-07-04
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 2018-09-29
  • 2018-04-09
  • 1970-01-01
相关资源
最近更新 更多