要求实现一个函数,功能是将一个字符串左旋转k个字符,也就是说把字符串左边的K个字符移动到字符串的右面,比如:
abcd左旋一个字符得到bcda
abcd左旋两个字符得到cdab
我们用3种方法实现:
- 思路:直接用例子说话,对于字符"abcde",
(1)先把字符串的第一个字符'a'存到一个临时字符变量中
(2)再把之后的4个字符向前移动一个字符(注意字符串末尾隐藏的的'\0'不动),
(3)那现在'e'的位置就空出来了,再把'a'放到e的位置。
(4)左旋k个字符,就循环上述步骤k次
void Left_Move(char* s, int k)
{
assert(s!=NULL);
int len = strlen(s);
for (int i = 0; i < k; i++)//这样的动作重复k次
{
char tmp = *s;//(1)
for (int j = 0; j < len - 1; j++)
{
*(s + j) = *(s + j + 1);
}//(2)
*(s + len - 1) = tmp;//(3)
}
}
int main()
{
char a[] = "abcde";
int k=2;//左旋k个字符
Left_Move(a, k);
printf("%s\n", a);
return 0;
}
2. 三步翻转法
(1)对于”abcde"想要左旋2个字符,先操作左边的两个字符"ab",翻转成"ba"
(2)在操作右边剩下的字符"cde",翻转成"edc"
(3)现在的字符串变成了"baedc"
(4)再让现在的字符串整体翻转,变成了"cdeab",即为所求!
- 其中需要自己写一个reverse函数来实现翻转。
3.第三种方法我感觉还是比较巧妙的void reverse(char* a, char* b)//实现翻转函数 { char* left = a;//记录左指针 char* right = b;//记录右指针 while (left < right) { char tmp = *left; *left = *right; *right = tmp; left++; right--; } } void Left_Move(char* s, int k) { int len = strlen(s); //传进reverse的是两个指针 reverse(s, s + k - 1); //第一步翻转 "ab"->"ba" reverse(s + k, s + len - 1);//第一步翻转 "cde"->"edc" reverse(s, s + len - 1); //第一步翻转 "baedc"->"cdeab" } int main() { char a[] = "abcde"; int k = 2;//左旋k个字符 Left_Move(a, k); printf("%s\n", a); return 0; }
(1)用strncat函数,在s字符串后面追加一个s字符串,变成了"abcdeabcde",这首后我们会发现
这个串就包含了左旋的所有情况!见下图
(2)如果我们的目的是实现左旋k=2个字符,那么只需从k=2的位置截取这个大串的一部分赋给另外一个字符数组 s2
(3)值得注意的是,为了能够正常在s字符串后面追加一个s字符串,需要。提前给字符数组S分配足够的空间。
void Left_Move(char* s,char* s2, int k)
{
int len = strlen(s);//提前计算好我们之后要截取的那一段字符串的长度
strncat(s, s, len);//追加完成
for (int i = 0; i < len; i++)
{
s2[i] = *(s + k + i);
}
}
int main()
{
char s[30] = "abcde";
int k = 2;//左旋k个字符
char s2[30] = { '\0' };
Left_Move(s, s2,k);
printf("%s\n", s2);
return 0;
}
后记:编写第三个方法时,我一开始是这样写的(是错误写法)
char * Left_Move(char* s, int k)
{
int len = strlen(s);//提前计算好我们之后要截取的那一段字符串的长度
strncat(s, s, len);//追加完成
char s2[30]={'\0'};
for (int i = 0; i < len; i++)
{
s2[i] = *(s+k+i);
}
return s2;
}
int main()
{
char a[30] = "abcde";
int k = 2;//左旋k个字符
char* ret = Left_Move(a, k);
printf("%s\n", ret);
return 0;
}
一直输出“烫烫。。。找了几分钟,最后锁定问题是因为s2在出函数的时候指向的栈里面的内存已经被释放掉了,一些知识的掌握还是不到家
局部变量的作用域是在函数的内部函数返回之后,我们局部变量的内存已经被释放掉了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。所以函数是可以返回局部变量的。但是如果函数返回的是局部变量的。地址。程序运行就会报错。由于只是把地址复制后返回了,而指针指向的内存。已经被释放掉了,这样指针没有访问该内存的权限,所以就会报错。准确的来说,函数不能返回指向栈内存的指针。但是可以返回指向对应内存的指针。因为堆内存里面的内容是在整个程序结束之后才释放的。
Static存在data区里面。也是整个程序结束之后才释放的。
遇到一个问题就解决一个问题,记在脑子里,而不是记在什么形式主义的笔记上面,这样才能提高