【问题标题】:Why !strcmp is used instead of strcmp?为什么使用 !strcmp 而不是 strcmp?
【发布时间】:2021-10-12 11:08:06
【问题描述】:

这里我写了一个代码来判断一个词是否可用。

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

char *names[] = {"Sushant", "Jhon", "Robin", "Mark", NULL};
int search(char *p[], char *names);
int main(void){
    if(search(names, "Sushant") != -1){
        printf("Sushant is in this list");
    } else{
        printf("Sushant is not in this list.");
    }
    return 0;
}

int search(char *p[], char *name){
    register int t;
    for(t = 0; p[t]; t++){
        if(!strcmp(p[t], name)){
            return t;
        } else{
            return -1;
        }
    }
}

代码运行良好。但问题是这样的。为什么它在工作?我使用strcmp 来比较数组和给定名称,但我也在strcmp 的开头使用! 来反转语句。问题是应该只有strcmp 而不是!strcmp 你能告诉我为什么在这里使用!strcmp 吗?

【问题讨论】:

  • strcmp 在传递的字符串匹配时返回零。
  • 您是否阅读过您不确定它们如何工作的函数的文档?

标签: c for-loop c-strings strcmp function-definition


【解决方案1】:

根据man strcmp,如果字符串相同,strcmp 返回 0。由于 0 在布尔上下文中表示 false,因此我们需要用 !strcmp 取反来检查两个字符串是否相等。


返回值
strcmp() 和 strncmp() 函数根据字符串 s1 大于、等于或小于字符串 s2 返回一个大于、等于或小于 0 的整数。

【讨论】:

    【解决方案2】:

    为什么使用 !strcmp 而不是 strcmp?

    这是一个糟糕的成语。我们可以争论贫穷是使用成语的人的错,还是设计strcmp的人的错,促使人们使用(可怜的)成语。

    当然,有些函数是“布尔型”:它们返回一个真/假值。其他的,比如getcharsqrt,绝对不是:非布尔函数可以返回整个范围的值。所以这里的关键问题是,strcmp 是布尔函数吗?一个重要的次要问题是,strcmp 的名称是否准确反映了其布尔或非布尔状态?

    strcmp 当然,不是二进制。它可以返回 3 个值:负数、零或正数,具体取决于第一个字符串按字典顺序是小于、等于还是大于第二个字符串。此外,正如我刚才所说,如果两个字符串相等strcmp 返回 0。

    现在,想要编写一个if() 语句来在两个字符串相等时执行某些操作是很常见的。字符串是 C 语言中的二等公民,因此您不会将它们与== 进行比较,您将不得不调用一个函数。所以你要写类似的东西

    if(f(string1, string1))
    

    所以,如果您 确实 有一个字符串比较函数可供您使用,该函数 确实 返回一个布尔值,那么您可以编写类似

    if(strings_are_equal(string1, string2))
    

    或者,也许,你可以或多或少地写出类似的东西

    if(!strings_are_different(string1, string2))
    

    但是您没有布尔值字符串比较函数,至少在标准 C 库中没有。你有strcmp,它不仅告诉你字符串是否相同,它还告诉你(如果它们不同)哪个更大。这应该是一种帮助,但它最终会激励你问的那个可怜的成语。

    由于strcmp如果字符串相等则返回0,并且由于0在C语言中是“假”,许多程序员发现你可以写

    if(!strcmp(string1, string2))
    

    它有效。您会注意到,这实际上与假设的代码相同

    if(!strings_are_different(string1, string2))
    

    我之前建议过。唯一的问题是名称strcmp 没有任何区别;如果有的话,它表明相似性。所以除非你注意,否则很容易误读

    if(!strcmp(string1, string2))
    

    说,“如果字符串 相同,则做某事”,而实际上,它真正的意思是“如果两个字符串 相同,则做某事”一样”。

    如果strcmp's 名称改为strdiff,情况可能会更好。然后你可以写

    if(!strdiff(string1, string2))
    

    它会很好读。 (不过还有其他问题:有些程序员可能会写if(strdiff(string1, string2) == TRUE),想知道为什么它不起作用。)

    我们在这里遇到的是一种编程风格:行

    if(!strcmp(string1, string2))
    

    可能可以正常工作,但读起来很混乱,而且以后有人不小心维护程序时可能会导致错误。

    当你看到这条线时

    if(!strcmp(string1, string2))
    

    帮助理解它的一种方法是将名称 strcmp 心理翻译为 strdiffstrings_are_different,然后您会得到对 if 语句的正确解释。

    我,在一个有很多字符串要比较的程序中,我写了

    #define Streq(s1, s2) (strcmp(s1, s2) == 0)
    

    之后我可以写

    if(Streq(string1, string2))
    

    这样我得到的东西既可以正常工作并且读起来也很好。

    【讨论】:

      【解决方案3】:

      为什么使用 !strcmp 而不是 strcmp?

      是因为代码的作者不是很准确。:)

      常用的成语是

      if( strcmp(p[t], name) == 0 ){
      

      虽然这些记录

      if( strcmp(p[t], name) == 0 ){
      

      if(!strcmp(p[t], name)){
      

      都是等价的,不过第一个更清楚,

      函数strcmp在两个字符串相同时返回0。

      来自 C 标准(7.23.4 比较函数)

      1 比较函数返回的非零值的符号 memcmp、strcmp 和 strncmp 由 第一对字符的值之间的差异(两者 解释为 unsigned char) 的对象不同 比较

      和(7.23.4.2 strcmp 函数)

      3 strcmp 函数返回一个大于、等于或 小于零,因此因为 s1 指向的字符串更大 小于、等于或小于 s2 指向的字符串。

      至于你的代码,那么它有一个错误。

      对于初学者来说,将数组names 声明为全局是没有意义的。它应该在 main 中声明

      const char * names[] = {"Sushant", "Jhon", "Robin", "Mark", NULL};
      

      由于函数search 不会改变传递的字符串,所以它应该被声明为

      int search( const char *p[], const char *name );
      

      函数搜索中的else语句应删除,返回语句

      return -1;
      

      必须放在for循环之后。例如

      int search( const char *p[], const char *name )
      {
          register int t;
      
          for(t = 0; p[t]; t++){
              if( strcmp( p[t], name ) == 0 ){
                  return t;
              }
          }
      
          return -1;
      }
      

      我会按照下面的演示程序中所示的方式定义函数

      #include <stdio.h>
      #include <string.h>
      
      size_t search( const char *p[], const char *name )
      {
          size_t i = 0;
          
          while ( p[i] && strcmp( p[i], name ) != 0 ) ++i;
          
          return p[i] ? i : -1;
      }
      
      int main(void) 
      {
          const char * names[] = {"Sushant", "Jhon", "Robin", "Mark", NULL};
      
          size_t i = search(names, "Sushant");
          
          if ( i != -1 ) puts( names[i] );
          
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2014-04-29
        • 1970-01-01
        • 1970-01-01
        • 2020-03-18
        • 2012-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        相关资源
        最近更新 更多