你可能不太熟悉的函数:
strcpy(dest,src); //字符串拷贝函数
strcat(dest,src); //字符串合并函数
strncpy(dest,src,num); //拷贝n个字符
strstr(char* mother,char* child); //查找子字符串,
malloc //堆上动态开辟内存
//dest是目标字符串,src操作字符串
字符串左旋
实现一个函数,可以左旋字符串中的k个字符。 ABCD左旋一个字符得到BCDA ;ABCD左旋两个字符得到CDAB 。
思路一>逐次移位
我们知道数组左旋转一次,除过第一个元素外,其余元素都向前移一位。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
void left_mov(char s[], int k)
{
int len = strlen(s);
char copy1 = *s;
k = k%len;
while (k)
{
copy1 = *s;
for (int i = 0; i < len; i++)
s[i] = s[i + 1];
s[len - 1] = copy1;
s[len] = '\0';
k--;
}
}
int main()
{
char s[100];
int left;
printf("请输入想要进行左旋的字符串>\n");
scanf("%s", s);
printf("请输入想要旋转的次数>\n");
scanf("%d", &left);
left_mov(s, left);
printf("结果>%s\n", s);
system("pause");
return 0;
}
思路一的方法太过繁琐,复杂度不符合要求?
思路二>三次逆置
逆置前k项元素,再逆置第k项之后的元素,最后整体逆置。比如ABCD
,左旋2位,先逆置前k项BACD
,再逆置第k项之后的元素BADC
,整个数组所以元素逆置CDAB
。实质上,旋转不就是将前k项和第k项之后的元素顺序颠倒嘛!
vvoid Reverse(char*start, char*end)
{
while (start < end)
{
*start ^= *end;
*end ^= *start;
*start ^= *end;
start++;
end--;
}
}
void left_mov(char str[], int left)
{
int sz = strlen(str);
left = left%sz;
Reverse(str, str + left - 1);
Reverse(str + left, str + sz - 1);
Reverse(str, str + sz - 1);
}
思路三–双数组截取新数组
实际上,我们考虑到旋转过程中,原数组的长度是有限的,那么为了解决这个问题可以考虑,弄一个更大的数组。这个新数组是原数组的两倍,将原数组按序拷贝到新数组,截取前k项,截取新数组使其与原数组长度相等即可。
void left_mov(char s[], int k)
{
char* p = (char*)malloc(2*sizeof(s));
strcpy(p, s);
strcat(p, s);
strncpy(s, p+k, strlen(s));
}
判断是否为旋转字符串
2.判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 = AABCD和s2 = BCDAA,返回1,给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
第三种方法的拓展,查找子字符串的应用
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
int find_dest(char* src, char* dest)
{
int len = strlen(src);
char*tmp = (char*)malloc(2*len+1);
if (len == strlen(dest))
{
strcpy(tmp, src);
strcat(tmp, src);
if (strstr(tmp, dest) != NULL)
{
return 1;
}
}
free(tmp);
return 0;
}
int main()
{
int ret = 0;
char S1[] = { "ABCD" };
char S2 []= { "BCDA" };
ret = find_dest(S1, S2);
if (ret == 1)
printf("S2是由S1左旋得到的\n");
else
printf("S2不是由S1左旋得到的\n");
system("pause");
return 0;
}
S2是由S1左旋得到的
请按任意键继续. . .
字符串排序
写冒泡排序可以排序多个字符串。
#include<stdio.h>
#include<Windows.h>
#include<string.h>
int my_strcmp(const void*x, const void*y)
{
return *(int*)x > *(int*)y;
}
void Bubble_sort_str(char*str[], int sz)
{
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - i - 1; j++)
{
if (my_strcmp(*(str + j), *(str + j + 1))>0)
{
char*tmp = *(str + j);
*(str + j) = *(str + j + 1);
*(str + j + 1) = tmp;
}
}
}
}
int main()
{
int i = 0;
char *str[] = { "HSDF", "abcde", "abc"};
int sz = sizeof(str) / sizeof(*str);
Bubble_sort_str(str, sz);
for (i = 0; i < sz; i++)
{
printf("%s\n", *(str + i));
}
system("pause");
return 0;
}
abc
HSDF
abcde
请按任意键继续. . .
字符串逆置
有一个字符数组的内容为:“student a am i”,请你将数组的内容改为"i am a student".
要求:
不能使用库函数。只能开辟有限个空间(空间个数和字符串的长度无关)。
#include<stdio.h>
#include<Windows.h>
#include<assert.h>
void reverse(char *start,char *end)
{
assert(start&&end);
while (start < end)
{
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
}
void str_reverse(char*str)
{
reverse(str, str+strlen(str) - 1);
while (*str != '\0')
{
char*string = str;
while (*str!='\0'&&*str != ' ')
str++;
reverse(string, str - 1);
if (*str != '\0')
str++;
}
}
int main()
{
char str[] = "student a am i";
str_reverse(str);
printf("%s\n", str);
system("pause");
return 0;
}