【问题标题】:C Trying to match the exact substring and nothing moreC 试图匹配确切的子字符串,仅此而已
【发布时间】:2018-04-13 12:57:18
【问题描述】:

我尝试了不同的功能,包括strtok()strcmp()strstr(),但我想我错过了一些东西。有没有办法匹配字符串中的确切子字符串?

例如:

如果我有名字:“Tan”

我有 2 个文件名:“SomethingTan5346”和“nothingTangyrs634”

那么我怎样才能确保我匹配第一个字符串而不是两者?因为第二个文件是给 Tangyrs 的。或者这种方法不可能?我是不是走错路了?

【问题讨论】:

  • “精确”子字符串是什么意思?两者都有子字符串。
  • 您要做的第一件事是严格定义“名称”的含义。您似乎将两个示例文件名分解为单独的字符串。要完全匹配这些字符串,一种方法是将文件名分成您定义为其单独子字符串的内容,然后在子字符串上查找 complete 匹配项,例如 strcmp().
  • 文件名的结构是什么? SOMETHINGTAN5346 是有效的文件名吗?应该在这里找到 TAN 吗?
  • 正如其他人所说,首先确定文件名的约定是什么。难道你不能p = strstr(str, "Tan") 并且如果找到它,请检查p[strlen("Tan")] 的下一个字符是否是数字? (当然,如果有名称为 "Tan5""gTan" 的用户,这将失败。)
  • 您似乎对自己的代码应该做什么有一个过于模糊的概念。在一个地方,您提到了一个“确切的子字符串”而没有定义它是什么。在其他地方,您提到了“为”“人”的“文件”,但没有定义这些词的含义。如果您认为这些事情是不言而喻的,请再想一想。 !@#$Tz:Gh012NV65$# 是“文件”吗?它“为”什么“人”?为什么?

标签: c


【解决方案1】:

如果看起来确实如此,您只想识别包含您的文本但后面紧跟一个数字的字符串,您最好的选择可能是让自己找到a good regular expression implementation,然后搜索Tan[0-9]

可以简单地使用 strstr() 查找字符串,然后使用 isnum() 检查后面的字符,但实际代码是:

  1. 不像您想象的那么容易,因为您可能需要进行多次搜索(例如,TangoTangoTan42 需要进行三项检查);和
  2. 如果搜索可能变得更复杂(例如 Tan 后跟 1-3 位数字或恰好两个 @ 字符和一个 X),则不建议这样做。

只要您愿意投入一点精力来学习它,正则表达式库将使这变得更容易。


如果你不想想花时间学习正则表达式,下面的完整测试程序应该是一个很好的起点,可以根据第一段中的要求评估字符串:

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

int hasSubstrWithDigit(char *lookFor, char *searchString) {
    // Cache length and set initial search position.

    size_t lookLen = strlen(lookFor);
    char *foundPos = searchString;

    // Keep looking for string until none left.

    while ((foundPos = strstr(foundPos, lookFor)) != NULL) {
        // If at end, no possibility of following digit.

        if (strlen(foundPos) == lookLen) return 0;

        // If followed by digit, return true.

        if (isdigit(foundPos[lookLen])) return 1;

        // Otherwise keep looking, from next character.

         foundPos++;
    }

    // Not found, return false.

    return 0;
}

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage testprog <lookFor> <searchIn>...\n");
        return 1;
    }
    for (int i = 2; i < argc; ++i) {
        printf("Result of looking for '%s' in '%s' is %d\n", argv[1], argv[i], hasSubstrWithDigit(argv[1], argv[i]));
    }
    return 0;
}

不过,如您所见,它不如正则表达式搜索优雅,而且如果您的要求发生变化,它可能会变得更加不那么优雅:-)

运行它:

./testprog Tan xyzzyTan xyzzyTan7 xyzzyTangy4 xyzzyTangyTan12

表明这是行动:

Result of looking for 'Tan' in 'xyzzyTan' is 0
Result of looking for 'Tan' in 'xyzzyTan7' is 1
Result of looking for 'Tan' in 'xyzzyTangy4' is 0
Result of looking for 'Tan' in 'xyzzyTangyTan12' is 1

【讨论】:

    【解决方案2】:

    解决方案取决于您对精确匹配的定义。 这可能对您有用:

    1. 遍历目标子串的所有匹配项。

    C find all occurrences of substring

    Finding all instances of a substring in a string

    find the count of substring in string

    https://cboard.cprogramming.com/c-programming/73365-how-use-strstr-find-all-occurrences-substring-string-not-only-first.html

    等等

    1. 有了匹配的范围,验证前面和后面的字符是否匹配/不匹配您的“完全匹配”标准。

    或者,

    1. 您可以利用 C++ 中的正则表达式(我知道标签是“C”),使用 #include &lt;regex&gt; 或 POSIX #include &lt;regex.h&gt;

    【讨论】:

    【解决方案3】:

    您可能希望使用strstr(3) 搜索字符串中的子字符串,使用strchr(3) 搜索字符串中的字符,或者甚至使用regular expressionsregcomp(3)。 p>

    您应该阅读有关 parsing 技术 的更多信息,尤其是有关 recursive descent parsers 的信息。在某些情况下,sscanf(3)%n 也很方便。您应该注意退货数量。

    您可以循环读取然后解析每一行,可能使用getline(3),请参阅this

    您需要首先记录您的输入file format(或您的文件名约定,如果SomethingTan5346 是一些file path),可能使用EBNF 表示法。

    (你可能想结合我上面建议的几种方法)

    顺便说一句,我建议(为了您的方便)将文件路径限制为一组受限制的字符。例如,可以在文件路径中使用*; 或空格或制表符(请参阅path_resolution(7)),但应该不赞成。

    【讨论】:

      猜你喜欢
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多