【发布时间】:2018-08-20 06:08:58
【问题描述】:
这是我程序中的函数原型:void FindRepStr(char str[], const char findStr[], const char replaceStr[]);
它在str[] 中找到findStr[] 并将其替换为replaceStr[]。
这是我的代码:
void FindRepStr(char str[], const char findStr[], const char replaceStr[])
{
char *s = nullptr;
s = strstr(str,findStr); //s points to the first-time appear in str
char tmp[] ="";
//length equal
if(strlen(findStr)==strlen(replaceStr))
{
for(int i=0;i<strlen(findStr);i++)
{
if(replaceStr[i]=='\0' || s[i] =='\0')
break;
else
s[i] = replaceStr[i];
}
cout<<str<<endl;
}
else
{
//find shorter than replace
if(strlen(findStr)<strlen(replaceStr))
{
//!!!problem here!!!
strncpy(tmp,s,strlen(s)+1); // store the left part
for(int i=0;i<=strlen(replaceStr);i++)
{
if(replaceStr[i]=='\0') //if end of replace
{
s[i]='\0'; //make s(str) end here
break;
}
else
s[i] = replaceStr[i]; //if not end, give the value
}
}
//finder longer than replace
else
{
//...not finished yet
}
}
}
我还没有完成这个,但是在 strncpy 之后,我打印了 s 和 tmp 进行测试,我发现 tmp 被正确复制,但是 s 打印出来是空的:
cout<<"s before strncpy:"<<s<<endl;
strncpy(tmp,s,strlen(s)+1);
cout<<"tmp after strncpy:"<<tmp<<endl;
cout<<"s after strncpy:"<<s<<endl;
但是在我写的简单测试程序中,我发现它不会被清空:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char a[]="abc";
char b[]="defgh";
cout<<"a before:"<<a<<endl;
cout<<"b before:"<<b<<endl;
strncpy(a,b,strlen(b)+1);
cout<<"a after:"<<a<<endl;
cout<<"b after:"<<b<<endl;
return 0;
}
我的程序出了什么问题?
【问题讨论】:
-
1) 不要将明显是 C 的问题标记为 C++。在 C++ 中,您应该使用
std::string,而不是编写所有这些低级操作代码。 2)for(int i=0;i<strlen(findStr);i++)不要这样做。这是非常低效的。在某些情况下,编译器可以拯救你,但在这个特定的情况下,它实际上不能。它必须在循环的每次迭代中调用strlen(时间与字符串的长度呈线性关系)。 -
你总是可以通过在进入循环之前调用一次
strlen(findStr)来优化,在一个临时变量中获取长度并在循环中使用它而不是for(int i=0;i<strlen(findStr);i++) -
但有
cout语句,编译器是 C++,所以它是 C++ C 风格,但它是 C++:meta.stackoverflow.com/questions/360709/… -
请提供 MCVE stackoverflow.com/help/mcve 。此外,你如何调用你的函数?因为我没有看到任何检查 s 是否为 NULL。
-
不要使用
strncpy。它不会像你想的那样。