一个优雅的解决方案使用反转来实现所需的结果。假设您的目标字符串 str 由两个块 AB 组成,其中 A 是插入点之前的块,B 是插入点之后的块。此外,假设要插入的字符串 ins 由第三个块 C 表示。
可以看出,如果你将C连接到AB,然后反向B,反向C,同时反向B和C,得到ACB,这就是想要的结果。更明确地说,这是将 C 附加到 AB 之后的内容:
美国广播公司
这就是你想要的:
ACB
ACB 可以通过以下方式获得:
- 反转B,得到B_r(B反转);
- 反转C,得到C_r——此时我们有AB_rC_r;
- 反转 B 和 C,即计算 A(B_rC_r)_r,得到 ACB。
下面是实现这个算法的代码:
void reverse(char *, char *, char *);
/* Insert string C between blocks AB in str */
void insertstring(char *str, char *ins, int n) {
/* 1 - Append C to the end of str */
int i = strlen(str);
char *p = str+i, *q = ins;
while ((*p++ = *q++));
p--;
/* 2 - Reverse C and B */
reverse(str, str+i, p-1); /* C */
reverse(str, str+n, str+i-1); /* B */
/* 3 - Reverse B_rC_r */
reverse(str, str+n, p-1);
}
void reverse(char *str, char *begin, char *end) {
char tmp;
while (begin < end) {
tmp = *begin;
*begin = *end;
*end = tmp;
begin++;
end--;
}
}
和一些示例代码来测试它:
#include <stdio.h>
#include <string.h>
int main() {
void insertstring(char *, char *, int);
char test[128] = "A string to test.";
printf("Before: %s\n", test);
insertstring(test, "hello!", 4);
printf("After: %s\n", test);
return 0;
}
这将插入“你好!” 从测试 [4] 开始。这是输出:
$ ./test
Before: A string to test.
After: A sthello!ring to test.
考虑采用这种方法:代码简短而优雅。此技术在 Programming Pearls,第 2 版中进行了描述,是一种执行矢量旋转的好方法。据作者介绍,Brian Kernighan 和 PJ Plauger 在他们的 Pascal 软件工具中正是使用这种方法在文本编辑器中移动行。