替换 C 字符字符串中的字符串(strreplace,无 sprintf)
Replace a string within a C char string (strreplace, no sprintf)
您好,很抱歉,如果这个问题已经得到回答(以我想要的方式:-)),但我想我有记忆问题。
假设以下 C 函数(是的,这个很脏而且没有优化):
char *strreplace(char **str, char *dst, char *replace) {
int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace);
char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1));
memset(tmp1, 0, sizeof(char) * (replacestart + 1));
memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1));
strncpy(tmp1, *str, replacestart);
strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart)));
*str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2));
memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2));
strncpy(*str, tmp1, strlen(tmp1));
strncpy(*str + strlen(tmp1), replace, replacelen);
strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2));
return *str;
}
如所见,它应该在 **str
.
中用 *replace
替换 *dst
这基本上按预期工作。问题是:
输出 (*str
) 在 memsetting 后没有用零清除,并且即使在重新分配后仍然有错误的长度。
意思是,如果字符串在替换后更长,最后的字符将被删除 *str
.
反过来,如果字符串较短,则找到 char 字符串末尾的旧字符。
我做错了什么。提到我不想使用 sprintf
也不想使用 C++-STL,只想用 C 中的指针来做这个。
换句话说,用指针替换 c 字符字符串中的字符串的正确方法是什么。
非常感谢。
请求更多信息后编辑
我使用这个函数如下:
...open a textfile via FILE type, determining file lengts (fseek)...
char *filecontent = (char *)malloc(sizeof(char) * filesize);
if(filesize != fread(filecontent, sizeof(char), filesize, fd)) {
free(filecontent);
return -1;
}
streplace(&filecontent, "[#TOBEREPLACED#]", "replaced");
...doing other stuff with filecontent...
编辑 2,添加 stringcompare()
int stringcompare(const char *string, const char *substr) {
int i, j, firstOcc;
i = 0, j = 0;
while(string[i] != '[=12=]') {
while(string[i] != substr[0] && string[i] != '[=12=]') {
i++;
}
if(string[i] == '[=12=]') {
return -1;
}
firstOcc = i;
while(string[i] == substr[j] && string[i] != '[=12=]' && substr[j] != '[=12=]') {
i++;
j++;
}
if(substr[j] == '[=12=]') {
return firstOcc;
}
if(string[i] == '[=12=]') {
return -1;
}
i = firstOcc + 1;
j = 0;
}
}
您的函数看起来过于复杂。这是一个简单的工作版本:
char *strreplace(char **str, char *dst, char *replace) char *strreplace(char **str, char *dst, char *replace)
{
char *start, *tmp;
int n;
if ((start=strstr(*str,dst))==0) return(0);
n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
tmp=malloc(n);
strncpy(tmp,*str,start-*str);
strcpy(tmp+(start-*str),replace);
strcat(tmp,start+strlen(dst));
free(*str);
*str= tmp;
return(tmp);
}
带测试功能:
void reptest(void)
{
char *src;
char rep[]= "brave new world";
src=malloc(strlen("Hello world of wonders")+1);
strcpy(src,"Hello world of wonders");
strreplace(&src,"world",rep);
printf("%s\n", src);
free(src);
}
编辑:我以前的版本忘了复制其余部分。固定。
函数的逻辑并不像乍看起来那么简单
您应该决定在 1) 源字符串为空和 2) 目标字符串为空时执行什么操作。
例如,如果目标字符串为空,则标准函数 strstr
将 return 源字符串的第一个字符的地址。但是从逻辑上讲,如果 dst
是一个空字符串,那么不应更改源字符串,除非它又是一个空字符串。在这种情况下,该函数应该只创建一个等于字符串 replace
.
的新字符串
请注意,由于字符串 dst
和 replace
在函数内未更改,因此应使用限定符 const
.
声明它们
char * strreplace( char **str, const char *dst, const char *replace );
此外,该函数还应通过 return空指针报告函数内的新内存分配是否成功,以防分配失败。
考虑到所有这些因素,该函数可以像演示程序中所示的那样。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strreplace( char **str, const char *dst, const char *replace )
{
char *result = *str;
if ( *str[0] == '[=11=]' )
{
if ( dst[0] == '[=11=]' && replace[0] != '[=11=]' )
{
char *result = malloc( strlen( replace ) + 1 );
if ( result )
{
strcpy( result, replace );
free( *str );
*str = result;
}
}
}
else if ( dst[0] != '[=11=]' )
{
char *pos = strstr( *str, dst );
if ( pos != NULL )
{
size_t dst_n = strlen( dst );
size_t replace_n = strlen( replace );
result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );
if ( result )
{
size_t n = pos - *str;
strncpy( result, *str, n );
strcpy( result + n, replace );
strcpy( result + n + replace_n, *str + n + dst_n );
}
free( *str );
*str = result;
}
}
return result;
}
int main(void)
{
const char *hello = "Hello everybody here";
char *str = malloc( sizeof( char ) );
str[0] = '[=11=]';
if ( strreplace( &str, "", hello ) )
{
puts( str );
}
if ( strreplace( &str, "everybody", "Eurobertics" ) )
{
puts( str );
}
if ( strreplace( &str, "Hello", "Bye" ) )
{
puts( str );
}
if ( strreplace( &str, " here", "" ) )
{
puts( str );
}
if ( strreplace( &str, "Bye ", "" ) )
{
puts( str );
}
free( str );
return 0;
}
程序输出为
Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics
您好,很抱歉,如果这个问题已经得到回答(以我想要的方式:-)),但我想我有记忆问题。
假设以下 C 函数(是的,这个很脏而且没有优化):
char *strreplace(char **str, char *dst, char *replace) {
int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace);
char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1));
memset(tmp1, 0, sizeof(char) * (replacestart + 1));
memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1));
strncpy(tmp1, *str, replacestart);
strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart)));
*str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2));
memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2));
strncpy(*str, tmp1, strlen(tmp1));
strncpy(*str + strlen(tmp1), replace, replacelen);
strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2));
return *str;
}
如所见,它应该在 **str
.
中用 *replace
替换 *dst
这基本上按预期工作。问题是:
输出 (*str
) 在 memsetting 后没有用零清除,并且即使在重新分配后仍然有错误的长度。
意思是,如果字符串在替换后更长,最后的字符将被删除 *str
.
反过来,如果字符串较短,则找到 char 字符串末尾的旧字符。
我做错了什么。提到我不想使用 sprintf
也不想使用 C++-STL,只想用 C 中的指针来做这个。
换句话说,用指针替换 c 字符字符串中的字符串的正确方法是什么。
非常感谢。
请求更多信息后编辑
我使用这个函数如下:
...open a textfile via FILE type, determining file lengts (fseek)...
char *filecontent = (char *)malloc(sizeof(char) * filesize);
if(filesize != fread(filecontent, sizeof(char), filesize, fd)) {
free(filecontent);
return -1;
}
streplace(&filecontent, "[#TOBEREPLACED#]", "replaced");
...doing other stuff with filecontent...
编辑 2,添加 stringcompare()
int stringcompare(const char *string, const char *substr) {
int i, j, firstOcc;
i = 0, j = 0;
while(string[i] != '[=12=]') {
while(string[i] != substr[0] && string[i] != '[=12=]') {
i++;
}
if(string[i] == '[=12=]') {
return -1;
}
firstOcc = i;
while(string[i] == substr[j] && string[i] != '[=12=]' && substr[j] != '[=12=]') {
i++;
j++;
}
if(substr[j] == '[=12=]') {
return firstOcc;
}
if(string[i] == '[=12=]') {
return -1;
}
i = firstOcc + 1;
j = 0;
}
}
您的函数看起来过于复杂。这是一个简单的工作版本:
char *strreplace(char **str, char *dst, char *replace) char *strreplace(char **str, char *dst, char *replace)
{
char *start, *tmp;
int n;
if ((start=strstr(*str,dst))==0) return(0);
n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
tmp=malloc(n);
strncpy(tmp,*str,start-*str);
strcpy(tmp+(start-*str),replace);
strcat(tmp,start+strlen(dst));
free(*str);
*str= tmp;
return(tmp);
}
带测试功能:
void reptest(void)
{
char *src;
char rep[]= "brave new world";
src=malloc(strlen("Hello world of wonders")+1);
strcpy(src,"Hello world of wonders");
strreplace(&src,"world",rep);
printf("%s\n", src);
free(src);
}
编辑:我以前的版本忘了复制其余部分。固定。
函数的逻辑并不像乍看起来那么简单
您应该决定在 1) 源字符串为空和 2) 目标字符串为空时执行什么操作。
例如,如果目标字符串为空,则标准函数 strstr
将 return 源字符串的第一个字符的地址。但是从逻辑上讲,如果 dst
是一个空字符串,那么不应更改源字符串,除非它又是一个空字符串。在这种情况下,该函数应该只创建一个等于字符串 replace
.
请注意,由于字符串 dst
和 replace
在函数内未更改,因此应使用限定符 const
.
char * strreplace( char **str, const char *dst, const char *replace );
此外,该函数还应通过 return空指针报告函数内的新内存分配是否成功,以防分配失败。
考虑到所有这些因素,该函数可以像演示程序中所示的那样。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strreplace( char **str, const char *dst, const char *replace )
{
char *result = *str;
if ( *str[0] == '[=11=]' )
{
if ( dst[0] == '[=11=]' && replace[0] != '[=11=]' )
{
char *result = malloc( strlen( replace ) + 1 );
if ( result )
{
strcpy( result, replace );
free( *str );
*str = result;
}
}
}
else if ( dst[0] != '[=11=]' )
{
char *pos = strstr( *str, dst );
if ( pos != NULL )
{
size_t dst_n = strlen( dst );
size_t replace_n = strlen( replace );
result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );
if ( result )
{
size_t n = pos - *str;
strncpy( result, *str, n );
strcpy( result + n, replace );
strcpy( result + n + replace_n, *str + n + dst_n );
}
free( *str );
*str = result;
}
}
return result;
}
int main(void)
{
const char *hello = "Hello everybody here";
char *str = malloc( sizeof( char ) );
str[0] = '[=11=]';
if ( strreplace( &str, "", hello ) )
{
puts( str );
}
if ( strreplace( &str, "everybody", "Eurobertics" ) )
{
puts( str );
}
if ( strreplace( &str, "Hello", "Bye" ) )
{
puts( str );
}
if ( strreplace( &str, " here", "" ) )
{
puts( str );
}
if ( strreplace( &str, "Bye ", "" ) )
{
puts( str );
}
free( str );
return 0;
}
程序输出为
Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics