无法理解strcmp函数的一小部分

时间:2017-04-25 17:17:21

标签: c strcmp

我正在阅读C中的一本书并看过这两个strcmp算法。

我已经了解了usel for循环的工作原理。

但是这两个for循环对我来说是新的。我不理解这些部分

  1. for (i = 0; s[i] == t[i]; i++) 它没有长度而是有s[i] == t[i]

  2. for ( ; *s == *t; s++, t++)这个家伙的意思是什么;

  3. 我理解的其他部分,我也知道这些功能会返回什么。

       /* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
    int strcmp(char *s, char *t)
    {
       int i;
       for (i = 0; s[i] == t[i]; i++)
           if (s[i] == '\0')
         return 0;
       return s[i] - t[i];
    }
    
    int strcmp(char *s, char *t)
    {
     for ( ; *s == *t; s++, t++)
      if (*s == '\0')
      return 0;
     return *s - *t;
    }
    

5 个答案:

答案 0 :(得分:2)

首先,一些基础知识。

for循环的语法是

for ( expr1opt ; expr2opt ; expr3opt ) statement

每个 expr1 expr2 expr3 都是可选的。声明

for ( ; ; ) { // do something }
除非在循环体中某处有breakreturn语句,

将永远循环播放#34;

expr1 ,如果存在,在循环执行之前只进行一次评估 - 它用于建立一些初始状态(例如将索引设置为0,或者指定一个指针值,或类似的东西)。

expr2 ,如果存在,则在循环体的每次迭代之前进行评估。它是继续循环执行的测试条件。如果表达式求值为非零值,则执行循环体;否则,循环退出。如果缺少 expr2 ,则假定评估为1(true)。

expr3 ,如果存在,则在循环体的每次迭代后进行评估。它通常会更新 expr2 中正在测试的内容。

  

for (i = 0; s[i] == t[i]; i++)没有长度而是s[i] == t[i]

此循环将执行s[i] == t[i];只要t[i]不等于s[i],循环就会退出。就其本身而言,这意味着如果您有相同的字符串,则循环将超过字符串的结尾 - 如果st都包含"foo",则循环将以

s[0] == t[0] == 'f'
s[1] == t[1] == 'o'
s[2] == t[2] == 'o'
s[3] == t[3] == 0
s[4] == t[4] // danger, past the end of the string

因此,在循环体内,代码还会检查a[i]是否为0 - 如果是这样,这意味着我们已经匹配了0终止符之前的所有内容,并且字符串是相同的

所以,基本上,它就是......

s[0] == t[0] == 'f', s[0] != 0, keep going
s[1] == t[1] == 'o', s[1] != 0, keep going
s[2] == t[2] == 'o', s[2] != 0, keep going
s[3] == t[3] == 0, s[3] == 0, at end of s, strings match
  

for(; * s == * t; s ++,t ++)

与第一个循环完全相同,但它不是使用[]运算符索引到st,而是使用指针。由于没有什么可以初始化,所以第一个表达式只是留空。

答案 1 :(得分:1)

在第一种情况下,for语句之后的代码检查是否找到了字符串结束标记,如果是,则该函数返回0.

在第二个for语句的情况下,for语句的初始化部分未填写,因此语句以for( ;开头。这是完全合法的。

祝你好运。

答案 2 :(得分:1)

For循环有3个部分 - 初始化,条件和循环表达。所有这些都是可选的 所以这个循环 -

for (i = 0; s[i] == t[i]; i++)

直到字符s[i]等于t[i]为止。所以这是条件。如果是假循环中断。

条件不一定总是基于长度。

这一个 -

for ( ; *s == *t; s++, t++)  

正如我们在上面看到的那样初始化是可选的,并且在这里不存在,这是完全正常的。该循环中的条件也是相同的循环,直到字符相等。

答案 3 :(得分:1)

  

for(i = 0; s [i] == t [i]; i ++)//没有长度

实际上这段代码有点危险,因为它假定传递的字符串以NULL结尾(但稍后会读)。循环仅在字符串的左半部分相等时继续,因此,在循环内,当遇到NULL时,唯一可能返回的结果是0(相等)(for(;;)条件确保两个字符串在同一位置都有NULL。)

关于长度,要计算它,你应该扫描整个字符串...并且两次(因为有两个字符串)。相反,这个循环结合在一起。此外,C 中的字符串必须以NULL结尾。当然,没有其他方法可以进行这种比较!

  

for(; * s == * t; s ++,t ++)//这意味着什么

这与前一个大致相同,但不是使用索引取消引用s和t(并且不触及它们),而是将它们修改为一个接一个地指向字符。我相信这更快,但取决于编译器。而且,增加s和t会使你失去字符串的开头;但是在这个功能中它不是问题。

关于for(;;)的语法,评论已经解释了为什么它是这样编写的。分号和结束括号之间的for()的最后一部分在每次迭代后执行。在这种情况下,我们需要增加两个变量,因此有两个语句用逗号分隔。

答案 4 :(得分:1)

  1. 它没有长度。 for循环运行直到条件为真,因此在这种情况下,这意味着它将一直运行,直到s[i]不等于t[i]

  2. for ( ; *s == *t; s++, t++)

  3. ;这里意味着省略了for循环的第一个子句。如 僵尸st是在for循环之外定义的,因此无需在此处定义它们。

    C标准允许:

      

    for(clause-1; expression-2; expression-3)statement

         

    (...)

         

    可以省略子句-1和表达式-3。省略的表达式-2是   用非零常数代替。

    当已定义的变量放在第一个子句中时,某些编译器(如clang)会发出警告。例如这段代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
      int i = 0;
      for (i; i < 10; i++)
        puts("Hi");
    
      return EXIT_SUCCESS;
    }
    
    clang编译的

    产生警告:

    main.c:7:8: warning: expression result unused [-Wunused-value]
      for (i; i < 10; i++)
           ^