字符串左旋就是将字符串卡面的字符换到后面去,比如说左旋两位就是“abedef”变为“cdefab”。
这里我讲解两种方式来左旋字符串。
一:左旋字符串
头文件:
#include<string.h>
#include<stdio.h>
#include<Windows.h>
#include<assert.h>
1.暴力求解法:
传入的字符串不能是常量字符串要记住,因为常量字符串是不能更改的,所以传入数组的首元素地址,以及我们需要左旋的位数,以旋转的位数作为大循环,每次循环进来得到首地址的内容,然后依次向前移动,直到找到字符串的结束符。该方法在需要变化的个数不是太多时能够使用,但是效率不会太高,因为它是一步一步的改变的。
//暴力求解法
void left_move(char* arr, int n)
{
assert(arr);
int i = 0;
//循环一次,左旋一个字符
for (i = 0; i < n; i++)
{
char temp = *arr;
int j = 0;
while (*(arr + j) != '\0')
{
//将除了第一个字符都往前移动
*(arr + j) = *(arr + j + 1);
j++;
}
//为数组最后一个地址赋值我们之前的第一个字符
*(arr + j - 1) = temp;
}
}
2. 三部翻转法:
一个字符串,“abcdef”,第一步翻转“ba cdef”,第二部翻转“ba fedc”,第三步翻转“cdefab”,可以看到第一次翻转我们需要左旋的几个字符,第二次翻转不需要左旋的字符,第三次翻转整个字符串,就能拿到我们的左旋字符串了。那么这里就需要有逆序一个字符串的函数了,传入的参数应该为字符串的起始位置地址和想要翻转的字符的结束地址。利用循环,直到左边等于右边结束。
//三步翻转法
void reverse(char* left, char* right)
{
assert(left);
assert(right);
//当左地址等于右地址时停止交换
while (left < right)
{
char temp = *left;
*left = *right;
*right = temp;
right--;
left++;
}
}
void left_move_2(char* arr, int n)
{
assert(arr);
int len = strlen(arr);
reverse(arr, arr + n - 1);//逆序左边
reverse(arr + n, arr + len - 1);//逆序右边
reverse(arr, arr + len - 1);//逆序全部
}
主函数:
int main()
{
char arr[] = "abcdef";
//左旋两个字符
int n = 0;
int len = strlen(arr);
scanf("%d", &n);
if (n < len)
{
left_move_2(arr, n);
}
else
printf("指针越界,字符串不做变化\n");
printf("%s\n", arr);
return 0;
}
结果:
二:判断一个字符串是否由另一个字符串左旋而来
1.笨办法:
左旋第一个字符串,得到所有的可能与另一个字符串比较,需要利用到我们之前写的左旋函数,不过由于方法比较挫,我这里就不做讲解了。
2.机智的办法:
在字符串后面追加一个相同的字符串,可以得到字符串左旋的所有可能,例如“abcdef”,追加后得到“abcdefabcdef”,我们可以在该字符串里面找到所有可能。在允许是用库函数string.h的情况下,我们需要用到strncat,strlen,strstr这几个函数。
strncat:作用是在字符串后面追加一个可以控制长度的字符串,及传参时需要定义我们后面需要追加几个字符,之所以不用strcat是因为该函数在追加自己时找不到字符串结束符‘\0’。
strlen:求字符串长度的函数,不包括'\0'。
strstr:寻找前一个字符串的子串中是否有与后一个字符串相等的存在。
int is_left_move_2(char* s1, char* s2)
{
//判断是否为空指针
assert(s1);
assert(s2);
//当两个字符串长度不相等时,直接退出
int len = strlen(s1);
int len2 = strlen(s2);
if (len != len2)
return 0;
//传入两个字符串还有,追加长度
strncat(s1, s1,len);
//strstr(str1,str2),在str1中寻找子串,是否有与str2相同的,要是没有则返回空指针
char* ret = strstr(s1, s2);
if (ret == NULL)
return 0;
else
return 1;
}
当我们不允许使用库函数string.h时,我们就需要自己追加字符串,比较字符串,求字符串长度的函数我比较懒,还是用的strlen函数。在代码中我配合的注释讲解,应该能理解,我就不做讲解了。
int my_strcmp(char* p, char* s2)
{
//判断是否为空指针
assert(p);
assert(s2);
//比较两个字符串
//通过s2的结束来判断结束
while (*s2 != '\0')
{
if (*p == *s2)
{
p++;
s2++;
}
else
return 0;
}
//全相同时返回1
return 1;
}
int is_left_move(char* s1, char* s2)
{
//判断是否为空指针
assert(s1);
assert(s2);
//当两个字符串长度不等时,直接退出
int len = strlen(s1);
int len2 = strlen(s2);
if (len != len2)
return 0;
int i = 0;
int ret;
for (i = 0; i < len; i++)
{
//将字符串s1复制一边,加在s1后面
*(s1 + len + i) = *(s1 + i);
}
//为字符串结尾添加一个结束符
*(s1 + len + i) = '\0';
for (i = 0; i < len; i++)
{
//每次向后偏移1位传参,用于比较
char* p = s1 + i;
ret = my_strcmp(p, s2);
if (ret == 1)
return 1;
}
return 0;
}
主函数:
int main()
{
char arr1[30] = "abcdef";
char arr2[30] = "cdefab";
int ret = is_left_move_2(arr1, arr2);
//对返回值操作
if (ret == 0)
printf("No\n");
else
printf("Yes\n");
system("pause");
return 0;
}
结果:
以上就是全部内容,希望能够帮到你。