目录
先看代码,下面有解析奥!!有两个改进思路也在下面!!
void leftro(char* arr,int a)
{
while (a)
{
char* brr = arr;
char tmp = *brr;
while (*(brr + 1) != '\0')
{
*brr = *(brr + 1);
brr ++;
}
*brr = tmp;
a--;
}
}
int main()
{
char arr[] = "ABCD";
int a = 0;
scanf("%d", &a);
leftro(arr, sz,a);
printf("%s", arr);
return 0;
}
解题思路
一个字符串ABCD,左旋一次后变成BCDA,两次则为CDAB,即将最前面的字符移到最后面即可。
代码解析
1.主函数
在主函数中,先定义字符串,并且输入一个数字a作为旋转的次数,最终将左旋字符串函数打印出即可
int main()
{
char arr[] = "ABCD";
int sz = sizeof(arr) / sizeof(arr[0]);
int a = 0;
scanf("%d", &a);
leftro(arr, sz,a);
printf("%s", arr);
return 0;
}
2.左旋函数
在左旋函数中,首先先定义一个字符指针来接收arr字符数组,即接收字符串ABCD。
1. 用while循环进行循环左旋,以a作为表达式,就是在左旋每进行完一次,就让a--直到a = 0,为了避免arr被更改首先定义一个brr接收arr指针,然后用一个变量tmp接收 *brr(解引用brr),得到ABCD中第一个字符A
2. 内循环中表达式的意思是,让字符串从A进行字符串交换,直到A移到D的位置,并且 (*(brr+1))(意思是下一个字符)是\0 时停止。每次循环brr++,即让brr在数组中的地址+1,。最后再将tmp的值传到目前brr的地址中即可。因为当A走到D区域时就会停止,因为D区域下一个字符就是\0 ,所以将brr现在位置的值改为tmp,实则是为了将D改为A
void leftro(char* arr,int a)
{
while (a)
{
char* brr = arr;
char tmp = *brr;
while (*(brr + 1) != '\0')
{
*brr = *(brr + 1);
brr ++;
}
*brr = tmp;
a--;
}
}
改进思路
改进一:
这个思路当然可以,但是一次一次转毕竟太麻烦,就不能一次到位么?
当然可以,我们可以选择拼接法,一次到位:
void leftRound(char * src, int time)
{
int len = strlen(src);
int pos = time % len; //断开位置的下标
char tmp[256] = { 0 }; //更准确的话可以选择malloc len + 1个字节的空间来做这个tmp
strcpy(tmp, src + pos); //先将后面的全部拷过来
strncat(tmp, src, pos); //然后将前面几个接上
strcpy(src, tmp); //最后拷回去
}
改进思路主要就是要知道下面几个库函数的用法即可。
改进二:
这个方法要用到一个数组形成的辅助空间,让人觉得有点不爽,还可以有更好的选择,例如ABCDEFG,左旋3次后变成DEFGABC,有一个特殊的操作方式:
先将要左旋的前三个家伙逆序(CBADEFG),然后将后半段也逆序(CBAGFED),最后整体逆序(DEFGABC)即可。这样只需要做数值交换即可,可以写一个函数帮我们完成局部逆序,代码如下:
void reverse_part(char *str, int start, int end) //将字符串从start到end这一段逆序
{
int i, j;
char tmp;
for (i = start, j = end; i < j; i++, j--)
{
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
void leftRound(char * src, int time)
{
int len = strlen(src);
int pos = time % len;
reverse_part(src, 0, pos - 1); //逆序前段
reverse_part(src, pos, len - 1); //逆序后段
reverse_part(src, 0, len - 1); //整体逆序
}