当前位置: 技术问答>linux和unix
今天作C语言程序的时候偶有心得,发现自己过去的很多程序是错误的.愿与各位共享.
来源: 互联网 发布时间:2015-02-10
本文导语: 请各位不要解释为什么这样写的原因都写一个函数,要求如下 char *replacestr(char* source_str,char* repl_str, char* with_str) { } 这个函数要求在source_str中用with_str替换repl_atr.大家看看是否简单,但是这个函数真的非常见功底.大家不妨尝...
请各位不要解释为什么这样写的原因都写一个函数,要求如下
char *replacestr(char* source_str,char* repl_str, char* with_str)
{
}
这个函数要求在source_str中用with_str替换repl_atr.大家看看是否简单,但是这个函数真的非常见功底.大家不妨尝试.
|
{
char *p, *buf;
if (!(p=strstr(source_str, repl_str)))
return(NULL);
buf=(char *)calloc(strlen(source_str)-strlen(repl_str)+strlen(with_str)+1, sizeof(char));
memmove(buf, source_str, p-source_str);
memmove(buf+(p-source_str), with_str, strlen(with_str));
memmove(buf+(p-source_str)+strlen(with_str), p+strlen(repl_str), strlen(p)-strlen(with_str));
return(buf);
}
char *p, *buf;
if (!(p=strstr(source_str, repl_str)))
return(NULL);
buf=(char *)calloc(strlen(source_str)-strlen(repl_str)+strlen(with_str)+1, sizeof(char));
memmove(buf, source_str, p-source_str);
memmove(buf+(p-source_str), with_str, strlen(with_str));
memmove(buf+(p-source_str)+strlen(with_str), p+strlen(repl_str), strlen(p)-strlen(with_str));
return(buf);
}
|
strstr()就是这么做的,它不分配内存,只是在原串中查找。
如果结果不是"???????",我到会觉得很可怕
如果结果不是"???????",我到会觉得很可怕
|
呵呵,当时我是想到这个问题了。
与其在这个函数里面进行多次替换,不如再写个wrapper函数。所以当时没写。
下面是完整的程序:
strrep是strrep0的wrapper。
strrep0只替代第一个出现的,
strrep调用strrep0迭代替换。
#include
char *strrep0(char* source_str,char* repl_str, char* with_str)
{
char *p, *buf;
if (!(p=strstr(source_str, repl_str)))
return(NULL);
buf=(char *)calloc(strlen(source_str)-strlen(repl_str)+strlen(with_str)+1, sizeof(char));
memmove(buf, source_str, p-source_str);
memmove(buf+(p-source_str), with_str, strlen(with_str));
memmove(buf+(p-source_str)+strlen(with_str), p+strlen(repl_str), strlen(p)-strlen(repl_str));
return(buf);
}
char *strrep(char* source_str,char* repl_str, char* with_str)
{
char *p, *q;
p=strdup(source_str);
while((q=fun(p, repl_str, with_str)))
{
free(p);
p=q;
}
return(p);
}
与其在这个函数里面进行多次替换,不如再写个wrapper函数。所以当时没写。
下面是完整的程序:
strrep是strrep0的wrapper。
strrep0只替代第一个出现的,
strrep调用strrep0迭代替换。
#include
char *strrep0(char* source_str,char* repl_str, char* with_str)
{
char *p, *buf;
if (!(p=strstr(source_str, repl_str)))
return(NULL);
buf=(char *)calloc(strlen(source_str)-strlen(repl_str)+strlen(with_str)+1, sizeof(char));
memmove(buf, source_str, p-source_str);
memmove(buf+(p-source_str), with_str, strlen(with_str));
memmove(buf+(p-source_str)+strlen(with_str), p+strlen(repl_str), strlen(p)-strlen(repl_str));
return(buf);
}
char *strrep(char* source_str,char* repl_str, char* with_str)
{
char *p, *q;
p=strdup(source_str);
while((q=fun(p, repl_str, with_str)))
{
free(p);
p=q;
}
return(p);
}
|
学习ing...
|
char *replacestr(char* source_str,char* repl_str, char* with_str)
{
int len,w_len;
char *s,*r,*w,*p;
s = source_str;
r = repl_str;
w = with_str;
w_len = strlen(w);
for(p=s;p!=NULL;)
{
s = strstr(s,w);
if(s==NULL)
{
strcpy(r,p);
break;
}
len = s - p;
memcpy(r,s,len);
s += len;
r += len;
memcpy(r,w,w_len);
r += w_len;
}
return repl_str;
}
{
int len,w_len;
char *s,*r,*w,*p;
s = source_str;
r = repl_str;
w = with_str;
w_len = strlen(w);
for(p=s;p!=NULL;)
{
s = strstr(s,w);
if(s==NULL)
{
strcpy(r,p);
break;
}
len = s - p;
memcpy(r,s,len);
s += len;
r += len;
memcpy(r,w,w_len);
r += w_len;
}
return repl_str;
}
|
你的程序十有八就会core.
|
兄弟,你这个不就是要两个异常判断就搞定了吗?
1。 判断空指针和空字符串
2。 判断是否存在内存覆盖
1。 判断空指针和空字符串
2。 判断是否存在内存覆盖
|
char *replacestr(char* source_str,char* repl_str, char* with_str)
{
int len,w_len,r_len;
char *s,*r,*w,*p,*q,*t;
s = source_str;
r = repl_str;
w = with_str;
w_len = strlen(w);
r_len = strlen(r);
t = (char*)malloc(strlen(s)+w_len-r_len+1);
for(p=t,q=s;;)
{
q = strstr(s,r);
if(q==NULL)
{
strcpy(p,s);
break;
}
len = q - s;
memcpy(p,s,len);
p += len;
memcpy(p,w,w_len);
p += w_len;
s += len + r_len;
}
strcpy(source_str,t);
free(t);
return source_str;
}
{
int len,w_len,r_len;
char *s,*r,*w,*p,*q,*t;
s = source_str;
r = repl_str;
w = with_str;
w_len = strlen(w);
r_len = strlen(r);
t = (char*)malloc(strlen(s)+w_len-r_len+1);
for(p=t,q=s;;)
{
q = strstr(s,r);
if(q==NULL)
{
strcpy(p,s);
break;
}
len = q - s;
memcpy(p,s,len);
p += len;
memcpy(p,w,w_len);
p += w_len;
s += len + r_len;
}
strcpy(source_str,t);
free(t);
return source_str;
}
|
还是会core的。
你怎么保证替换后的字符串比原串短?
你怎么保证替换后的字符串比原串短?
|
我知道有这个问题,如果真的要解决的话,最好的办法是再加2个参数,
char *replacestr(char* source_str,char* repl_str, char* with_str,char *out_buf,int len);
char *replacestr(char* source_str,char* repl_str, char* with_str,char *out_buf,int len);
|
在使用频率较高,功能单一的函数中最好不要加入过多的有效性检查,要放在较高一层去做
|
如果注意一下,调用函数的原型,错误会少多了
strstr(..) 函数返回值是 char* 指针,即所匹配的地址,库函数里很少会主动帮调用者申请空间的.(涉及到 释放等原因),若有,函数帮助中回特别说明
strstr(..) 函数返回值是 char* 指针,即所匹配的地址,库函数里很少会主动帮调用者申请空间的.(涉及到 释放等原因),若有,函数帮助中回特别说明
|
子函数负责分配空间,父函数负责释放。这是很常用的做法。
特别是父函数该分配多时时经常使用。
库函数也有,比如strdup()。
如果你经常读代码,应该会常看到这种情况。
特别是父函数该分配多时时经常使用。
库函数也有,比如strdup()。
如果你经常读代码,应该会常看到这种情况。
|
Sorry,笔误。
“特别是父函数不知道该分配多时时经常使用。”
“特别是父函数不知道该分配多时时经常使用。”
|
我觉得子函数负责分配空间,父函数负责释放,只是不得以的做法。好的做法是分配与释放内存都在同一个层次进行,要么是在同一个函数内,要么设计2个单独的函数,一个分配了内存,另一个负责释放
|
我不认为是不得以的办法。
你可以man一下getcwd,getcwd函数的参数已经有指针了,
但如果该参数为NULL,getcwd会为你分配堆空间的。
你一可以考虑calloc,它实际上是一个malloc加一个memset
实际上完全可以将他们分开,但为了方便定义了calloc
再比如c++中的new运算符,实际上是malloc后调用构造函数。
在逻辑上,你可以把任何子函数分配空间的函数看成内存分配函数。
他们在逻辑上跟malloc没什么区别,只不过又作了一点其他处理,
就象calloc一样,只不过可能比calloc复杂一点。
你可以man一下getcwd,getcwd函数的参数已经有指针了,
但如果该参数为NULL,getcwd会为你分配堆空间的。
你一可以考虑calloc,它实际上是一个malloc加一个memset
实际上完全可以将他们分开,但为了方便定义了calloc
再比如c++中的new运算符,实际上是malloc后调用构造函数。
在逻辑上,你可以把任何子函数分配空间的函数看成内存分配函数。
他们在逻辑上跟malloc没什么区别,只不过又作了一点其他处理,
就象calloc一样,只不过可能比calloc复杂一点。
|
若调用者忘记释放空间,就会有内存泄漏,若释放方式不对,如 malloc ->用了 delete,
new 来的用 free,
另外 对于楼主的问题
用转成 std::string 更简单
string::substr(..),
string::replace(...)
new 来的用 free,
另外 对于楼主的问题
用转成 std::string 更简单
string::substr(..),
string::replace(...)
|
说来说去,只是编程的风格不同,但有一点一定对的,没把握的话,最好man函数帮助.从某个侧面上说,对开发者来说,文档资料是如此的重要,
没人会知道你提供的库,是否有无心的"陷阱"
没人会知道你提供的库,是否有无心的"陷阱"
|
good
|
忘了释放空间或这释放错了,这跟到底是谁分配的内存无关。
而是写程序的人的错误。如果这个人无法认真的阅读理解C程
序中关于内存分配的问题。那我建议他还是用象Java这样带GC
功能的语言吧,只是别指望用这类语言进行系统程序设计。
打个比方:
假设你自行车骑不好而经常摔交,那时你的问题,不是自行车的问题。
也别说是自行车给你设下的陷阱。如果你骑不好非想骑而又不想摔交,
可以买个儿童自行车,就是后轮带两边各带一个小轮的那种。或干脆
改骑三轮吧。
而是写程序的人的错误。如果这个人无法认真的阅读理解C程
序中关于内存分配的问题。那我建议他还是用象Java这样带GC
功能的语言吧,只是别指望用这类语言进行系统程序设计。
打个比方:
假设你自行车骑不好而经常摔交,那时你的问题,不是自行车的问题。
也别说是自行车给你设下的陷阱。如果你骑不好非想骑而又不想摔交,
可以买个儿童自行车,就是后轮带两边各带一个小轮的那种。或干脆
改骑三轮吧。
|
用shell比C++还简单,一行搞定:
echo $source_str | sed "s/$replace_str/$with_str/g"
echo $source_str | sed "s/$replace_str/$with_str/g"