我正在尝试在C中重新创建C ++函数std::string.pop_back
,其中弹出输入字符串的最后一个非NUL字符。在下面的pop_back
函数中,变量out
具有所需的函数输出,但尝试将*string
重新分配为out
会使*string
成为正确的值在函数关闭之前(例如,如果我在函数末尾打印string*
,它将输出Hello World
),但在main()
中,在pop_back()
之后被叫string
输出为空白。在重新分配string
时我做错了什么?
#include <stdio.h>
#include <string.h>
void pop_back(char** string) {
size_t stringLen = strlen(*string);
char out[stringLen];
strxfrm(out, *string, stringLen);
// Here *string == "Hello World!"
*string = out;
// Here *string == "Hello World"
}
int main(int argc, char* argv[]) {
char* string = "Hello World!";
printf("Initial string: %s\n", string);
pop_back(&string);
printf("After pop_back: %s\n", string);
return 0;
}
// Output:
// $ ./pop_back_test
// Initial string: Hello World!
// After pop_back:
// Expected output:
// $ ./pop_back_test
// Initial string: Hello World!
// After pop_back: Hello World
答案 0 :(得分:4)
使用您的代码
char out[stringLen];
...
*string = out;
“返回”(赋值给参数)指向“局部变量”的指针,即指向具有自动存储持续时间的对象的指针,其寿命在函数结束时结束。访问超出其生命周期的对象是不确定的行为。
您可能必须动态分配一个新字符串,然后您可以在函数执行结束后进行操作和使用。例如:
if (!(*string) || !(**string)) {
// decide what to do with NULL or empty input strings.
...
}
else {
size_t stringLen = strlen(*string);
char* out = malloc(stringLen);
memcpy(out, *string, stringLen);
out[stringLen-1] = '\0';
}
*string = out;
之后不要忘记释放分配的内存。顺便说一句:如果你操作副本,我建议返回(新)副本并保持输入指针不变,即我将原型更改为
char* pop_back(char* string) {
...
return out;
}
答案 1 :(得分:2)
当我单步执行代码时,调试器中的消息显示在线...
*string = out;
... *string
超过了数组范围,导致分配失败。 *string
指向 string literal ,这意味着它无法修改。尝试修改其内容将始终失败。
有几种方法可以解决这个问题。
一种方法是修改pop_back()
函数以接受char *
,并返回char *
,允许您传入不可变字符串并返回结果字符串。
建议实施:
char * pop_back(char *string)
{
size_t stringLen = strlen(string)+1;//add one for NULL
char *out = calloc(stringLen,1);//create space for new string
strxfrm(out, string, stringLen);
// Here *string == "Hello World!"
return out;//return string
// Here *string == "Hello World"
}
int main(int argc, char* argv[])
{
char *string1 = "Hello World!"; // source string
char *string2 = {0}; // container for local result
printf("Initial string: %s\n", string1);
string2 = pop_back(string1); // get local result
printf("After pop_back: %s\n", string2);// use local result
free(string2); // free local result
return 0;
}
答案 2 :(得分:0)
char out[stringLen];
是void pop_back(char ** string)的局部变量,超出了范围。