我怎样写一个合适的strcmp?

我怎样写一个合适的strcmp?,c,C,下面是我为strcmp编写的代码,我希望它不区分大写字母和小写字母,但是它仍然可以区分,如何解决这个问题 int strcmp(char str1[], char str2[]) { int i = 0; for (; str1[i] || str2[i];) { if (str1[i] > str2[i]) { int j = (str1[i] - str2[i]); if (j == 32)

下面是我为strcmp编写的代码,我希望它不区分大写字母和小写字母,但是它仍然可以区分,如何解决这个问题

int strcmp(char str1[], char str2[]) {
    int i = 0;
    for (; str1[i] || str2[i];) {
        if (str1[i] > str2[i]) {
            int j = (str1[i] - str2[i]);
            if (j == 32)
                i++;
            else {
                return +1;
            }
        } else
        if (str1[i] < str2[i]) {
            int q = (str1[i] - str2[i]);
            if (q == -32) {
                i++;
            } else {
                return -1;
            }
        } else
        if (str1[i] == str2[i]) {
            i++;
        }
    }
    return 0;
}
输出:

Aryan
Kim
Nap
Semi
kim
例如:

int strcasecmp(const char *a, const char *b)
{
    size_t i;
    for (i = 0; tolower((unsigned char)a[i]) == tolower((unsigned char)b[i]) && a[i]; ++i);
    return tolower((unsigned char)a[i]) - tolower((unsigned char)b[i]);
}
例如:

int strcasecmp(const char *a, const char *b)
{
    size_t i;
    for (i = 0; tolower((unsigned char)a[i]) == tolower((unsigned char)b[i]) && a[i]; ++i);
    return tolower((unsigned char)a[i]) - tolower((unsigned char)b[i]);
}

您的功能存在多个问题:

  • 不要将名称命名为strcmp()。您不应该用不同的语义重新定义标准函数
    strcmp()
    通常是高度优化的,当您将
    strcmp
    传递给排序函数时,您的版本甚至可能不是使用的版本

  • 该算法不正确:相隔32个位置的任意2个字符被视为相等,例如“0”==“p”

  • 比较是不可传递的:您有
    “A”<“\u”
    “A”
    但是
    “A”==“A”
    ,这对于排序来说是非常有问题的

  • 您不应该假定ASCII和硬编码大小写偏移量。使用
    中的
    toupper()
    ,并将
    char
    值转换为
    (无符号字符)
    ,以避免在负值上出现未定义的行为

  • i
    应该是
    size\u t

  • str1
    str2
    应为
    const
    合格

以下是一个改进的版本:

#include <ctype.h>

int strcmp_case(const char *str1, const char *str2) {
    for (size_t i = 0;; i++) {
        int c1 = toupper((unsigned char)str1[i]);
        int c2 = toupper((unsigned char)str2[i]);
        if (c1 != c2) {
            return (c1 > c2) - (c1 < c2);
        }
        if (c1 == '\0') {
            return 0;
        }
    }
}
#包括
int strcmp_案例(常量字符*str1,常量字符*str2){
对于(大小i=0;i++){
int c1=toupper((无符号字符)str1[i]);
int c2=toupper((无符号字符)str2[i]);
如果(c1!=c2){
返回(c1>c2)-(c1
您的功能存在多个问题:

  • 不要将名称命名为strcmp()。您不应该用不同的语义重新定义标准函数
    strcmp()
    通常是高度优化的,当您将
    strcmp
    传递给排序函数时,您的版本甚至可能不是使用的版本

  • 该算法不正确:相隔32个位置的任意2个字符被视为相等,例如“0”==“p”

  • 比较是不可传递的:您有
    “A”<“\u”
    “A”
    但是
    “A”==“A”
    ,这对于排序来说是非常有问题的

  • 您不应该假定ASCII和硬编码大小写偏移量。使用
    中的
    toupper()
    ,并将
    char
    值转换为
    (无符号字符)
    ,以避免在负值上出现未定义的行为

  • i
    应该是
    size\u t

  • str1
    str2
    应为
    const
    合格

以下是一个改进的版本:

#include <ctype.h>

int strcmp_case(const char *str1, const char *str2) {
    for (size_t i = 0;; i++) {
        int c1 = toupper((unsigned char)str1[i]);
        int c2 = toupper((unsigned char)str2[i]);
        if (c1 != c2) {
            return (c1 > c2) - (c1 < c2);
        }
        if (c1 == '\0') {
            return 0;
        }
    }
}
#包括
int strcmp_案例(常量字符*str1,常量字符*str2){
对于(大小i=0;i++){
int c1=toupper((无符号字符)str1[i]);
int c2=toupper((无符号字符)str2[i]);
如果(c1!=c2){
返回(c1>c2)-(c1
if((isalpha(str1[i])?tolower(str1[i]):str1[i])>等
如此多的分支…我建议你只使用
toupper
tolower
对每个字符进行比较,你能给出一些输入和输出的示例吗?我猜
if(j==32)有点太天真了。请考虑<代码> 1代码> vs.代码> p>代码>这些都是相等的!<代码> ToupPu/COD>当字符不是小写字母时是良性的。所以只比较<代码> ToupPr(STR[i])< /> > <代码> ToupPr(STR2[i])
。不要使用像
32
这样的幻数。在纯字符未签名的系统上,您的代码会失败得更糟。
如果((isalpha(str1[i])?tolower(str1[i]):str1[i])>etc
如此多的分支…我建议您在每个字符上使用
toupper
tolower
,并进行比较。您能给出一些输入和输出的示例吗?我猜
如果(j==32)有点太天真了。请考虑<代码> 1代码> vs.代码> p>代码>这些都是相等的!<代码> ToupPu/COD>当字符不是小写字母时是良性的。所以只比较<代码> ToupPr(STR[i])< /> > <代码> ToupPr(STR2[i])
。不要使用像
32
这样的神奇数字。同样,在纯字符未签名的系统上,您的代码会失败得更糟。非常好,可移植性强。详细信息(可能超出OP的考虑范围):关键问题是在无大小写比较中,区域设置缺少小写字母到大写字母的映射。例如,迂腐的代码可以使用往返
int c1=toupper(tolower((unsigned char)str1[i]);
或其近亲
tolower(toupper())
。这两个函数的功能顺序倾向于将
的排序转移到字母之间。@chux:有趣的文章。应该注意的是,在对德语文本进行排序时,
ß
应该扩展到
ss
,这可能超出了OP的目标。对法语文本进行排序尤其困难,因为重音必须删除,但仍然存在我将从右到左考虑区分只在重音上不同的单词。无大小写比较的整个概念是语言/区域敏感的。当然,OP在这里的初始编码尝试是介绍性的,你的好答案将其提升到下一个层次。我只是希望我们大家都转向UTF8,使用库函数和由于粗心比较的详细信息非常广泛,所以不要使用通用的无大小写比较。虽然这种解决方案绝对正确,但看到布尔值上的算术运算让我感到不安。这会损害可读性,IMHO。@chux当然有很多选择。例如,
return(c1>c2)?1:-1;
c1-c2
在语义上是不正确的,顺便说一句(不管溢出情况如何)非常好而且非常便于携带。详细信息(可能超出OP的考虑):角落问题在案例中比较少