gpt4 book ai didi

c - 将字符串返回到可变长度字符数组

转载 作者:太空宇宙 更新时间:2023-11-04 01:09:08 25 4
gpt4 key购买 nike

我有一个程序可以从可变长度字符数组的输入中反转字符串。该函数返回一个可变长度的字符数组并被打印出来。当我打印输出时,我确实得到了反转的字符串,但在我的控制台打印中附加了垃圾字符。

就返回缓冲区而言,这是“合法”操作吗?如果方法不正确,有人可以批评我的代码并提出更好的替代方案吗?

谢谢。

#include <stdio.h>
#include <stdlib.h>
char *reverse_string(char *input_string);

char *reverse_string(char *input_string)
{
int i=0;
int j=0;
char *return_string;
char filled_buffer[16];
while (input_string[i]!='\0')
i++;
while (i!=0)
{
filled_buffer[j]=input_string[i-1];
i--;
j++;
}
return_string=filled_buffer;
printf("%s", return_string);
return return_string;
}

int main (void)
{
char *returned_string;
returned_string=reverse_string("tasdflkj");
printf("%s", returned_string);
return 1;
}

这是我的 Xcode 输出 - jklfdsat\347\322̲\227\377\231\235

最佳答案

不,在函数中返回指向本地字符串的指针是不安全的。 C 不会阻止你这样做(尽管有时如果你要求编译器会警告你;在这种情况下,局部变量 return_string 会阻止它发出警告,除非你将代码更改为 return filled_buffer;).但这并不安全。基本上,该空间会被其他函数重用,因此它们会愉快地践踏曾经是格式整齐的字符串。

Can you explain this comment in more detail — "No, it isn't safe..."

当函数返回时,局部变量(相对于字符串常量)超出范围。返回指向范围外变量的指针是未定义的行为,这是无论如何都要避免的事情。当您调用未定义的行为时,任何事情都可能发生——包括程序似乎可以正常工作——并且没有理由提示,即使程序重新格式化了您的硬盘驱动器。此外,不能保证相同的事情会发生在不同的机器上,甚至不能保证在您当前机器上使用相同编译器的不同版本。

要么将输出缓冲区传递给函数,要么让函数使用 malloc() 分配可以返回给调用函数并由调用函数释放的内存。

将输出缓冲区传递给函数

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

int reverse_string(char *input_string, char *buffer, size_t bufsiz);

int reverse_string(char *input_string, char *buffer, size_t bufsiz)
{
size_t j = 0;
size_t i = strlen(input_string);
if (i >= bufsiz)
return -1;

buffer[i] = '\0';
while (i != 0)
{
buffer[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", buffer);
return 0;
}

int main (void)
{
char buffer[16];
if (reverse_string("tasdflkj", buffer, sizeof(buffer)) == 0)
printf("%s\n", buffer);
return 0;
}

内存分配

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

char *reverse_string(char *input_string);

char *reverse_string(char *input_string)
{
size_t j = 0;
size_t i = strlen(input_string) + 1;
char *string = malloc(i);
if (string != 0)
{
string[--i] = '\0';
while (i != 0)
{
string[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", string);
}
return string;
}

int main (void)
{
char *buffer = reverse_string("tasdflkj");
if (buffer != 0)
{
printf("%s\n", buffer);
free(buffer);
}
return 0;
}

请注意,示例代码在每个格式字符串的末尾包含一个换行符;这样可以更轻松地判断字符串的末端在哪里。

这是一个替代的 main(),它表明即使在多次调用 reverse_string() 函数(已修改为采用const char * 而不是普通的 char * 参数,但其他方面没有改变。

int main (void) 
{
const char *strings[4] =
{
"tasdflkj",
"amanaplanacanalpanama",
"tajikistan",
"ablewasiereisawelba",
};
char *reverse[4];
for (int i = 0; i < 4; i++)
{
reverse[i] = reverse_string(strings[i]);
if (reverse[i] != 0)
printf("[%s] reversed [%s]\n", strings[i], reverse[i]);
}
for (int i = 0; i < 4; i++)
{
printf("Still valid: %s\n", reverse[i]);
free(reverse[i]);
}
return 0;
}

此外(正如 pwny 在他的 answer 中指出的那样,在我将此注释添加到我的之前),您需要确保您的字符串以 null 结尾。返回指向本地字符串的指针仍然不安全,即使您可能不会立即发现示例代码的问题。这说明了输出末尾的垃圾。

关于c - 将字符串返回到可变长度字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16578476/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com