制作自己的 strchr() 函数但不区分大小写

Make own strchr() function but case-insensitive

我的练习要求我可以使用不区分大小写的输入。我的做法是使用tolower和toupper函数。

如何将数组转换为小写字母?

void KULstrcichr(char *arr, char search)
{
    printf("Return value when uppercase character %c is passed to isupper(): %d\n", search, isupper(search));
    // The  strchr() function returns a pointer to the first occurrence of the character c in the string s.
    if (isupper(search))
    {
        printf("Groß\n");
        char lowercasesearch = tolower(search);
        printf("Das ist der Output: %s", arr);
        char *ptr = strchr(arr, lowercasesearch);
        printf("Das ist der Buchstabe: %s", ptr);
    }
    else
    {
        printf("Klein\n");
        char upercasesearch = toupper(search);
        printf("Das ist der Output: %s", arr);
        char *ptr = strchr(arr, upercasesearch);
        printf("Das ist der Buchstabe: %s", ptr);
    }
}

根据题名

Make own strchr() function but case-insensitive

你的代码没有任何意义。您应该编写自己的类似于 strchr 的函数,该函数在 C 标准中声明为

char * strchr(const char *s, int c);

该函数应按以下方式声明和定义

char * my_strchr( const char *s, int c )
{
    c = tolower( ( unsigned char )c );

    while ( *s && tolower( ( unsigned char ) *s ) != c ) ++s;

    return c == '[=11=]' || *s != '[=11=]' ? ( char * )s : NULL;
}

这是一个演示程序。

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

char *my_strchr( const char *s, int c )
{
    c = tolower( ( unsigned char )c );

    while (*s && tolower( ( unsigned char )*s ) != c) ++s;

    return c == '[=12=]' || *s != '[=12=]' ? ( char * )s : NULL;
}

int main( void )
{
    char s[] = "Hello";
    char *p = my_strchr( s, 'h' );

    if (p != NULL)
    {
        printf( "position = %td, substring = %s\n", p - s, s );
    }
}

程序输出为

position = 0, substring = Hello

因为看起来您使用的是简单的 8 位 ASCII 字符,请注意给定的大写字符只是 (lowercase & 0x20)。获取输入字符并 运行 通过 strchr() 两次:一次是小写版本,一次是大写版本。

char *myStrchr(const char *s, char c) {
    char *pLower;
    char *pUpper;
    char *p;

    c |= 0x20;
    pLower = strchr(s, c);
    c &= ~0x20;
    pUpper = strchr(s, c);
    if (pLower == NULL) {
        p = pUpper;
    } else if (pUpper == NULL) {
        p = pLower;
    } else {
        p = (pLower < pUpper) ? pLower : pUpper;
    }
    return p;
}

注意:我认为您不希望您的函数是 void 类型。

编辑:如果您的输入字符串可能包含字母以外的字符,您需要在执行搜索之前bound-check。

“如何将数组转换为小写字母?” - 你不会。相反,一个字符一个字符地检查,直到到达字符串的末尾。

  • 首先将您搜索的char转换为小写(或大写)。
    char lowsearch = tolower((unsigned char)search);
    
  • 然后循环 arr 直到 *arr == '[=14=]' 并检查途中的每个字符:
    for(;*arr != '[=11=]'; ++arr) {
        if(tolower((unsigned char)*arr) == lowsearch) return arr;
    }
    return NULL;
    

请注意,这需要您 return 一个 char* 就像 strchr,而不是 void

How can I convert the array to lowercase letters? void KULstrcichr(char *arr, char search)

  • 要实现“制作自己的 strchr() 函数但 case-insensitive”,请使用 char *strchr(const char *s, int c); 之类的接口以最大程度地兼容该标准函数。

  • search*arr转换为普通情况。例如tolower()tolower(int ch) 是为 unsigned char 范围内的 chEOF.

    定义的

示例:

char *TLG_strchr(const char *s, int c) {
  c = tolower((unsigned char)c);

  // str...() functions perform as if `s` was `unsigned char *`.
  const unsigned char *us = (const unsigned char *) s;

  while (tolower(*us) != c && *us) {
    us++;
  }

  return tolower(*us) == c ? (char *) us : NULL;
}

迂腐:(unsigned char)*s 对于罕见的非 2 的带有 签名 char 的恭维机器是不正确的。更好的是 *((unsigned char *)s),这实际上是这个答案所做的,以正确访问否定 char 并将 +0 与 -0 区分开来。这可能是下一个 C 版本的 non-issue,因为预计需要 2 的赞美。

这个小任务比看起来更棘手:

  • 您的代码并不总是有效,因为您只搜索大写或小写,具体取决于 search 的大小写,这并不涵盖所有情况(双关语意)。

  • 首先使用大写字母 strchr,如果未找到大写字母,则使用小写字母仍然不正确:您必须找到任何一种情况下的第一个匹配项。

  • 如果 search0,您还必须找到空终止符。简单的实现通常无法通过此测试。

  • tolowertoupper 没有为不同于 EOF 的负值定义,因此它们不应被传递 char 值在默认签署 char 的平台上为负值。将 char 参数转换为 (unsigned char) 是避免此问题的简单方法。

这是一个例子:

// using int c for compatibility with char *strchr(const char *s, int c)
char *KULstrcichr(const char *s, int c) {
    int uc = tolower((unsigned char)c);

    for (;; s++) {
        if (tolower(*(unsigned char *)s) == uc)
            return (char *)s;
        if (*s == '[=10=]')
            return NULL;
    }
}