C语言 如何从函数返回字符串?

mum43rcc  于 2022-12-03  发布在  其他
关注(0)|答案(3)|浏览(153)

通常我用PHP开发。但是对于一个项目,我必须用C开发一个小程序(在Windows上使用Visual Studio)为了简化我的代码,我创建了一个返回字符串的函数(该函数比示例中的函数更复杂)。
最初我有一个警告C4172: returning address of local variable or temporary [duplicate],我修改了我的函数,不再有这个警告。它工作。但代码是正确的...?

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

// Declaration Function
char* getMyString();

//----------------------------//
// Function getMyString()     //
//----------------------------//
char* getMyString()
{
  char* response = NULL;
  response = (char*)malloc(5 * sizeof(char)); if (response == NULL) exit(EXIT_FAILURE);

  strcpy(response, "EFGH");

  return response;
}


//--------------------------------------------------//
//                    Main Program                  //
//--------------------------------------------------//
int main(int nbArg, char** listeArg)
{
  // Initialization
  char* myStringFull = malloc(10 * sizeof(char)); if (myStringFull == NULL) return EXIT_FAILURE;
  char* myString = NULL;

  // Get String with Personnal Function
  myString = getMyString();

  // Finalization
  strcpy(myStringFull, "ABCD");
  strcat(myStringFull, myString);

  // Display
  printf("\n%s\n\n", myStringFull);

  // Free Memory
  free(myStringFull);
  free(myString);

  return(EXIT_SUCCESS);
}

如果上面的代码是正确的,我可以使用下面的代码来进一步简化我的代码吗?如果我可以,它是如何发生在内存中的,因为对于最后一个代码,我不能释放函数使用的内存

int main(int nbArg, char** listeArg)
{
  // Initialization
  char* myStringFull = malloc(10 * sizeof(char)); if (myStringFull == NULL) return EXIT_FAILURE;

  // Finalization
  strcpy(myStringFull, "ABCD");
  strcat(myStringFull, getMyString());

  // Display
  printf("\n%s\n\n", myStringFull);

  // Free Memory
  free(myStringFull);

  return(EXIT_SUCCESS);
}

希望我的问题不是太傻,但PHP和C之间有一个巨大的、巨大的、深渊般的差距:)

cs7cruho

cs7cruho1#

您所做的是正确的。但是,您已经注意到这是一个相当大的工作量,并且您必须记住在之后释放分配的内存。如果可能的话,我将使用C++,这样您就可以毫无顾虑地返回一个std::string,就像您在PHP和许多其他语言中所做的那样。
在C语言中,还有其他函数可以帮助你创建字符串。例如,复制字符串可以通过POSIX函数strdup()来完成。你也可以在GNU和BSD平台上使用asprintf()
除了分配内存,你还可以打印到缓冲区。要从一个函数中实现这一点,你需要将一个指向缓冲区的指针及其大小传递给该函数。例如:

void getMyString(char *buf, size_t size) {
    snprintf(buf, size, "EFGH");
}

int main(int argc, char *argv[]) {
    char myStringFull[10];
    int pos = snprintf(myStringFull, sizeof myStringFull, "ABCD");
    getMyString(myStringFull + pos, sizeof myStrinfFull - pos);
    printf("%s\n", myStringFull);
}

请注意,以上仍然是遗漏错误检查; snprintf()的返回值是在缓冲区足够大的情况下已经写入的字符数,或者可能是指示错误的负数。

qq24tv8q

qq24tv8q2#

有三种主要的方法来做你想做的事情:
1.您可以只声明一个static缓冲区,该缓冲区具有足够的空间来在不使用函数时保存数据

char *func(...)
{
    static char my_buffer[1000]; /* enough space for the biggest answer */
    /* do some calculations to fill my_buffer */
    return my_buffer;  /* return a pointer to the prepared data */
}

这种解决方案的缺点是它不是可重入的,因此如果两个线程试图同时使用它,bot执行将覆盖缓冲区,结果将被丢弃。
1.你可以用malloc(3)来分配动态内存,并返回指向所分配内存的指针。这样做的缺点是,一旦不再尼德内存,调用例程就负责(并且必须知道)使用free(3)

char *func(...)
{
    char *ret_val = malloc(/* enough space to hold the data */);
    /* blah blah... */
    return ret_val;
}

此解决方案使调用代码负责返回内存,因此容易出错。
1.你可以从调用代码传递一个本地的,已经分配的缓冲区,以及它的大小。你可以使用这个缓冲区来保存请求的数据,然后返回一个有效的指针指向你的字符串开始的地方(我也不需要从缓冲区的开始)

char *func(char *buffer, size_t siz)
{
    /* sample code */
    snprintf(buffer, siz, "Hello, world\n");
    return buffer;
}
/* ... */
void calling_code()
{
    char buffer[100];
    printf("the string is [%s]\n", func(buffer, sizeof buffer));
}

这种方法让调用方负责分配空间,因此,它不必是动态的,可以是本地空间,因为您将引用传递给它及其大小。
你可以选择最适合你的,但在我看来,更灵活的是最后一种。你就都试试吧。

oaxa6hgo

oaxa6hgo3#

在C语言中,字符串只是数组中的字符序列,但你不能从函数中返回数组,所以你不能直接返回'string'。
C函数通常做的是将数组(和大小)作为参数传递给函数,然后让函数将字符串放入数组中“返回”它。它们的第一个和第二个参数是一个指向数组的指针和数组的大小。在你的例子中,这将是这样的:

char* getMyString(char *buffer, size_t len) {
    snprintf(buffer, len, "%s", "EFGH");
    return buffer;
}

相关问题