1.实现一个函数,可以左旋字符串中的k个字符。
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB

看到问题后的第一反应是左旋一个字符,那就是说把A放到字符串末尾,BCD依次向前移动一个位置,即得到BCDA。即先定义一个临时变量把A保存起来,BCD再依次移动,最后把A再写入。

void revolve_string(char *str, int k)
{
	if (k > 0 && k < strlen(str)){
		while (k){
			char *p = str;
			char tmp = *p;
			while (*(p + 1)){   //依次前移
				*p = *(p + 1);
				p++;
			}
			*p = tmp;
			k--;
		}
	}
}

但转念一想,如果我们把A和BCD整体逆置的话,这里把BCD当作一个整体,也可以得到结果。
如果是左旋俩位,我们把AB和CD分别看作整体,然后逆置,得到CDAB,再分别把C和D,A和B逆置,即可得到DCBA.
这里我们需要一个实现逆置的函数,之前的博客中写到过:

void adverse(char *left, char *right)
{
	assert(*left);
	assert(*right);
	char tmp = 0;
	while (left < right){
		tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

实现了逆置功能之后,我们要写一个旋转字符串的函数。我们先定义一个指针,找到他要旋转的第k个字符,然后标记,先进行内部逆置,再整体逆置。

void left_revolve(char *arr, int k,int len)
{
	char *p = arr;
	while (k>0){   //找到k之后的字符
		p=arr+1;
		k--;
	}
	adverse(arr, p);//A和B 逆置:BACD
	adverse(p + 1, arr + len - 1);//C和D逆置:BADC
	adverse(arr, arr + len - 1);//整体逆置:CDAB

}

完整程序为:

#include<stdio.h>
#include<windows.h>
#include<assert.h>
#pragma warning(disable:4996)

void adverse(char *left, char *right)
{
	assert(*left);
	assert(*right);
	char tmp = 0;
	while (left < right){
		tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void left_revolve(char *arr, int k,int len)
{
	char *p = arr;
	while (k>0){
		p=arr+1;
		k--;
	}
	/*int i = 0;
	while (i < k){
		p = arr + i;
		i++;
	}*/
	adverse(arr, p);//bacd
	adverse(p + 1, arr + len - 1);//badc
	adverse(arr, arr + len - 1);//cdab

}
int main()
{
	char a[] = "ABCD";
	int len = sizeof(a) / sizeof(a[0])-1;
	int k = 0;
	printf("左移几个字符?");
	scanf("%d", &k);
	left_revolve(a, k ,len);
	printf("%s\n", a);
	system("pause");
	return 0;
}


2…判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.

AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC

我们可以用刚刚的旋转字符串的方法,例如求CDAB是不是ABCD旋转之后的字符串,将字符串ABCD左旋俩个字符,再和CDAB比较。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

void reverse(char *left,char *right)
{
	assert(*left);
	assert(*right);
	while (left < right){
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void revolve_string(char *str, int k)
{
	//防御性检查
	assert(str != NULL&&k < strlen(str));
	int len = strlen(str);
	reverse(str, str + k - 1);
	reverse(str + k, str + len - 1);
	reverse(str, str + len - 1);
}

int judge_string(char *str1, char *str2,int len)
{
	int len1 = sizeof(str1);
	int len2 = sizeof(str2);
	if (len1 != len2){
		return 0;
	}
	while (len1){
		revolve_string(str1, 1,len);
		if (strcmp(str1, str2) == 0){
			return 1;
		}
		len1--;
	}
	return 0;
}


int main()
{
	char a[] = "ABCD";
	char b[] = "CDAB";
	int len = sizeof(a) / sizeof(a[0]) - 1;
	revolve_string(a, 2,len);
	int ret = judge_string(a, b,len);
	printf("%d\n", ret);
	system("pause");
	return 0;
}

但是如果是用户要判断,你不知道他要判断的字符串,也不知道参照串,那以上的方法是肯定不可行的。
方法一:
那我们就让源串一直旋转,判断是否与目标串相等,直至完整旋转过strlen(str)。
代码:

void reverse(char *left, char *right)
{
	while (left < right){
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void revolve_string(char *str, int k)
{
	//防御性检查
	assert(str != NULL&&k < strlen(str));//debug
	/*if (str == NULL || k>strlrn(str)){
		return;
	}*/
	int len = strlen(str);
	reverse(str, str + k - 1);
	reverse(str + k, str + len - 1);
	reverse(str, str + len - 1);
}

int is_revolve_string(char *str1, const char *str2)
{
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	assert(str1 != NULL&&str2 != NULL && (len1 == len2));
	int i = 0;
	for (i = 0; i < len1; i++){
		revolve_string(str1, 1);
		if (strcmp(str1, str2) == 0){
			return 1;
		}
	}
	return 0;
}

所以在这里我们就需要利用字符串操作了,首先我们用strncat把str拼接起来,再用strsrt求字串,就可以判断了。
例:初始串:ABBCD
strncat拼接之后:ABBCDABBCD
如果用户要判断的的串是初始串旋转之后的,那它一定是拼接之后的字串。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable:4996)
#define N 20

void Merge_string(char *str)
{
	str = strncat(str, str, strlen(str));
}

int Judge_string(char *str1, char *str2)
{
	Merge_string(str1);
	if (strstr(str1, str2) != NULL)
		return 1;
	else
		return 0;
}
int main()
{
	char arr1[N];
	char arr2[N];
	printf("请输入初始字符串:");
	scanf("%s", &arr1);
	printf("请输入要查找的左旋之后的字符串:");
	scanf("%s", &arr2);
	int res = Judge_string(arr1, arr2);
	if (res == 1){
		printf("是!\n");
	}
	else{
		printf("不是!\n");
	}
	printf("%d", res);
	system("pause");
	return 0;
}

运行结果:

更多推荐

字符串的旋转问题