前几天帮一个同学改代码,苦苦寻思了半天终于发现问题所在:内存重叠,因此写下这篇文章以作警示。
程序作用:输入字符串,输入右移位数n,然后输出字符串循环右移n位的结果。
例如,输入abcdefg,在输入2,则结果应为fgabcde。
以下是源代码
void main()
{
char str[200],ch[200];
int len,n,i;
char *p,*q;
printf("输入字符串:");
gets(str);
printf("右移的位数为:");
scanf("%d",&n);
p=str;
q=p+strlen(p)-1;
len=strlen(p);
for(i=n;i>0;i--)//取出倒数n个字符
{
ch[i-1]=*q;
q--;
}
strncpy(p+n,p,len-n);//正是此处出了问题
p[a]='\0';
for(i=0;i<n;i++)
p[i]=ch[i];
printf("调整后的字符串为:%s\n",p);
}
同学的思路是,先把后面n位字符保存到数组ch中,然后再把p向后复制(len-n)位到p+n中,再把数组ch中的字符复制回p的前n位。
但是,此处出了一个内存重叠的问题,书上的代码是把后面的字符往前移没有出现错误,但是把字符从前面往后移的时候就会出现问题。(从后往前是否真的不会出现问题?我也不太确定。。)
以下是解决方案:
#include<stdio.h>
#include<string.h>
void main()
{
char str[200],ch[200];
int len,n;
printf("输入字符串:");
gets(str);
printf("右移的位数为:");
scanf("%d",&n);
len=strlen(str);//把a改成len,长度
strcpy(ch, str+len-n);
strcpy(ch+n, str);
*(ch+len) = '\0';
strcpy(str, ch);
printf("调整后的字符串为:%s\n",str);
}
封装之后:
void LoopMove(char *str, int n) { int len = strlen(str); char tmp[NUM]; strncpy (tmp, str+len-n, n); strncpy (tmp+n, str, len-n); *(tmp+len) = '\0'; strncpy (str, tmp, len); }