简体   繁体   English

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

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

I need to call a function from the main to determine a string value.我需要从 main 调用 function 以确定字符串值。 However, as far as I know, string cannot be in the form string_name = call_function() .但是,据我所知,字符串不能采用string_name = call_function()的形式。 The assignment of string has to be in form of strcpy(str1, str2) right?字符串的分配必须采用strcpy(str1, str2)的形式,对吗? So I am wondering what am I doing wrong with this strcpy with str1 as the variable name and the str2 is a return string value from another function.所以我想知道我在用str1作为变量名而str2是另一个strcpy的返回字符串值时我做错了什么。

So far, this is what I have.到目前为止,这就是我所拥有的。

#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);
}

It is not printing anything on my output screen.它没有在我的 output 屏幕上打印任何内容。

What I have tried:我试过的:

  • get_name(num) without using pointers (still does not work) get_name(num)不使用指针(仍然不起作用)

p/s: This is not the actual code. p/s:这不是实际的代码。 This is just an example of what I am trying to do, the actual code is longer and I have identified that this part is where the error is coming from.这只是我正在尝试做的一个例子,实际代码更长,我已经确定这部分是错误的来源。

You are correct, a string cannot be returned as an array via the return statement.您是对的,字符串不能通过return语句作为数组返回。 When you pass or return an array, only a pointer to its first element is used.当您传递或返回一个数组时,只使用指向其第一个元素的指针。 Hence the function get_name() returns a pointer to the array defined locally with automatic storage (aka on the stack ).因此,function get_name()返回一个指向使用自动存储在本地定义的数组的指针(也就是在堆栈上)。 This is incorrect as this array is discarded as soon as it goes out of scope, ie: when the function returns.这是不正确的,因为该数组一离开 scope 即被丢弃,即:当 function 返回时。

There are several ways for get_name() to provide the name to its caller: get_name()有几种方法可以向调用者提供名称:

  • you can pass a destination array and its length: and let the function fill the name in the array, carefully avoiding to write beyond the end of the array but making sure it has a null terminator:您可以传递目标数组及其长度:并让 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; }
  • you can allocate memory in get_name() and return a pointer to the allocated array where you copy the string.您可以在get_name()中分配 memory 并返回指向复制字符串的已分配数组的指针。 It will be the caller's responsibility to free this object with free() when it is no longer used.当不再使用此 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; }
  • you can return a constant string, but you can only do this if all names are known at compile time.您可以返回一个常量字符串,但只有在编译时知道所有名称时才能这样做。

     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; }

You are returning address of real_name from get_name method which will go out of scope after the function returns.您正在从get_name方法返回real_name的地址,在 function 返回后,go 从 scope 中返回。 Instead allocate the memory of string on heap and return its address.而是在堆上分配字符串的 memory 并返回其地址。 Also, the caller would need to free the string memory allocated on the heap to avoid any memory leaks.此外,调用者需要释放在堆上分配的字符串 memory 以避免任何 memory 泄漏。

Like you said, "However, as far as I know, string cannot be in the form string_name = call_function() ."就像您说的那样,“但是,据我所知,字符串不能采用string_name = call_function()的形式。” To understand the logic behind this, just look at your get_name() function:要了解这背后的逻辑,只需查看您的get_name() function:

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

Here, you try to return the starting address of real_name , but real_name is destroyed when it goes out of scope (in this case, when the function returns).在这里,您尝试返回 real_name 的起始地址,但是real_name在超出real_name时被销毁(在这种情况下,当 function 返回时)。 There are two ways I think you could fix this.我认为有两种方法可以解决这个问题。 One is to add the string that should hold the return value as a parameter.一种是添加应该保存返回值的字符串作为参数。 In your case, it would be:在您的情况下,它将是:

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

Or, just avoid using real_name at all now to make the function shorter:或者,现在完全避免使用real_name以使 function 更短:

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

The other way is to allocate the return value on the heap, but I wouldn't recommend this;另一种方法是在堆上分配返回值,但我不建议这样做; you would have to keep track of each allocated string and eventually free all of them.您必须跟踪每个分配的字符串并最终释放所有字符串。 Nevertheless, here is how it would look like in your case:不过,在您的情况下,情况如下:

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;
}

By the way, I kept your strcpy here, but might want to avoid using it in the future, as it can cause buffer overruns.顺便说一句,我将您的strcpy保留在这里,但可能希望将来避免使用它,因为它可能导致缓冲区溢出。 Here's a post with useful answers as to why it's bad . 这是一篇关于为什么不好的有用答案的帖子 In fact, even strncpy isn't fully safe (See here (credit to @chqrlie for providing the link)).事实上,即使strncpy也不是完全安全的(请参阅此处(感谢@chqrlie 提供链接))。 @chqrlie provides a clean and safe alternative using snprintf in his own answer, I'd suggest you use that. @chqrlie 在他自己的答案中使用snprintf提供了一种干净且安全的替代方案,我建议您使用它。

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

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