这是一个有效的版本。我还包括了一些单元测试:
#include <stdio.h>
#include <string.h>
char str_dest[] = "abcdefg";
char str_source[] = "123";
int dlen;
void
replace(char *dst,char *src,int pos)
{
// find starting place in destination -- we must scan char-by-char in
// case pos is larger than the destination string size
for (; (*dst != 0) && (pos > 0); ++dst, --pos);
// copy in source string until _it_ ends or we run out of room in the
// destination
for (; (*dst != 0) && (*src != 0); ++dst, ++src)
*dst = *src;
}
void
test(int pos)
{
char dst[dlen + 1];
strcpy(dst,str_dest);
replace(dst,str_source,pos);
printf("POS: %d DST: '%s'\n",pos,dst);
}
int
main(void)
{
dlen = strlen(str_dest);
for (int pos = 0; pos <= (dlen + 3); ++pos)
test(pos);
return 0;
}
更新:
我正在为微控制器编写此代码,安全检查会影响性能吗?
是的,安全检查要求逐字节扫描目标字符串以定位结尾。
请注意,无需strlen
对源字符串执行任何操作。请参阅string_replace_fast
下面的功能变体。它并不安全,但速度快 [大约 2 倍]。
另外我认为,如果源字符串长度加上 pos 参数大于 strlen(dest),则使用当前代码我将覆盖不属于 dest 字符串的内存。
对,那是正确的。您可以在下面的测试结果中看到它。
您可能不得不牺牲一点速度。如果这不是一个被大量调用的函数,那么选择更慢/更安全的版本。您只能通过一些基准测试来判断这一点。
这是测试程序的修改版本,它对您的版本和我的版本进行了基准测试,以及一两个变体:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char str_dest[] = "abcdefghijklimnopqrstuvwxyz";
char str_source[] = "123";
char *tmp;
int dlen;
typedef void (*func_p)(char *dst,char *src,int pos);
#define TIMEIT(_fnc,_pos) \
timeit(_fnc,_pos,#_fnc)
char *
fixstr(const char *src)
{
static char fix[1000];
char *dst = fix;
for (; *src != 0; ++src) {
if ((*src >= 0x20) && (*src <= 0x7E))
*dst++ = *src;
else
dst += sprintf(dst,"{?%2.2X?}",*src & 0xFF);
}
*dst = 0;
return fix;
}
double
tvgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_REALTIME,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
return sec;
}
void
string_replace_pos(char *dest, char *source, int pos)
{
int source_length = strlen(source);
for (int i = 0; i < source_length; i++) {
dest[pos + i] = source[i];
}
}
void
string_replace_fast(char *dest, char *source, int pos)
{
int chr;
dest += pos;
for (chr = *source++; chr != 0; chr = *source++, ++dest)
*dest = chr;
}
void
replace(char *dst,char *src,int pos)
{
// find starting place in destination -- we must scan char-by-char in
// case pos is larger than the destination string size
for (; (*dst != 0) && (pos > 0); ++dst, --pos);
// copy in source string until _it_ ends or we run out of room in the
// destination
for (; (*dst != 0) && (*src != 0); ++dst, ++src)
*dst = *src;
}
void
replace2(char *dst,char *src,int pos)
{
int mlen = strlen(dst);
// find starting place in destination -- we must scan char-by-char in
// case pos is larger than the destination string size
if (pos <= mlen)
dst += pos;
// copy in source string until _it_ ends or we run out of room in the
// destination
for (; (*dst != 0) && (*src != 0); ++dst, ++src)
*dst = *src;
}
void
timeit(func_p func,int pos,const char *name)
{
double tvbeg;
strcpy(tmp,str_dest);
tvbeg = tvgetf();
for (int iter = 1; iter <= 1000; ++iter)
func(tmp,str_source,pos);
tvbeg = tvgetf() - tvbeg; \
printf("POS: %d %.9f DST: '%s' (%s)\n",
pos,tvbeg,fixstr(tmp),name);
int clen = strlen(tmp);
if (clen != dlen)
printf("ERROR: length mismatch -- EXPECTED: %d ACTUAL: %d\n",dlen,clen);
}
void
test(int pos)
{
printf("\n");
TIMEIT(string_replace_pos,pos);
TIMEIT(string_replace_fast,pos);
TIMEIT(replace,pos);
TIMEIT(replace2,pos);
}
int
main(void)
{
dlen = strlen(str_dest);
tmp = malloc(dlen + 100);
for (int pos = -3; pos <= (dlen + 3); ++pos)
test(pos);
return 0;
}
这是这个测试程序的输出。
请注意您的版本的错误行。另外,请注意如果插入位置为负数会发生什么。
POS: -3 0.000008106 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: -3 0.000003815 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: -3 0.000007629 DST: '123defghijklimnopqrstuvwxyz' (replace)
POS: -3 0.000011683 DST: 'abcdefghijklimnopqrstuvwxyz' (replace2)
POS: -2 0.000007153 DST: '3bcdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: -2 0.000003815 DST: '3bcdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: -2 0.000007391 DST: '123defghijklimnopqrstuvwxyz' (replace)
POS: -2 0.000012159 DST: '3bcdefghijklimnopqrstuvwxyz' (replace2)
POS: -1 0.000007391 DST: '23cdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: -1 0.000003815 DST: '23cdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: -1 0.000007391 DST: '123defghijklimnopqrstuvwxyz' (replace)
POS: -1 0.000012159 DST: '23cdefghijklimnopqrstuvwxyz' (replace2)
POS: 0 0.000007391 DST: '123defghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 0 0.000004053 DST: '123defghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 0 0.000007391 DST: '123defghijklimnopqrstuvwxyz' (replace)
POS: 0 0.000012159 DST: '123defghijklimnopqrstuvwxyz' (replace2)
POS: 1 0.000007391 DST: 'a123efghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 1 0.000003815 DST: 'a123efghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 1 0.000008583 DST: 'a123efghijklimnopqrstuvwxyz' (replace)
POS: 1 0.000012159 DST: 'a123efghijklimnopqrstuvwxyz' (replace2)
POS: 2 0.000007153 DST: 'ab123fghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 2 0.000003815 DST: 'ab123fghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 2 0.000010014 DST: 'ab123fghijklimnopqrstuvwxyz' (replace)
POS: 2 0.000012159 DST: 'ab123fghijklimnopqrstuvwxyz' (replace2)
POS: 3 0.000007391 DST: 'abc123ghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 3 0.000003815 DST: 'abc123ghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 3 0.000011206 DST: 'abc123ghijklimnopqrstuvwxyz' (replace)
POS: 3 0.000015497 DST: 'abc123ghijklimnopqrstuvwxyz' (replace2)
POS: 4 0.000007629 DST: 'abcd123hijklimnopqrstuvwxyz' (string_replace_pos)
POS: 4 0.000004053 DST: 'abcd123hijklimnopqrstuvwxyz' (string_replace_fast)
POS: 4 0.000013351 DST: 'abcd123hijklimnopqrstuvwxyz' (replace)
POS: 4 0.000012636 DST: 'abcd123hijklimnopqrstuvwxyz' (replace2)
POS: 5 0.000007629 DST: 'abcde123ijklimnopqrstuvwxyz' (string_replace_pos)
POS: 5 0.000004053 DST: 'abcde123ijklimnopqrstuvwxyz' (string_replace_fast)
POS: 5 0.000014544 DST: 'abcde123ijklimnopqrstuvwxyz' (replace)
POS: 5 0.000012636 DST: 'abcde123ijklimnopqrstuvwxyz' (replace2)
POS: 6 0.000007391 DST: 'abcdef123jklimnopqrstuvwxyz' (string_replace_pos)
POS: 6 0.000004053 DST: 'abcdef123jklimnopqrstuvwxyz' (string_replace_fast)
POS: 6 0.000015736 DST: 'abcdef123jklimnopqrstuvwxyz' (replace)
POS: 6 0.000012636 DST: 'abcdef123jklimnopqrstuvwxyz' (replace2)
POS: 7 0.000007629 DST: 'abcdefg123klimnopqrstuvwxyz' (string_replace_pos)
POS: 7 0.000004053 DST: 'abcdefg123klimnopqrstuvwxyz' (string_replace_fast)
POS: 7 0.000018358 DST: 'abcdefg123klimnopqrstuvwxyz' (replace)
POS: 7 0.000012636 DST: 'abcdefg123klimnopqrstuvwxyz' (replace2)
POS: 8 0.000007629 DST: 'abcdefgh123limnopqrstuvwxyz' (string_replace_pos)
POS: 8 0.000004053 DST: 'abcdefgh123limnopqrstuvwxyz' (string_replace_fast)
POS: 8 0.000019550 DST: 'abcdefgh123limnopqrstuvwxyz' (replace)
POS: 8 0.000012636 DST: 'abcdefgh123limnopqrstuvwxyz' (replace2)
POS: 9 0.000007629 DST: 'abcdefghi123imnopqrstuvwxyz' (string_replace_pos)
POS: 9 0.000003815 DST: 'abcdefghi123imnopqrstuvwxyz' (string_replace_fast)
POS: 9 0.000020504 DST: 'abcdefghi123imnopqrstuvwxyz' (replace)
POS: 9 0.000012636 DST: 'abcdefghi123imnopqrstuvwxyz' (replace2)
POS: 10 0.000007629 DST: 'abcdefghij123mnopqrstuvwxyz' (string_replace_pos)
POS: 10 0.000003815 DST: 'abcdefghij123mnopqrstuvwxyz' (string_replace_fast)
POS: 10 0.000032425 DST: 'abcdefghij123mnopqrstuvwxyz' (replace)
POS: 10 0.000012159 DST: 'abcdefghij123mnopqrstuvwxyz' (replace2)
POS: 11 0.000007391 DST: 'abcdefghijk123nopqrstuvwxyz' (string_replace_pos)
POS: 11 0.000003815 DST: 'abcdefghijk123nopqrstuvwxyz' (string_replace_fast)
POS: 11 0.000021696 DST: 'abcdefghijk123nopqrstuvwxyz' (replace)
POS: 11 0.000012159 DST: 'abcdefghijk123nopqrstuvwxyz' (replace2)
POS: 12 0.000007391 DST: 'abcdefghijkl123opqrstuvwxyz' (string_replace_pos)
POS: 12 0.000003815 DST: 'abcdefghijkl123opqrstuvwxyz' (string_replace_fast)
POS: 12 0.000022888 DST: 'abcdefghijkl123opqrstuvwxyz' (replace)
POS: 12 0.000012159 DST: 'abcdefghijkl123opqrstuvwxyz' (replace2)
POS: 13 0.000007391 DST: 'abcdefghijkli123pqrstuvwxyz' (string_replace_pos)
POS: 13 0.000003815 DST: 'abcdefghijkli123pqrstuvwxyz' (string_replace_fast)
POS: 13 0.000023842 DST: 'abcdefghijkli123pqrstuvwxyz' (replace)
POS: 13 0.000012159 DST: 'abcdefghijkli123pqrstuvwxyz' (replace2)
POS: 14 0.000007153 DST: 'abcdefghijklim123qrstuvwxyz' (string_replace_pos)
POS: 14 0.000003815 DST: 'abcdefghijklim123qrstuvwxyz' (string_replace_fast)
POS: 14 0.000024796 DST: 'abcdefghijklim123qrstuvwxyz' (replace)
POS: 14 0.000015736 DST: 'abcdefghijklim123qrstuvwxyz' (replace2)
POS: 15 0.000007391 DST: 'abcdefghijklimn123rstuvwxyz' (string_replace_pos)
POS: 15 0.000003815 DST: 'abcdefghijklimn123rstuvwxyz' (string_replace_fast)
POS: 15 0.000025749 DST: 'abcdefghijklimn123rstuvwxyz' (replace)
POS: 15 0.000015497 DST: 'abcdefghijklimn123rstuvwxyz' (replace2)
POS: 16 0.000007153 DST: 'abcdefghijklimno123stuvwxyz' (string_replace_pos)
POS: 16 0.000003815 DST: 'abcdefghijklimno123stuvwxyz' (string_replace_fast)
POS: 16 0.000026941 DST: 'abcdefghijklimno123stuvwxyz' (replace)
POS: 16 0.000015497 DST: 'abcdefghijklimno123stuvwxyz' (replace2)
POS: 17 0.000007153 DST: 'abcdefghijklimnop123tuvwxyz' (string_replace_pos)
POS: 17 0.000003815 DST: 'abcdefghijklimnop123tuvwxyz' (string_replace_fast)
POS: 17 0.000027895 DST: 'abcdefghijklimnop123tuvwxyz' (replace)
POS: 17 0.000015497 DST: 'abcdefghijklimnop123tuvwxyz' (replace2)
POS: 18 0.000007153 DST: 'abcdefghijklimnopq123uvwxyz' (string_replace_pos)
POS: 18 0.000004053 DST: 'abcdefghijklimnopq123uvwxyz' (string_replace_fast)
POS: 18 0.000028849 DST: 'abcdefghijklimnopq123uvwxyz' (replace)
POS: 18 0.000015497 DST: 'abcdefghijklimnopq123uvwxyz' (replace2)
POS: 19 0.000007153 DST: 'abcdefghijklimnopqr123vwxyz' (string_replace_pos)
POS: 19 0.000003815 DST: 'abcdefghijklimnopqr123vwxyz' (string_replace_fast)
POS: 19 0.000029802 DST: 'abcdefghijklimnopqr123vwxyz' (replace)
POS: 19 0.000015497 DST: 'abcdefghijklimnopqr123vwxyz' (replace2)
POS: 20 0.000007391 DST: 'abcdefghijklimnopqrs123wxyz' (string_replace_pos)
POS: 20 0.000003815 DST: 'abcdefghijklimnopqrs123wxyz' (string_replace_fast)
POS: 20 0.000030994 DST: 'abcdefghijklimnopqrs123wxyz' (replace)
POS: 20 0.000015497 DST: 'abcdefghijklimnopqrs123wxyz' (replace2)
POS: 21 0.000007153 DST: 'abcdefghijklimnopqrst123xyz' (string_replace_pos)
POS: 21 0.000003815 DST: 'abcdefghijklimnopqrst123xyz' (string_replace_fast)
POS: 21 0.000031948 DST: 'abcdefghijklimnopqrst123xyz' (replace)
POS: 21 0.000015497 DST: 'abcdefghijklimnopqrst123xyz' (replace2)
POS: 22 0.000007153 DST: 'abcdefghijklimnopqrstu123yz' (string_replace_pos)
POS: 22 0.000003815 DST: 'abcdefghijklimnopqrstu123yz' (string_replace_fast)
POS: 22 0.000032902 DST: 'abcdefghijklimnopqrstu123yz' (replace)
POS: 22 0.000015497 DST: 'abcdefghijklimnopqrstu123yz' (replace2)
POS: 23 0.000007391 DST: 'abcdefghijklimnopqrstuv123z' (string_replace_pos)
POS: 23 0.000003815 DST: 'abcdefghijklimnopqrstuv123z' (string_replace_fast)
POS: 23 0.000034094 DST: 'abcdefghijklimnopqrstuv123z' (replace)
POS: 23 0.000015497 DST: 'abcdefghijklimnopqrstuv123z' (replace2)
POS: 24 0.000007153 DST: 'abcdefghijklimnopqrstuvw123' (string_replace_pos)
POS: 24 0.000003815 DST: 'abcdefghijklimnopqrstuvw123' (string_replace_fast)
POS: 24 0.000034571 DST: 'abcdefghijklimnopqrstuvw123' (replace)
POS: 24 0.000015497 DST: 'abcdefghijklimnopqrstuvw123' (replace2)
POS: 25 0.000007153 DST: 'abcdefghijklimnopqrstuvwx123' (string_replace_pos)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 28
POS: 25 0.000003815 DST: 'abcdefghijklimnopqrstuvwx123' (string_replace_fast)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 28
POS: 25 0.000034571 DST: 'abcdefghijklimnopqrstuvwx12' (replace)
POS: 25 0.000014305 DST: 'abcdefghijklimnopqrstuvwx12' (replace2)
POS: 26 0.000007153 DST: 'abcdefghijklimnopqrstuvwxy123' (string_replace_pos)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 29
POS: 26 0.000003815 DST: 'abcdefghijklimnopqrstuvwxy123' (string_replace_fast)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 29
POS: 26 0.000034809 DST: 'abcdefghijklimnopqrstuvwxy1' (replace)
POS: 26 0.000012636 DST: 'abcdefghijklimnopqrstuvwxy1' (replace2)
POS: 27 0.000007391 DST: 'abcdefghijklimnopqrstuvwxyz123' (string_replace_pos)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 30
POS: 27 0.000003815 DST: 'abcdefghijklimnopqrstuvwxyz123' (string_replace_fast)
ERROR: length mismatch -- EXPECTED: 27 ACTUAL: 30
POS: 27 0.000148058 DST: 'abcdefghijklimnopqrstuvwxyz' (replace)
POS: 27 0.000008821 DST: 'abcdefghijklimnopqrstuvwxyz' (replace2)
POS: 28 0.000007629 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 28 0.000003815 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 28 0.000039339 DST: 'abcdefghijklimnopqrstuvwxyz' (replace)
POS: 28 0.000012159 DST: '123defghijklimnopqrstuvwxyz' (replace2)
POS: 29 0.000007391 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 29 0.000003815 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 29 0.000035048 DST: 'abcdefghijklimnopqrstuvwxyz' (replace)
POS: 29 0.000011921 DST: '123defghijklimnopqrstuvwxyz' (replace2)
POS: 30 0.000007153 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_pos)
POS: 30 0.000003815 DST: 'abcdefghijklimnopqrstuvwxyz' (string_replace_fast)
POS: 30 0.000035048 DST: 'abcdefghijklimnopqrstuvwxyz' (replace)
POS: 30 0.000012159 DST: '123defghijklimnopqrstuvwxyz' (replace2)