繁体   English   中英

如何调用 function 作为 strcpy 中的第二个字符串?

[英]How to have a call function as the second string in strcpy?

我需要从 main 调用 function 以确定字符串值。 但是,据我所知,字符串不能采用string_name = call_function()的形式。 字符串的分配必须采用strcpy(str1, str2)的形式,对吗? 所以我想知道我在用str1作为变量名而str2是另一个strcpy的返回字符串值时我做错了什么。

到目前为止,这就是我所拥有的。

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

char *get_name(int num);

char *get_name(int num) {
    char real_name[30];
    
    if (num == 1)
        strcpy(real_name, "Jake Peralta");
    
    return real_name;
}

void main() {
    char name[30];
    int num;
    
    num = 1;
    
    strcpy(name, *get_name(num));
    printf("%s", name);
}

它没有在我的 output 屏幕上打印任何内容。

我试过的:

  • get_name(num)不使用指针(仍然不起作用)

p/s:这不是实际的代码。 这只是我正在尝试做的一个例子,实际代码更长,我已经确定这部分是错误的来源。

您是对的,字符串不能通过return语句作为数组返回。 当您传递或返回一个数组时,只使用指向其第一个元素的指针。 因此,function get_name()返回一个指向使用自动存储在本地定义的数组的指针(也就是在堆栈上)。 这是不正确的,因为该数组一离开 scope 即被丢弃,即:当 function 返回时。

get_name()有几种方法可以向调用者提供名称:

  • 您可以传递目标数组及其长度:并让 function 填充数组中的名称,小心避免超出数组末尾,但确保它具有 null 终止符:

     char *get_name(char *dest, size_t size, int num) { if (num == 1) { snprintf(dest, size, "Jake Peralta"); } else { snprintf(dest, size, "John Doe"); } // return the destination pointer for convenience. return dest; } int main() { char name[30]; int num = 1; get_name(name, sizeof name, num); printf("%s\n", name); return 0; }
  • 您可以在get_name()中分配 memory 并返回指向复制字符串的已分配数组的指针。 当不再使用此 object 时,调用者将负责使用free()它。

     char *get_name(int num) { if (num == 1) { return strdup("Jake Peralta"); } else { return strdup("John Doe"); } } int main() { int num = 1; char *name = get_name(num); printf("%s\n", name); free(name); return 0; }
  • 您可以返回一个常量字符串,但只有在编译时知道所有名称时才能这样做。

     const char *get_name(int num) { if (num == 1) { "Jake Peralta"; } else { "John Doe"; } } int main() { int num = 1; const char *name = get_name(num); printf("%s\n", name); return 0; }

您正在从get_name方法返回real_name的地址,在 function 返回后,go 从 scope 中返回。 而是在堆上分配字符串的 memory 并返回其地址。 此外,调用者需要释放在堆上分配的字符串 memory 以避免任何 memory 泄漏。

就像您说的那样,“但是,据我所知,字符串不能采用string_name = call_function()的形式。” 要了解这背后的逻辑,只需查看您的get_name() function:

char *get_name(int num)
{
    char real_name[30];
    
    if (num==1)
        strcpy(real_name,"Jake Peralta");
    
    return real_name;
}

在这里,您尝试返回 real_name 的起始地址,但是real_name在超出real_name时被销毁(在这种情况下,当 function 返回时)。 我认为有两种方法可以解决这个问题。 一种是添加应该保存返回值的字符串作为参数。 在您的情况下,它将是:

void get_name(int num, char *dest)
{
    char real_name[30];
    
    if (num==1)
    {
        strcpy(real_name,"Jake Peralta");
        strcpy(dest, real_name);
    }
}

或者,现在完全避免使用real_name以使 function 更短:

void get_name(int num, char *dest)
{
    if (num==1)
        strcpy(dest, "Jake Peralta");
}

另一种方法是在堆上分配返回值,但我不建议这样做; 您必须跟踪每个分配的字符串并最终释放所有字符串。 不过,在您的情况下,情况如下:

char *get_name(int num, char *dest)
{
    char *real_name = calloc(30, sizeof(char)); // Using calloc to avoid returning an uninitialized string if num is not 1
    if (num==1)
        strcpy(real_name, "Jake Peralta";
    return real_name;
}

顺便说一句,我将您的strcpy保留在这里,但可能希望将来避免使用它,因为它可能导致缓冲区溢出。 这是一篇关于为什么不好的有用答案的帖子 事实上,即使strncpy也不是完全安全的(请参阅此处(感谢@chqrlie 提供链接))。 @chqrlie 在他自己的答案中使用snprintf提供了一种干净且安全的替代方案,我建议您使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM