2010-09-11 25 views
0

我对C非常陌生,我决定创建一个名为str_replace的函数,它替换使用malloc创建的字符串内部的字符串。它似乎工作,但任何人都可以找到任何改善的余地。有什么办法来改善这个函数,用malloc分配的字符串中的另一个字符串替换子字符串的出现?

任何意见将不胜感激。我想知道,如果人们认为找到出现次数来计算新的字符串大小是一个好主意,并且如果我使用指针是有道理的。

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

char * str_replace(char * string,char * find,char * replace){ 
    //Replaces each occurence of a particular string inside a malloc-made string with another string 
    char * pos = string; 
    size_t replace_size = strlen(replace); 
    size_t find_size = strlen(find); 
    size_t excess = replace_size - find_size; 
    //Get number of occurences 
    int x = 0; 
    while (1) { 
     pos = strstr(pos,find); 
     if (pos == NULL){ 
      break; 
     } 
     pos++; 
     x++; 
    } 
    if (!x){ //No occurences so return with original string 
     return string; 
    } 
    char * new_string = malloc(sizeof(char)*(strlen(string) + excess*x + 1)); //Plus 1 for null termination 
    pos = string; //Reset pointer 
    char * string_track = string; //Used to move around string. 
    char * new_string_begin = new_string; //Begining of new string to return 
    while (1) { 
     pos = strstr(pos,find); 
     if (pos == NULL){ 
      strcpy(new_string,string_track); //Fill in remainder 
      break; 
     } 
     pos++; 
     size_t seg_len = pos-string_track; //Length between found string and last 
     strncpy(new_string,string_track,seg_len); //Copy string to just before pos 
     new_string += seg_len - 1; //Go to point for replacement by adding what was added to pointer. 
     strncpy(new_string,replace,replace_size); 
     new_string += replace_size; //Go to point after what was replaced 
     string_track = pos + find_size - 1; //Original string should go to point after found string. 
    } 
    free(string); //Remove old string 
    return new_string_begin; //return new string 
} 

int main (int argc, const char * argv[]) { 
    char * string = malloc(sizeof(char)*21); 
    strcpy(string,"No,yes,no,yes,no,yes"); 
    printf("%s\n",string); 
    string = strreplace(string, "no", "nope"); 
    printf("%s\n",string); 
    free(string); 
    string = malloc(sizeof(char)*21); 
    strcpy(string,"No,yes,no,yes,no,yes"); 
    printf("%s\n",string); 
    string = strreplace(string, "hello", "nope"); 
    printf("%s\n",string); 
    free(string); 
    string = malloc(sizeof(char)*21); 
    strcpy(string,"No,yes,no,yes,no,yes"); 
    printf("%s\n",string); 
    string = strreplace(string, "yes", "y"); 
    printf("%s\n",string); 
    free(string); 
    return 0; 
} 
+0

尝试存储针的位置,因此您不必搜索两次。 – arthurprs 2012-04-23 00:04:33

回答

2

总的来说这是非常坚实的,有些事情我会建议将

1)不名的第一个参数“字符串” ..我认为是一个有点冒险(不string.h中定义了一个“字符串“的符号?)

2)我不会释放str_replace函数中的旧字符串,它不是由该函数分配的,所以它不应该释放它IMO,这个例子不是很重要,但它是一般是一个好习惯。这也意味着它不需要“string_track”变量,因为第一个arg只是一个指向字符串的指针的副本,您可以使用它并且不关心它在哪里结束,导致它在函数中被抛弃退出。

+0

谢谢你的回答。我为我制作的程序制作了这个功能,而我的一般用途不需要旧数据。因此,我觉得为了方便,最好删除函数中的旧数据。这是一个替换字符串的功能,而不是创建一个新字符串。 – 2010-09-11 01:09:53

+2

@Matthew:你写的函数不止一件事 - 它执行子字符串替换,它也释放了它的参数。这似乎没问题,直到你想要做字符串替换,但你不想释放参数,例如:'str_replace(“某个固定字符串”,查找,替换);'。然后,你必须编写另一个函数,来执行当前函数所做的两件事之一,而不是另一件事。如果代码每次只执行一件事,则代码更具可重用性。 – 2010-09-11 14:43:23

+0

感谢您的评论。你是对的,但是对于这个特殊的节目,我觉得它很好,因为它确实需要什么。我可以在将来修改它以更好地控制所做的事情。 – 2010-09-11 21:36:23

1

一个建议:如果你打算调用该函数的语法string = str_replace(string, "no", "nope");,那么我会建议改变的第一个参数一个char**。这样,您可以直接修改指针,而不必假定用户正在使用该特定的调用符号。既然你释放原始的字符串,下面的代码块是危险的:

char* str1; 
char* str2; 
str1 = malloc(SIZE_1); 
/* Write something into the buffer here.. */ 
str2 = str_replace(str1, "from", "to"); 
free(str1); // Whoops! Double free! 

通过改变第一个参数一个char**,用户可以安全地释放他们与malloc无论他们如何调用该函数使用相同的指针。在这种情况下,您可以使函数返回void,或者直接将指针的副本返回到原始字符串(*string)。

+1

不错的一点。我设法按照你的方式实现它,即使原始变量被释放,它也能正常工作。当用户输入参数时,它确实需要使用&符号,但我认为这种方法更安全。如果只有一种方法来测试指针是否是用malloc创建的。如果我可以使一个函数与内存缓冲区和正常变量一起工作(两种不同类型的数据的正确名称是什么?),那将会很好。非常感谢你的贡献。 – 2010-09-11 01:01:51

+0

而且我也喜欢你的想法,因为我不再需要重新分配指针。我想在使用这个函数时,需要的代码很少。 – 2010-09-11 01:11:18

相关问题