我正在实现一个函数,给定一个字符串,一个字符和另一个字符串(因为现在我们可以将其称为子字符串");将子字符串放在字符在字符串中的任何位置. 为了更好地解释我,给定这些参数,这就是函数应该返回的内容(伪代码):
I'm implementing a function which, given a string, a character and another string (since now we can call it the "substring"); puts the substring everywhere the character is in the string. To explain me better, given these parameters this is what the function should return (pseudocode):
func ("aeiou", 'i', "hello") -> aehelloou我正在使用string.h lib中的一些函数.我已经对其进行了很好的测试:
I'm using some functions from string.h lib. I have tested it with pretty good result:
char *somestring= "this$ is a tes$t wawawa$wa"; printf("%s", strcinsert(somestring, '$', "WHAT?!") ); Outputs: thisWHAT?! is a tesWHAT?!t wawawaWHAT?!wa所以现在一切都很好.问题是,当我尝试使用以下字符串进行此操作时:
so for now everything is allright. The problem is when I try to do the same with, for example this string:
char *somestring= "this \"is a test\" wawawawa"; printf("%s", strcinsert(somestring, '"', "\\\"") );因为我想将每个"更改为\".当我这样做时,PC崩溃了.我不知道为什么,但是它停止工作,然后关闭.我已经了解了string.h lib某些功能的不良行为,但是我找不到有关此信息,我真的很感谢任何帮助.
since I want to change every " for a \" . When I do this, the PC collapses. I don't know why but it stops working and then shutdown. I've head some about the bad behavior of some functions of the string.h lib but I couldn't find any information about this, I really thank any help.
我的代码:
#define salloc(size) (str)malloc(size+1) //i'm lazy typedef char* str; str strcinsert (str string, char flag, str substring) { int nflag= 0; //this is the number of times the character appears for (int i= 0; i<strlen(string); i++) if (string[i]==flag) nflag++; str new=string; int pos; while (strchr(string, flag)) //since when its not found returns NULL { new= salloc(strlen(string)+nflag*strlen(substring)-nflag); pos= strlen(string)-strlen(strchr(string, flag)); strncpy(new, string, pos); strcat(new, substring); strcat(new, string+pos+1); string= new; } return new; }感谢您的帮助!
推荐答案一些建议:
- 不要使用typedef char* str;. char *类型在C语言中很常见,并且将其屏蔽会导致您的代码更难审核
- 出于完全相同的原因,请避免使用#define salloc(size) (str)malloc(size+1).另外,请勿在C语言中投射malloc
- 每次编写malloc(或calloc或realloc)时,都应该有一个相应的free:C没有垃圾回收
- 动态分配非常昂贵,请仅在需要时使用它.换句话说,循环内的malloc应该查看两次(特别是如果没有相应的free的话)
- 始终测试分配函数(无关:和io),当耗尽内存时,malloc将仅返回NULL.这样,一条不错的错误消息比崩溃更容易理解
- 学习使用调试器:如果您是在调试器下执行代码的,则错误很明显
- refrain from typedef char* str;. The char * type is common in C and masking it will just make your code harder to be reviewed
- refrain from #define salloc(size) (str)malloc(size+1) for the exact same reason. In addition don't cast malloc in C
- each time you write a malloc (or calloc or realloc) there should be a corresponding free: C has no garbage collection
- dynamic allocation is expensive, use it only when needed. Said differently a malloc inside a loop should be looked at twice (especially if there is no corresponding free)
- always test allocation function (unrelated: and io) a malloc will simply return NULL when you exhaust memory. A nice error message is then easier to understand than a crash
- learn to use a debugger: if you had executed your code under a debugger the error would have been evident
接下来的原因:如果替换字符串包含原始字符串,那么您将再次落在其上并无休止地循环运行
Next the cause: if the replacement string contains the original one, you fall again on it and run in an endless loop
一种可能的解决方法:在循环之前 分配结果字符串,并在原始循环和结果中进行排序.这样可以避免不必要的分配和取消分配,并避免替换字符串中存在原始字符.
A possible workaround: allocate the result string before the loop and advance both in the original one and the result. It will save you from unnecessary allocations and de-allocations, and will be immune to the original char being present in the replacement string.
可能的代码:
// the result is an allocated string that must be freed by caller str strcinsert(str string, char flag, str substring) { int nflag = 0; //this is the number of times the character appears for (int i = 0; i<strlen(string); i++) if (string[i] == flag) nflag++; str new_ = string; int pos; new_ = salloc(strlen(string) + nflag*strlen(substring) - nflag); // should test new_ != NULL char * cur = new_; char *old = string; while (NULL != (string = strchr(string, flag))) //since when its not found returns NULL { pos = string - old; strncpy(cur, old, pos); cur[pos] = '\0'; // strncpy does not null terminate the dest. string strcat(cur, substring); strcat(cur, string + 1); cur += strlen(substring) + pos; // advance the result old = ++string; // and the input string } return new_; }注意:我没有还原str和salloc,但您确实应该这样做.
Note: I have not reverted the str and salloc but you really should do.
更多推荐
将字符串插入C中的另一个字符串
发布评论