【问题标题】:C - Own str_join function does not workC - 自己的 str_join 函数不起作用
【发布时间】:2017-08-30 10:29:24
【问题描述】:

我想用 C 语言创建一个简单的 str_join 函数(以了解更多关于指针和数组的知识),它实际上将两个字符串连接在一起。

#include <stdio.h>
#include <stdlib.h>

int str_size(char *str);
void str_join(char *str1, char *str2);

int main(int argc, char **argv)
{
    char *part1 = "Hello ";
    char *part2 = "World!";
    str_join(part1, part2);
    printf("%s\n", part1);
    return 0;
}

int str_size(char *str)
{
    char c;
    for(int i = 0;; i++)
    {
        c = str[i];
        if(c == '\0')
            return i + 1;
    }
}

void str_join(char *str1, char *str2)
{
    int str_size_1 = str_size(str1) - 1; //Last char is '\0', don't need them 2 times
    int str_size_2 = str_size(str2);
    char str3[str_size_1 + str_size_2];
    int i;

    for(i = 0; i < str_size_1; i++)
        str3[i] = str1[i];

    for(i = 0; i < str_size_2; i++)
        str3[i + str_size_1] = str2[i];

    str1 = (char *)str3;
}

看起来很简单(也许太简单了)。 我将输出除外:

Hello World

但它看起来像:

Hello 

我使用以下命令编译了程序:

gcc main.c -o main

然后运行它:

./main

我没有看到我的失败,有人可以指出我的错误吗? 谢谢你帮助我!

【问题讨论】:

    标签: c pointers parameter-passing function-call


    【解决方案1】:

    在 C 中,函数参数是按值传递的。从函数内部对任何参数所做的任何更改都不会反映给调用者(实际参数)。

    因此,就您而言,str1 = (char *)str3; 并没有按照您的想法行事。

    也就是说,等等,停下来!! str3 是 VLA,生命周期是块范围。您不可能返回第一个元素的地址并期望它在访问内存位置的范围之外有效。您需要以超出其范围的方式分配内存。,您必须要么

    • 使用带有static 存储的阵列(不能与VLA 结合使用)
    • 使用内存分配器函数

    【讨论】:

    • 我不是把str1的地址改成str3的地址吗?
    • @l1677783 str1 是函数中的局部变量(函数参数的行为与局部变量非常相似)。 str1 = (char *)str3 将该局部变量更改为指向 str3。您没有更改 main() 中的 part1 变量。 main() 将 part1 指针的副本传递给您的 str_join() 函数。 (注意,指针的副本,而不是指针指向的副本)
    【解决方案2】:

    您没有返回您认为从函数返回的指针。

    str1 = (char *)str3;
    

    您似乎认为这会更改 str1,使其指向(正确)连接的字符串 str3,但此更改在函数外部不可见。

    您可以(至少)通过两种方式解决此问题:

    1) 使用malloc进行分配

    char *str3 = malloc(str_size_1 + str_size_2);
    

    然后从函数中返回这个指针(而不是void)

    或 2)

    传递一个指向函数指针的指针,像这样

    void str_join(char **str1, char *str2)
    

    然后

    *str1 = str3;
    

    【讨论】:

      【解决方案3】:

      您希望达到的目标是在函数调用方法的引用方法的帮助下完成的。但是在您的代码中,str_join 是按值调用的函数。当您更改 str1 的值时,它仅针对函数的范围进行更改。因为,一旦您离开 str_join 范围,str1 的值就会再次更改为之前的值,因为您传递给函数的不是 str1 的地址,而是值的副本str1。你应该试试这个:

      void str_join(char **str1, char **str2) 
      

      // though the str2 need not to be passed by reference you can leave it as it is now

      将函数内的str1替换为*str1

      然后你可以在你的主函数中调用它:str_join(&amp;str1, &amp;str2)

      &amp; 符号表示您正在传递str1str2 的地址

      【讨论】:

        【解决方案4】:

        我确信有很多方法可以实现这里所需的内容。在 C 语言中一个合理的惯用方式是创建一个新的动态分配的字符串,其大小足以容纳两个原始字符串,并将其返回给调用者。

        #include <stdio.h>
        #include <string.h>
        #include <malloc.h>
        
        char *str_join(char *str1, char *str2)
          {
          char *result = malloc (strlen (str1) + strlen (str2) + 1);
          strcpy (result, str1);
          strcat (result, str2);
          return result;
          }
        
         int main(int argc, char **argv)
           {
           char *part1 = "Hello ";
           char *part2 = "World!";
           char *joined = str_join(part1, part2);
           printf("%s\n", joined);
           free (joined);
           return 0;
           }
        

        调用者必须在结果上调用 free()。合理的常见做法是假设任何返回“char *”的函数都返回必须释放的东西,而返回“const char *”的函数返回的东西不需要释放。然而,C 标准库中的许多基本的、长期存在的函数并不遵循这个约定。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-17
          • 2022-07-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多