所以问题出在我的割包字符串函数上。它应该接受一个字符串、一个字符和一个整数数组,返回不带字符的字符串,并标记它删除的所有字符。
char* circumcisedString(char* og, char rem, int* checked)
{
char circS[100];
char* t= circS;
char* og2 = og;
while(*og2)
{
if(*og2 != rem)
{
*t = *og2;
t++;
}
else
{
checked[og2 - og] = 1;
}
og2++;
}
*t = '\0';
printf("%d ", circS);
return circS;
}
void Three()
{
char str[100]; scanf("%99s", str);
char rem[100]; scanf("%99s", rem);
int strl = strlen(str);
int reml = strlen(rem);
int checked[reml];
for(int i = 0; i < reml; i++) checked[i] = 0;
for(int i = 0; i < reml; i++)
{
if(!checked[i])
{
char* remstr = circumcisedString(rem, rem[i], checked);
printf("%d ", remstr);
int j = 0, c = 0;
//j = mystrstr(str, remstr) - str;
//while(j = strstr(str + j, remstr) + 1) c++;
}
}
}
打印 circS 的“%s”(这是我指向新字符串的指针)后,我得到了我想要的,直到我返回它。返回时,它只返回一个空地址。在仍在代码中的 printf 测试中,“print("%d", circS)" 输出 6421472 作为它的内存位置,而 printf("%d ", remstr) 输出 0。有谁知道可能是什么问题是什么?
本质上,
circS
指向的数组在函数结束后超出了范围,因此函数的堆栈帧被清除,并且不存在的数组的地址不再存在。
当你打电话时
printf("%d ", circS);
数组仍在作用域内,堆栈帧仍然存在,因此
circS
指向的地址仍然有效。让我们假设circS = 0x0061FBE0
。当 circS
返回时,将 0x0061FBE0
放入 remstr
。但是,由于 circS
指向的数组超出了范围并且堆栈帧被释放,因此 0x0061FBE0
不再指向该数组,而是指向我们不应该搞乱的其他内容,这使其现在成为空地址。
删除某个字符的重复项后,可以直接修改原始字符串参数并返回该参数(或者什么也不返回,使其成为一个
void
函数)。
如果您需要保存原始字符串,只需使用 memcpy
进行复制即可。
char* circumcisedString(char* og, char rem, int* checked)
{
// do something with og
return og;
// or return nothing
}
这段代码之所以有效,是因为传入函数的参数是从调用函数的位置开始的,而函数结束后,参数仍然会存在于调用函数的地方,所以当函数返回到在调用它的地方,内存将保持有效。 (在您的具体情况下,
og
将是一个有效的内存地址,即rem
)。
关于您的代码的其他注释:
使用可变变量提供的大小声明变量是不安全的。
int checked[reml];
这很糟糕,因为编译器应该知道为数组分配的内存量,但变量的大小有时只能在运行时知道。将数组大小设置为不会被超越的上限。
另外,要默认初始化一个数组,你可以这样做
int arr[8] = {0};
而不是循环遍历数组;它只是更干净