【问题标题】:Strings in C (strstr function)C 中的字符串(strstr 函数)
【发布时间】:2021-10-21 04:22:57
【问题描述】:

我正在尝试重现 strstr() 函数的行为,该函数试图在字符串中查找子字符串,为此我创建了以下函数并将其与原始函数进行比较。我在纸上进行了所有迭代以了解函数中发生了什么,但我不明白为什么命令return (&str[i]); 打印ab 而不仅仅是a。当函数进入if (to_find[j] == '\0')时,ij的值分别是22,所以它应该只打印&str[2],也就是a。为什么打印ab 而不仅仅是a

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

char    *ft_strstr(char *str, char *to_find)
{
    int i;
    int j;

    i = 0;
    if (*to_find == '\0')
        return (str);
    while (str[i] != '\0')
    {
        j = 0;
        while (str[i + j] == to_find[j])
        {
            //printf("%d", i);
            //printf("%d\n", j);
            j++;
            if (to_find[j] == '\0')
                return (&str[i]);
        }
        i++;
    }
    return (0);
}

int main()
{
    char i[] = "ab";
    char dest[] = "a ab";
    printf("%s", ft_strstr(dest, i));
    //printf("%s", strstr(dest, i));
}

【问题讨论】:

  • printf 打印直到为"%s" 建立一个'0 也许你只想用"%c" 打印一个字符
  • 该函数返回 char * 而不是 char。因此,printf 会将其视为以空字符结尾的字符串
  • 我建议你在一张纸上画一个矩形,然后把它分成四个子矩形。在每个子矩形中填写字符串dest 的字母。为第一个字母画一个箭头并标记该箭头str。现在在第三个字母上绘制第二个箭头并将其标记为&amp;str[2]。两个箭头中的每一个都代表ft_strstr 函数中的重要指针,它们中的每一个都是指向以空字符结尾的字符序列的指针,也就是字符串

标签: c c-strings function-definition strstr


【解决方案1】:

在这个while循环中

    while (str[i + j] == to_find[j])
    {
        //printf("%d", i);
        //printf("%d\n", j);
        j++;
        if (to_find[j] == '\0')
            return (&str[i]);
    }

变量i 没有被更改。它保持不变。正在更改的是变量j

另一方面,return 语句

return (&str[i]);

返回指向i 位置符号的指针,该符号指向与字符串to_find 相等的子字符串的开头。

{注意数组dest 声明为

char dest[]="a ab";

其实有以下内容

char dest[] = { 'a', ' ', 'a', 'b', '\0' };

函数返回一个指向其子字符串的指针

char dest[] = { 'a', ' ', 'a', 'b', '\0' };
                           ^
                           |
                        { 'a', 'b', '\0' }

这是指向字符串"ab" 的第一个字符的指针,它是存储在数组dest 中的字符串的子字符串。

例如,当您编写示例时,请记住这一点

printf( "%s\n", dest );

当这个调用相当于

int i = 0;
printf( "%s\n", &dest[i] );

【讨论】:

    【解决方案2】:

    return (&amp;str[i]);这是做什么的:

    • str[i] 这与 *(str+i) 相同。就是取str指向的地址,加上i,得到它的值。
    • &amp;x 表示获取x 的地址
    • (&amp;str[i]) 是上面2个的组合。这意味着取str指向的地址,将i添加到它并获取它的值,然后获取该值的地址。这意味着最后两个步骤相互抵消,你得到:取str指向的地址,添加i。与(str+i)相同。
    • return 语句仅表示返回此指针。

    现在,在您调用ft_strstr(dest, i) 之后,您将获得此指针。在您的情况下,此指针指向字符串 "a ab" 中的第二个 a。你把这个指针指向printf(),并用"%s"告诉printf()打印这个指针指向的字符串,直到有一个'\0'字节。 'b' 不是 '\0'-byte 所以它也会被打印出来。

    调用printf()时返回的指针指向这里:

              V
    +---+---+---+---+---+
    | a |   | a | b |\0 |
    +---+---+---+---+---+
    

    printf() 然后将检查它是否指向'\0'-byte,这是错误的,因此打印字节('a')并且指针递增。然后对字节('b')做同样的事情,然后它指向'\0',这意味着printf()停在这里。

    【讨论】:

      【解决方案3】:

      当您使用说明符%s 打印来自strstr 的返回值时,它将打印“the needle”(也就是要查找的字符串)和 all 的原始字符串之后 针。

      在您的情况下,针后没有任何内容,因此您的输出只是“ab”。如果您的原始字符串是“a abHelloWorld”,那么您的输出将是“abHelloWorld”。

      如果你只想要针的第一个字符:

      printf("%c", *ft_strstr(dest, i));
      

      你也可以试试这个以获得更好的理解:

      char str[] = "Hello World";
      printf("%s\n", str);
      printf("%s\n", &str[0]);
      printf("%s\n", &str[1]);
      printf("%s\n", &str[2]);
      printf("%s\n", &str[3]);
      ...
      

      这会给你输出

      Hello World
      Hello World
      ello World
      llo World
      lo World
      ...
      

      如您所见,从&amp;str[n] 打印将跳过前 N 个字符并打印原始字符串的其余部分。

      顺便说一句:

      char    *ft_strstr(char *str, char *to_find)
      

      应该是

      char    *ft_strstr(const char *str, const char *to_find)
      

      【讨论】:

        【解决方案4】:

        return (&amp;str[i]); 不打印任何内容。它只是返回一个值。值是str的第i个元素的地址。

        打印发生在printf("%s", ft_strstr(dest, i)); 中,这里发生的是您从格式字符串开始,%s 是一个说明符,基本上说“打印字符直到到达零终止符,并从指定的地址开始” .

        【讨论】:

          【解决方案5】:

          printf("%s", ...) 打印一个字符串,而不是单个字符。要打印字符,请使用 %c 格式说明符并提供数组的第一个元素作为参数:

          printf("%c", *ft_strstr(dest, i));
          

          另一种选择是使用putchar(...) 打印单个字符。

          有关printf 格式说明符的更多信息,请参阅here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-08-25
            • 2014-05-04
            • 1970-01-01
            • 1970-01-01
            • 2020-06-13
            • 2012-07-16
            • 2015-02-12
            • 2013-12-22
            相关资源
            最近更新 更多