【问题标题】:How do I return a variable size string from a function?如何从函数返回可变大小的字符串?
【发布时间】:2011-08-25 17:40:05
【问题描述】:

我需要一个函数的工作代码,该函数将返回一个随机长度的随机字符串。

下面的代码会更好地描述我想做的事情。

char *getRandomString()
{
    char word[random-length];
    // ...instructions that will fill word with random characters.
    return word;
}
void main()
{
    char *string = getRandomString();
    printf("Random string is: %s\n", string);
}

为此,我严禁使用除 stdio.h 之外的任何其他包含。 编辑:该项目将适用于为 PIC 微控制器编译,因此我不能使用 malloc() 或类似的东西。 我在这里使用 stdio.h 的原因是我能够使用 GCC 检查输出。

目前,这段代码给出了这个错误。-
“警告:函数返回局部变量的地址[默认启用]”

然后,我认为这可以工作。-

char *getRandomString(char *string)
{
    char word[random-length];
    // ...instructions that will fill word with random characters.
    string = word;
    return string;
}
void main()
{
    char *string = getRandomString(string);
    printf("Random string is: %s\n", string);
}

但它只会打印一堆无意义的字符。

【问题讨论】:

  • 如果您希望获得可预测的结果,则不能返回指向堆栈上数据的指针。让调用者传递内存目标(例如 char*、 大小限制)或在堆上返回一些东西(通过malloc 分配,调用者必须free)。
  • stdio.h 不是库,而是标头。您是说不允许包含stdlib.h,因此不能选择malloc
  • 为什么要严格禁止?如果这是家庭作业,请添加homework 标签。您的具体要求是什么?
  • void main()错误。使用int main(void)。向任何告诉你使用void main()的书的作者投诉。
  • random-length 是什么意思是random 减去length 吗?或random_length,即单个变量。

标签: c pointers c-strings character-arrays


【解决方案1】:

有三种常见的方法可以做到这一点。

  1. 让调用者传入一个指针,该指针指向要存储数据的数组(的第一个元素)以及一个长度参数。如果要返回的字符串大于传入的长度,则为错误;你需要决定如何处理它。 (你可以截断结果,或者你可以返回一个空指针。无论哪种方式,调用者都必须能够处理它。)

  2. 返回一个指向新分配对象的指针,使调用者有责任在完成后调用free。如果malloc() 失败,可能会返回一个空指针(这总是有可能的,您应该始终检查它)。由于mallocfree<stdlib.h> 中声明,这不符合您的(人为)要求。

  3. 返回一个指向 static 数组(的第一个元素)的指针。这避免了返回指向本地分配对象的指针的错误,但它有其自身的缺点。这意味着以后的调用会破坏原始结果,并且会施加固定的最大大小。

如果这些是理想的解决方案,则没有。

【讨论】:

  • @alvin:如果您不允许使用<stdlib.h>,则不会。
  • #2 的一个变体是定义一个对称的freeRandomString() 函数来负责清理。在这个简单的示例中,这可能有点过头了,但是当您处理更复杂的数据结构时,它会干净得多。
  • @Oli:我使用的另一种方法是拥有 N 个结果的静态数组和数组的静态索引。在每次调用时增加索引,当它到达结束时将其设置回 0。这意味着调用者不必担心每次调用都会破坏前一次调用的结果,但如果您尝试保存 N 个以上的结果,它可能会严重失败。
  • 我使用了第三个 Keith 的方法,效果很好。感谢您的建议。
【解决方案2】:

它指向无意义的字符,因为您正在返回本地地址。 char word[random-length]; 本地定义为 char *getRandomString(char *string)

malloc动态分配字符串,填充字符串,用malloc返回返回地址。这个返回的地址是从堆中分配的,直到你不手动释放它(或者程序没有终止)。

char *getRandomString(void)
{
    char *word;
    word = malloc (sizeof (random_length));
    // ...instructions that will fill word with random characters.
    return word;
}

在你处理完分配的字符串后,记得释放字符串。

如果您不能使用malloc,则可以做另一件事,它将getRandomString 中的本地字符串定义为static,这样只要程序运行,静态声明的数组就会有生命周期。

char *getRandomString(void)
{
    static char word[LENGTH];
    // ...instructions that will fill word with random characters.
    return word;
}

或者简单地将char word[128]; 设为全局。

【讨论】:

  • 我不认为他可以使用malloc。
  • 然后要么将数组声明为静态,要么将其设为全局。
  • 我不能使用 malloc。如果我在函数中将数组声明为静态,编译器会抛出错误“错误:‘str’的存储大小不是常量”。而且我无法保留太多内存,因为我将针对可用内存非常少的 PIC 微控制器进行编译。
  • @Mario:在 C 中指定存储有三种方式:静态、本地(在堆栈上)和动态(malloc/calloc/realloc)。不能动态做,也不能返回本地存储,只能静态做。这意味着您需要在编译时指定最大字符串大小。
  • @David-Thornley 感谢您的回答,这是最清楚的回答,如果您将其添加为答案,我会选择您的答案作为正确的答案,但无论如何谢谢。
【解决方案3】:

据我了解,malloc 不是一种选择。

编写几个函数来 a) 获取一个随机整数(字符串长度),b) 一个随机字符。

然后使用这些来构建你的随机字符串。

例如:

//pseudocode
static char random_string[MAX_STRING_LEN];
char *getRandomString()
{
    unsigned int r = random_number();

    for (i=0;i<r;i++){
        random_string[i] = random_char();
    }

    random_string[r-1] = '\0';
}

【讨论】:

    【解决方案4】:

    如果不允许使用malloc,则必须声明一个数组,该数组可以是文件范围内可能的最大大小,并用随机字符填充。

    #define MAX_RANDOM_STRING_LENGTH  1024
    char RandomStringArray[MAX_RANDOM_STRING_LENGTH];
    
    char *getRandomString(size_t length)
    {
      if( length > ( MAX_RANDOM_STRING_LENGTH - 1 ) ) {
        return NULL; //or handle this condition some other way
    
      } else {
        // fill 'length' bytes in RandomStringArray with random characters.
        RandomStringArray[length] = '\0';
        return &RandomStringArray[0];
    
      }
    }
    
    int main()
    {
        char *string = getRandomString(100);
        printf("Random string is: %s\n", string);
    
        return 0;
    }
    

    【讨论】:

    • 它不必在文件范围内声明。它可以在函数内部使用static 关键字声明。而return &amp;RandomStringArray[0];可以写成return RandomStringArray;
    • @Keith Thompson 在这两个方面都是。关于后者,我更喜欢我使用的语法而不是您提到的语法。
    【解决方案5】:

    您的两个示例都返回指向局部变量的指针——这通常是一个禁忌。如果没有malloc(),您将无法为调用者创建内存以供使用,stdio.h 中未定义,所以我想您唯一的选择是将word 设为静态或全局,除非您可以声明它在main() 中并将指针传递给要填充的随机字符串函数。您如何仅使用stdio.h 中的函数生成随机数?

    【讨论】:

    • 实际上这些数字是由不同的机制生成的,在这里根本不重要,唯一重要的是,在该函数之后,运行时确定长度的数组将被随机填充数据。我在 GCC 中仅使用 stdio 来检查它,稍后我将调整为 PIC 微控制器编译的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2022-08-10
    • 1970-01-01
    • 2010-12-23
    • 2016-11-17
    • 1970-01-01
    相关资源
    最近更新 更多