【问题标题】:How to find a word within a string without case sensitivity?如何在不区分大小写的情况下在字符串中查找单词?
【发布时间】:2020-12-17 19:36:54
【问题描述】:

有没有办法以不区分大小写的方式在字符串中查找单词?

我想在 C 程序中查找“Word”或“WOrd”或“word”等。

我在发布此问题之前看到了一些解决方案,但它们不再起作用或强迫我触摸原始字符串以使其全部大写,这不是我想要的。有什么建议吗?

【问题讨论】:

  • GNU 有 strcasestr() ... linux.die.net/man/3/strcasestr ... strcasestr() 函数是一个非标准扩展。
  • 我不同意结束这个问题。它提出了一个明确的编程问题,并展示了在发布之前努力回答该问题的努力。
  • 这能回答你的问题吗? Case-insensitive string comparison in C++
  • @GHOSTHUNT 它不是 C++,我认为不是
  • @AndrewHenle 它并没有真正证明任何努力......这将包括真正尝试对其进行编码但失败了。问题基本上是“为我编写代码来完成这项任务”

标签: c string-matching


【解决方案1】:

有没有办法将字符串与单词进行比较且不区分大小写?

要比较不区分大小写的字符串,请使用tolower() 或toupper() 折叠值。

#include <ctype.h>

int compare(const char *s1, const char *s2) {
  const unsigned char *u1 = (const unsigned char *) s1; // Use unsigned char for use with `to....()`
  const unsigned char *u2 = (const unsigned char *) s2;

  while (*u1 && toupper(*u1) == toupper(*u2)) {
    u1++;
    u2++;
  }
  int ch1 = toupper(*u1);
  int ch2 = toupper(*u2);
  return (ch1 > ch2) - (ch1 < ch2);
}

要处理可能具有非一对一上/下映射的常见 ASCII 范围之外的字母,请转换两次:

while (*u1 && tolower(toupper(*u1)) == tolower(toupper(*u2))) {
  

使用tolower() 或toupper() 或以上任一顺序在寻找相等性时没有区别,但可以产生顺序差异。例如_ 是在A-Z 之前还是之后?

【讨论】:

  • @chqrlie 我确实把它留了下来,看看是否有人会注意到,然后发表评论或编辑。感谢您的反馈。答案修改
【解决方案2】:

如果您想以不区分大小写的方式在字符串中查找单词,GNU 系统上有一个库函数strcasestr()。这是一个简单的实现:

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

char *strcasestr(const char *haystack, const char *needle) {
    size_t i;
    for (;;) {
        for (i = 0;; i++) {
            if (needle[i] == '\0')
                return (char *)haystack;
            if (tolower((unsigned char)haystack[i]) != tolower((unsigned char)needle[i]))
                break;
        }
        if (*haystack++ == '\0')
            return NULL;
    }
}

【讨论】:

    【解决方案3】:

    您可以创建自己的函数来比较这些类型的字符串。我已经实现了,你可以自己修改。

    #include <stdio.h>
    #include <stdlib.h>
    
    // returns true if X and Y are same
    int compare(const char *X, const char *Y)
    {
        while (*X && *Y)
        {
            if (abs(*X-*Y)!=32 && *X != *Y) //here 32 is neglecting the case
                return 0;
    
            X++;
            Y++;
        }
    
        return (*Y == '\0');
    }
    
    // Function to implement mystrstr() function
    const char *mystrstr(const char *X, const char *Y)
    {
        while (*X != '\0')
        {
            if ((*X == *Y) && compare(X, Y))
                return X;
            X++;
        }
    
        return NULL;
    }
    
    // Implement mystrstr function in C
    int main()
    {
        char *X = "GHOST HUNT - Coding made easy";
        char *Y = "CodiNg";
    
        printf("%s\n", mystrstr(X, Y));
    
        return 0;
    }
    
    //OUTPUT
    Coding made easy
    

    【讨论】:

    • abs(*X-*Y)!=32 仅在字符是 A-Z 字母时才有意义。
    • @chux-ReinstateMonica 我刚刚给他举了个例子。对他来说,这只是一个开端,他必须自己找出异常。
    • @chux-ReinstateMonica 此外,第二个条件*X!=*Y 是针对字符是否不是 A-Z
    【解决方案4】:

    这是一种方法

    #include <stdio.h>
    #include <string.h>
    
    #define SIZE 100
    
    int matchWord( char *s );
    
    int main() {
    
        char s[SIZE];
        int i, len, match = 0;
    
        fgets(s, SIZE, stdin);
    
        len = strlen(s);
    
        for(i = 0; i < len - 3; i++) {
        
            if( matchWord(s+i) ) {
            
                match = 1;
                break;
            }
        }
    
        match ? printf("Match found in position %d\n", i) : puts("Not found");
    
        return 0;
    }
    
    int matchWord( char *s )
    {
        static char w[8] = "wordWORD";
        int response = 1;
    
        for(int i = 0; i < 4; i++) {
        
            if( s[i] != w[i] && s[i] != w[i+4] ) {
            
                response = 0;
                break;
            }
        }
    
        return response;
    }
    

    【讨论】:

      【解决方案5】:

      使用regular expressions 和regex() 服务可以使其更通用。下面是一个示例程序,其中有一个名为 find_pattern() 的函数,它接受两个参数:要在其中进行搜索的字符串和要查找的模式。

      #include <stdio.h>
      #include <sys/types.h>
      #include <regex.h>
      #include <libgen.h>
      
      
      const char *find_pattern(const char *string, const char *pattern)
      {
      int         rc;
      regex_t     reg;
      const char *found = (const char *)0;
      regmatch_t  match;
      
        rc = regcomp(&reg, pattern, REG_EXTENDED|REG_NEWLINE);
        if (rc != 0) {
          fprintf(stderr, "Invalid regex '%s', error %d\n", pattern, rc);
          return (const char *)0;
        }
      
        rc = regexec(&reg, string, 1, &match, 0);
        if (0 == rc) {
          found = string + match.rm_so; 
        }
      
        regfree(&reg);
      
        return found;
      
      } // find_pattern
      
      
      int main(int ac, char *av[])
      {
        const char *str;  
      
        if (ac != 3) {
          fprintf(stderr, "Usage: %s string regex\n", basename(av[0]));
          return 1;
        }
      
        str = find_pattern(av[1], av[2]);
      
        if (str) {
          printf("%s\n", str);
          return 0;
        }
      
        return 1;
      } // main
      

      一些尝试:

      $ gcc search.c -o search
      $ ./search "azerty wOrD qwErty" '[wW][Oo][rR][dD]'
      wOrD qwErty
      $ ./search "azerty word qwErty" '[wW][Oo][rR][dD]'
      word qwErty
      $ ./search "azerty word qwErty" '[wW][Oo][R][D]'
      $ echo $?
      1
      $ ./search "azerty woRD qwErty" '[wW][Oo][R][D]'
      woRD qwErty
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多