无法理解 strcmp 函数的一小部分
Can't understand small part of strcmp function
我正在看一本 C 语言的书,看过这两个 strcmp
算法。
我已经了解了 for 循环的使用原理。
但这两个for循环对我来说是新的。我不明白这些部分
for (i = 0; s[i] == t[i]; i++)
它没有长度而是有这个 s[i] == t[i]
.
for ( ; *s == *t; s++, t++)
这家伙是什么意思;
.
我了解的其他部分,我也知道这些功能是什么returns。
/* 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] == '[=10=]')
return 0;
return s[i] - t[i];
}
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '[=10=]')
return 0;
return *s - *t;
}
在第一种情况下,for
语句之后的代码正在检查是否找到了字符串结束标记,如果找到,函数 returns 0.
第二个for
语句的情况下,for
语句的初始化部分没有填写,所以语句以for( ;
开头。这是完全合法的。
祝你好运。
For 循环有 3 个部分 - 初始化、条件和循环表达式。这些都是可选的。
所以这个循环-
for (i = 0; s[i] == t[i]; i++)
它一直运行到字符 s[i]
等于 t[i]
。所以这是条件。如果它是假循环中断。
条件不一定总是基于长度。
还有这个 -
for ( ; *s == *t; s++, t++)
正如我们在上面看到的那样,初始化 是可选的,这里不存在,这很好。此循环中的条件也相同 i.e 循环直到字符相等。
for (i = 0; s[i] == t[i]; i++) // It has no length
实际上这段代码有点危险,因为它假定传递的字符串以 NULL 结尾(但稍后阅读)。只有当字符串的左侧部分相等时,循环才会继续,因此在循环内部,当遇到 NULL 时,唯一可能返回的结果是 0(相等)(for(;;) 条件确保两个字符串在同一位置都有 NULL)。
关于长度,要计算它,您无论如何都应该扫描整个字符串……并且扫描两次(因为有两个字符串)。这个循环反而将所有结合在一起。此外,C 中的字符串必须 以 NULL 结尾。当然,没有其他方法可以进行这种比较!
for ( ; *s == *t; s++, t++) // what means this guys
这与前面的大致相同,但不是使用索引取消引用 s 和 t(并且不触及它们),而是将它们修改为指向字符,一个接一个。我相信这会更快,但取决于编译器。此外,递增 s 和 t 会使您丢失字符串的开头;但是在这个函数中是没有问题的。
关于for(;;)
的语法,有评论已经解释了为什么要这样写。 for() 的最后一部分,在分号和右括号之间,在每次迭代后执行。在这种情况下我们需要增加两个变量,所以有两个语句用逗号分隔。
它没有长度。 for
循环是 运行 直到条件为真,所以在这种情况下,这意味着它将 运行ning 直到 s[i]
不等于 t[i]
。
for ( ; *s == *t; s++, t++)
这里的;
表示省略了for
循环的第一个子句。作为
bot s
和 t
是在 for
循环之外定义的,因此无需在此处定义它们。
C标准允许:
for ( clause-1 ; expression-2 ; expression-3 ) statement
(...)
Both clause-1 and expression-3 can be omitted. An omitted expression-2 is
replaced by a nonzero constant.
某些编译器(例如 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++)
^
首先,一些基础知识。
for
循环的语法是
for ( <em>expr1<sub>opt</sub></em> ; <em>expr2<sub>opt</sub></em> ; <em>expr3<sub>opt</sub></em> ) <em>statement</em>
expr1
、expr2
和 expr3
中的每一个 是可选的。语句
for ( ; ; ) { // do something }
将循环 "forever",除非循环主体中某处有 break
或 return
语句。
expr1
,如果存在,则在循环执行之前被计算一次——它用于建立一些初始状态(例如将索引设置为 0,或分配一个指针值,或类似的东西)。
expr2
,如果存在,在循环体的每次迭代之前计算。它是继续循环执行的测试条件。如果表达式的计算结果为非零值,则执行循环体;否则,循环退出。如果缺少 expr2
,则假定计算结果为 1 (true
)。
expr3
,如果存在,在循环体的每次迭代后计算。它通常会更新 expr2
中正在测试的任何内容。
for (i = 0; s[i] == t[i]; i++)
It have no length instead have this s[i] == t[i]
只要s[i] == t[i]
这个循环就会执行;一旦 t[i]
不等于 s[i]
,循环就会退出。就其本身而言,这意味着如果您有相同的字符串,循环将 运行 超过字符串的末尾 - 如果 s
和 t
都包含 "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++)
做的事情与第一个循环完全相同,但它没有使用 []
运算符索引到 s
和 t
,它只是使用指针。因为没有什么要初始化的,所以第一个表达式只是空的。
我正在看一本 C 语言的书,看过这两个 strcmp
算法。
我已经了解了 for 循环的使用原理。
但这两个for循环对我来说是新的。我不明白这些部分
for (i = 0; s[i] == t[i]; i++)
它没有长度而是有这个s[i] == t[i]
.for ( ; *s == *t; s++, t++)
这家伙是什么意思;
.
我了解的其他部分,我也知道这些功能是什么returns。
/* 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] == '[=10=]')
return 0;
return s[i] - t[i];
}
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '[=10=]')
return 0;
return *s - *t;
}
在第一种情况下,for
语句之后的代码正在检查是否找到了字符串结束标记,如果找到,函数 returns 0.
第二个for
语句的情况下,for
语句的初始化部分没有填写,所以语句以for( ;
开头。这是完全合法的。
祝你好运。
For 循环有 3 个部分 - 初始化、条件和循环表达式。这些都是可选的。
所以这个循环-
for (i = 0; s[i] == t[i]; i++)
它一直运行到字符 s[i]
等于 t[i]
。所以这是条件。如果它是假循环中断。
条件不一定总是基于长度。
还有这个 -
for ( ; *s == *t; s++, t++)
正如我们在上面看到的那样,初始化 是可选的,这里不存在,这很好。此循环中的条件也相同 i.e 循环直到字符相等。
for (i = 0; s[i] == t[i]; i++) // It has no length
实际上这段代码有点危险,因为它假定传递的字符串以 NULL 结尾(但稍后阅读)。只有当字符串的左侧部分相等时,循环才会继续,因此在循环内部,当遇到 NULL 时,唯一可能返回的结果是 0(相等)(for(;;) 条件确保两个字符串在同一位置都有 NULL)。
关于长度,要计算它,您无论如何都应该扫描整个字符串……并且扫描两次(因为有两个字符串)。这个循环反而将所有结合在一起。此外,C 中的字符串必须 以 NULL 结尾。当然,没有其他方法可以进行这种比较!
for ( ; *s == *t; s++, t++) // what means this guys
这与前面的大致相同,但不是使用索引取消引用 s 和 t(并且不触及它们),而是将它们修改为指向字符,一个接一个。我相信这会更快,但取决于编译器。此外,递增 s 和 t 会使您丢失字符串的开头;但是在这个函数中是没有问题的。
关于for(;;)
的语法,有评论已经解释了为什么要这样写。 for() 的最后一部分,在分号和右括号之间,在每次迭代后执行。在这种情况下我们需要增加两个变量,所以有两个语句用逗号分隔。
它没有长度。
for
循环是 运行 直到条件为真,所以在这种情况下,这意味着它将 运行ning 直到s[i]
不等于t[i]
。for ( ; *s == *t; s++, t++)
;
表示省略了for
循环的第一个子句。作为
bot s
和 t
是在 for
循环之外定义的,因此无需在此处定义它们。
C标准允许:
for ( clause-1 ; expression-2 ; expression-3 ) statement
(...)
Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
某些编译器(例如 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++)
^
首先,一些基础知识。
for
循环的语法是
for ( <em>expr1<sub>opt</sub></em> ; <em>expr2<sub>opt</sub></em> ; <em>expr3<sub>opt</sub></em> ) <em>statement</em>
expr1
、expr2
和 expr3
中的每一个 是可选的。语句
for ( ; ; ) { // do something }
将循环 "forever",除非循环主体中某处有 break
或 return
语句。
expr1
,如果存在,则在循环执行之前被计算一次——它用于建立一些初始状态(例如将索引设置为 0,或分配一个指针值,或类似的东西)。
expr2
,如果存在,在循环体的每次迭代之前计算。它是继续循环执行的测试条件。如果表达式的计算结果为非零值,则执行循环体;否则,循环退出。如果缺少 expr2
,则假定计算结果为 1 (true
)。
expr3
,如果存在,在循环体的每次迭代后计算。它通常会更新 expr2
中正在测试的任何内容。
for (i = 0; s[i] == t[i]; i++)
It have no length instead have thiss[i] == t[i]
只要s[i] == t[i]
这个循环就会执行;一旦 t[i]
不等于 s[i]
,循环就会退出。就其本身而言,这意味着如果您有相同的字符串,循环将 运行 超过字符串的末尾 - 如果 s
和 t
都包含 "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++)
做的事情与第一个循环完全相同,但它没有使用 []
运算符索引到 s
和 t
,它只是使用指针。因为没有什么要初始化的,所以第一个表达式只是空的。