关于如何在 C 中使用 strchr 的困惑

Confusion on how to use strchr in C

char *strchr( const char *s, int c );

我知道 strchr 定位字符 c 在字符串 s 中的第一次出现。如果找到 c,则 s 中指向 c 的指针被 returned。否则,NULL 指针被 returned。

那么为什么下面的代码将 num 输出到 strlen(string) 而不是其设计目的?

num=0;
   while((strchr(string,letter))!=NULL)
   {
      num++;
      string++;
   }

但是这段代码给出了正确的输出

num=0;
   while((string=strchr(string,letter))!=NULL)
   {
      num++;
      string++;
   }

我不明白为什么将 returned 的指针分配给另一个合格的指针甚至会有所不同。我只是在测试 return 值是否为 NULL 指针。

  1. string 是一个指针。

  2. 在第一个示例中,您只需将它向右移动一个位置,而不管在哪里(或如果!)找到 "letter"。

  3. 在第二个例子中,每次你找到一个"letter",你:

    a) 更新 "string" 指向字母,然后

    b) 再次更新 "string" 以指向刚刚过去的字母。

让我试着换一种说法,

strchr

returns a pointer to the located character, or a null pointer if the character does not occur in the string.

在您的代码段的第一部分,return 值未被捕获,string 的紧接下一个位置从它之前指向的位置作为参数传递。 简而言之,该片段正在计算字符总数,直到 letter

最后一次出现
const char* string = "hello"
char letter = 'l'
num=0;
while((strchr(string,letter))!=NULL)
{
    num++;
    string++;
}

像这样,

            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
              ^
              |
+-------+     |
+string +-----+
+-------+
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                  ^
                  |
+-------+         |
+string +---------+
+-------+

            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                      ^
                      |
+-------+             |
+string +-------------+
+-------+



            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                              ^
                              |
+-------+                     |
+string +---------------------+
+-------+

在第二个代码段中,strchr 的 return 值被捕获回 string 并且直接下一个地址在下一次迭代中作为参数传递,

const char* string = "hello"
char letter = 'l'
num=0;
while((string = strchr(string,letter))!=NULL)
{
    num++;
    string++;
}

像这样,

+-------+     
+string +-----+
+-------+     |
              |
/*input pointer to strchr*/
              |
              v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                      |
                      |
               /*return pointer from strchr*/
                      |
+-------+             |
+string +<------------+
+-------+     


+-------+                 
+string +-----------------+
+-------+                 |
                          |
            /*input pointer to strchr*/
                          |
                          v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                          |
                          |
              /*return pointer from strchr*/
+-------+                 |
+string +<----------------+
+-------+     

+-------+                     
+string +---------------------+
+-------+                     |
                              |
                /*input pointer to strchr*/
                              |
                              v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+

                   /*NULL return from strchr*/
+-------+                     |
+string +<--------------------+
+-------+

第一个代码片段:

So why does below code outputs num to strlen(string) rather than what its designed to do?

输出可能不会总是 strlen(string),而是取决于输入字符串 string 和传递给 strchr() 的字符 letter。例如如果输入是

string = "hello"
letter = 'l'

那么你将得到的输出是4,它不等于字符串的长度"hello"。如果输入是

string = "hello"
letter = 'o'

那么你将得到的输出是5,等于字符串的长度"hello"。如果输入是

string = "hello"
letter = 'x'

那么你将得到的输出是0
输出实际上取决于字符 letter 在输入字符串中最后出现的位置。

原因是只有一条语句在修改string指针的位置,那条语句是

      string++;

它是这样工作的-
如果 string 中存在字符,则 strchr() 将 return 一个非空值,直到输入 string 指针指向最后一次出现时或之前的字符字符串中的字符 letter。一旦 string 指针指向字符串中最后一次出现的 letter 字符之后的一个字符,strchr() 将 return NULL 并退出循环并 num 将等于 letter 字符在字符串中最后一次出现的位置。因此,您将获得从 0strlen(string) 范围内的输出,而不是总是 strlen(string)

string = "hello", letter = 'e', num = 0
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;

string = "ello", letter = 'e', num = 1
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;

string = "llo", letter = 'e', num = 2
strchr(string, letter) will return null as it does not find 'e' in input string and loop exits

Output will be 2

第二个代码片段:

But this code gives correct output

是的,原因是 strchr() returned 指针被分配给了 string 指针。同样拿上面的例子,假设输入是

string = "hello"
letter = 'l'

strchr(string, letter) 将 return 指向第一次出现的字符 l 的指针,并将其分配给指针 string。所以,现在字符串指针指向第一次出现的 l。也就是说,现在 string

string = "llo"

在循环体中你正在做

string++;

这将使字符串指针指向由 strchr() 编辑的 return 字符的下一个字符。现在 string

string = "lo"
letter = `l`

strchr(string, letter) 将 return 指向 string 当前指向的字符的指针,因为它与字符 letter 匹配。由于循环体中的string++,现在字符串将指向下一个字符

string = "o"
letter = `l`

strchr(string, letter) 将 return NULL 并且循环将退出。 num 递增的次数与在 string 中找到的字符 letter 递增的次数相同。因此第二个片段给出了正确的输出。