如何不借助临时变量,用<cstring>库实现字符数组指定索引右移?
字符串指定位置右移的问题分析与解决方案
为什么strcpy(str+i, str+j)(i>j)不符合预期?
strcpy的设计不支持重叠内存区域的复制。当目标指针(str+i)位于源指针(str+j)右侧时,strcpy会从左到右依次复制字节:先将str[j]覆盖到str[i],接着复制str[j+1]到str[i+1]——但此时str[j+1]可能已经被之前的复制操作覆盖(因为i>j,j+1可能等于i),后续复制的都是已经被修改过的数据,最终导致字符串出现连续重复的错误内容,就像你代码里的Welccccccco hell!!。
可行的实现方法(无需辅助变量,用库)
使用<cstring>中的memmove函数,它专门针对重叠内存区域做了优化:会先判断源和目标的位置关系,如果目标在源右侧,就从字符串末尾开始向左复制,避免覆盖未复制的源数据。
代码示例(实现你的预期效果:将Welcome改为Welccome)
#include <iostream> #include <cstring> using namespace std; int main() { char str[100] = "Welcome to hell!"; int insert_pos = 4; // 要插入字符的位置(即右移的起始位置) size_t str_len = strlen(str); // 将insert_pos开始的所有字符(包括'\0')右移一位 // 第三个参数是要复制的字节数:原长度 - 起始位置 + 1(包含终止符) memmove(str + insert_pos + 1, str + insert_pos, str_len - insert_pos + 1); // 把前一个位置的字符复制到腾出的位置,实现插入效果 str[insert_pos] = str[insert_pos - 1]; cout << str; // 输出:Welccome to hell! return 0; }
其他替代方案
如果不想用memmove,也可以手动从后往前遍历复制,原理和memmove一致:
#include <iostream> #include <cstring> using namespace std; int main() { char str[100] = "Welcome to hell!"; int insert_pos = 4; size_t str_len = strlen(str); // 从字符串终止符开始,往前逐个将字符右移一位 for (size_t i = str_len + 1; i > insert_pos; --i) { str[i] = str[i - 1]; } str[insert_pos] = str[insert_pos - 1]; cout << str; // 输出:Welccome to hell! return 0; }
内容的提问来源于stack exchange,提问作者oomertaa
相关产品推荐
相关产品推荐

