【问题标题】:A function that compares strings of names within an array and not case sensitive比较数组中名称字符串且不区分大小写的函数
【发布时间】:2019-12-16 11:19:08
【问题描述】:

在我的家庭作业中,我需要做一个函数,取 10 个名字并比较它们,告诉我名字是否相同。

首先,我创建了一个将名称放入数组的函数,然后创建了一个检查它们是否相同的函数。

一开始,我做了一个函数来逐个检查字母是否相似:

int stringCmpi (char *s1,char *s2)
{
    int i=0,diff=0;
    for(i=0; s1[i]!='\0'; i++)
    {
        if( toupper(s1[i])!=toupper(s2[i]) )
            return 1;
    }
    return 0;
} 

然后我做了一个函数来检查字符串,一个名字一个名字:

int cheak ()
{
    int k;
    int j=SIZE;
    for(k=0;k<MAX;k++)
        for(j=MAX;j>=k;j--)
        {
            if(1==stringCmpi(names[k],names[j]))
            {
                return 0;
            }
            return 1;
        }
}

main我做:

if(cheak(names)==1)
{
    printf("\nyou repeat names\n");
}
if(cheak(names!=1))
{
    printf("\n great! the names are not repeat\n");
}

但我的代码中有一些地方是错误的,因为它可以编译但无法正常工作。所以,请帮助我 - 我将不胜感激。

【问题讨论】:

  • 编程课程的目标是学习编程......所以学习如何调试一个软件,一步一步执行你的,你可能会发现问题所在。
  • @עידן רפאל דיי 显示字符串定义数组。
  • if( toupper(s1[i])!=toupper(s2[i]) ) - 如果字符串的长度不同怎么办?当s2s1 短时?
  • 你应该正确缩进你的代码。您的第一个代码 sn-p 正确缩进,其他两个没有。
  • if(cheak(names!=1)) - 这看起来很可疑

标签: c arrays for-loop c-strings toupper


【解决方案1】:

正如 KamilCuk 在 cmets 中所说,您遇到的一个重要问题是当您比较的字符串长度不同时。在不使用标准库函数的情况下(我猜这是您的目标),您可以通过在比较函数的不同位置查找 nul 终止符来检查这一点。

这是一种方法:

int stringCmpi (char *s1,char *s2)
{
    int i; // =0,diff=0; /// You don't use "diff" and "i" is initialized in the for loop!
    for(i=0; s1[i]!='\0'; i++)
    {
        if( toupper(s1[i])!=toupper(s2[i]) ) // This check will catch situations where...
            return 1; // ... s2 is SHORTER than s1, as s2[i] will be '\0' and s1 won't be!
    }
    // But we need to catch if s2 is LONGER than s1: s1[i] will now be '\0'...
    // ... so we can just check that s2[i] is ALSO '\0' (i.e. it's same length):
    if (s2[i] != '\0') return 1; // Different length strings!
    return 0;
} 

请随时要求进一步澄清和/或解释。

编辑/PS:另外,正如 Ed Heal 所提到的,比较:if(cheak(names!=1)) 非常可疑 - 可能只是一个错字,你的意思是 if(cheak(names)!=1)。但是,在这里使用else 会容易得多!

【讨论】:

    【解决方案2】:

    让我们从函数stringCmpi开始。

    int stringCmpi (char *s1,char *s2)
    {
        int i=0,diff=0;
        for(i=0; s1[i]!='\0'; i++)
        {
            if( toupper(s1[i])!=toupper(s2[i]) )
                return 1;
        }
        return 0;
    } 
    

    让我们假设s1"A" 并且s2"AB"。在这种情况下,函数返回 0,因为循环将在比较两个字符串的第一个字符 'A' 后停止其迭代。

    所以这个函数是不正确的。

    现在让我们考虑函数cheak

    int cheak ()
    {
    int k;
    int j=SIZE;
    for(k=0;k<MAX;k++)
      for(j=MAX;j>=k;j--)
    {
       if(1==stringCmpi(names[k],names[j]))
    {
       return 0;
    }
       return 1;
    }
    }
    

    似乎标识符 MAX 表示数组中的字符串数。在这种情况下,值为 MAX 的索引指定了一个不存在的字符串,因为索引的有效范围是 [0, MAX)。所以该函数已经有未定义的行为。

    如果两个名称不相等,尽管数组可以包含相同的名称,但您会立即退出函数。所以函数可能会返回错误的结果。

    您需要的是以下内容。

    #include <stdio.h>
    #include <ctype.h>
    
    int stringCmpi( const char *s1, const char *s2 )
    {
        while ( *s1 != '\0' && 
                toupper( ( unsigned char )*s1 ) == toupper( ( unsigned char )*s2 ) )
        {
            ++s1; ++s2;
        }
    
        return *s1 != *s2;
    } 
    
    int check( size_t m, size_t n, char  names[const m][n] )
    {
        int unique = 1;
    
        for (size_t i = 0 ; unique && i < m; i++ )
        {
            for ( size_t j = i + 1; unique && j < m; j++ )
            {
                unique = stringCmpi( names[i], names[j] );
            }
        }
    
        return unique;
    }
    
    
    int main(void) 
    {
        {
            enum { M = 3, N = 10 };
            char names[M][N] = { "Bob", "Tome", "David" };
    
            if( check( M, N, names ) )
            {
                printf( "\ngreat! the names are not repeat\n" );
            }
            else
            {
                printf( "\nyou repeat names\n" );
            }           
        }
    
        {
            enum { M = 3, N = 10 };
            char names[M][N] = { "Bob", "Tome", "Bob" };
    
            if( check( M, N, names ) )
            {
                printf( "\ngreat! the names are not repeat\n" );
            }
            else
            {
                printf( "\nyou repeat names\n" );
            }           
        }
    
        return 0;
    }
    

    程序输出是

    great! the names are not repeat
    
    you repeat names
    

    或者如果你的编译器不支持可变长度数组,那么程序可能看起来像

    #include <stdio.h>
    #include <ctype.h>
    
    #define M   3
    #define N   10
    
    int stringCmpi( const char *s1, const char *s2 )
    {
        while ( *s1 != '\0' && 
                toupper( ( unsigned char )*s1 ) == toupper( ( unsigned char )*s2 ) )
        {
            ++s1; ++s2;
        }
    
        return *s1 != *s2;
    } 
    
    int check( char names[][N], size_t m )
    {
        int unique = 1;
    
        for (size_t i = 0 ; unique && i < m; i++ )
        {
            for ( size_t j = i + 1; unique && j < m; j++ )
            {
                unique = stringCmpi( names[i], names[j] );
            }
        }
    
        return unique;
    }
    
    int main(void) 
    {
        {
            char names[M][N] = { "Bob", "Tome", "David" };
    
            if( check( names, M ) )
            {
                printf( "\ngreat! the names are not repeat\n" );
            }
            else
            {
                printf( "\nyou repeat names\n" );
            }           
        }
        {
            char names[M][N] = { "Bob", "Tome", "Bob" };
    
            if( check( names, M ) )
            {
                printf( "\ngreat! the names are not repeat\n" );
            }
            else
            {
                printf( "\nyou repeat names\n" );
            }           
        }
    }    
    

    【讨论】:

    • 很好地发现了MAX 问题,弗拉德!我完全错过了一些东西。 +1
    • @עידןרפאלדיין 您可以通过以下方式声明函数/#define N 10 int check(names[][N], size_t m);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2021-05-09
    • 2015-07-23
    • 2012-11-30
    • 1970-01-01
    相关资源
    最近更新 更多