您的位置:首页 > 编程语言 > C语言/C++

【C语言】实现一个函数,可以左旋字符串中的K个字符

2018-02-26 19:18 585 查看

题目说明:

要求实现一个函数,可以左旋字符串中的K个字符;

其中:

ABCD左旋一个字符得到BCDA

ABCD左旋两个字符得到CDAB

解法一:

解题思路:

拿到一组字符串之后,我们首先设置一个临时变量,存放字符串中的第一个字符。

然后把字符串中的其余字符通过循环依次前移一位,最后再把临时变量的值赋给字符串的最后的一位。

以上是字符串的一次左旋,要左旋几次就可以通过循环重复以上过程几次就可以了。

图解如下所示:



程序源码:

#include<iostream>
#include<assert.h>
#include<stdio.h>
#include<Windows.h>

using namespace std;

void string_reverse(char* arr, int len){
assert(arr);
assert(len > 0);
char temp;
temp = arr[0];
for (int i = 0; i < len - 1; ++i){
arr[i] = arr[i + 1];
}
arr[len - 1] = temp;
}

void Print(char* arr, int len){
for (int i = 0; i < len; ++i){
cout << arr[i] << "   ";
}
cout << endl;
}

void test(){
char arr[] = { 'A', 'B', 'C', 'D', '1', '2', '3', '4' };
//这里用数组来表示字符串,如果用字符串来表示字符串会产生一个错误
//char *arr = "ABCD1234";
int count = 0;
int len = 0;
len = sizeof(arr) / sizeof(arr[0]);
//len = strlen(arr);
Print(arr, len);
cout << "请输入要左旋的次数:>" << endl;
cin >> count;
count %= len;
while (count--){
string_reverse(arr, len);
}
Print(arr, len);
}

int main(){
test();
system("pause");
return 0;
}


程序运行结果:



【注意】

如果向程序中所标注的直接用字符串来表示的话,会造成以下后果:



原因:

我们先来看一个内存分配示意图:



假如现在执行以下代码:

int a,b,c,d;
a=0;
b=1;
c=2;
d=3;




则a的地址最高,d的地址最低,因为这是一个压栈的过程。



但是如果执行以下语句的话:

char arr[] = { 'A', 'B', 'C', 'D', '1', '2', '3', '4' };


内存分配如图所示:



这时我们可以发现数组内存放的数据的地址是依次增加的,也就是说开始的元素地址最小,结束的元素地址最大。这是为什么呢?

原来数组在申请内存的时候不是为他的元素一个个申请内存,而是一次性的把数组所需要的内存申请好,再依次存放数组元素。

而如果我们在代码中用的是以字符串的形式的话,就会造成问题了:

char *arr = "ABCD1234";




解法二:

解题思路:

部分逆置 + 部分逆置

整体逆置

具体思路如图所示:



程序源码:

#include<iostream>
#include<assert.h>
#include<stdio.h>
#include<Windows.h>

using namespace std;

void Print(char* arr, int len){
for (int i = 0; i < len; ++i){
cout << arr[i] << "   ";
}
cout << endl;
}

//数组的逆置
void reverse(char* start, char* end){
assert(start);
assert(end);
while (start<end){
*start ^= *end;
*end ^= *start;
*start ^= *end;
start++;
end--;
}
}

void string_reverse(char* arr, int len,int count){
assert(arr);
assert(len > 0);
assert(count > 0);
cout << "逆置前半段" << endl;
reverse(arr, arr + count - 1);
Print(arr, len);
cout << "逆置后半段" << endl;
reverse(arr + count, arr + len - 1);
Print(arr, len);
cout << "整体逆置" << endl;
reverse(arr, arr + len - 1);
Print(arr, len);
}

void test(){
char arr[] = { 'A', 'B', 'C', 'D', '1', '2', '3', '4' };
int count = 0;
int len = 0;
len = sizeof(arr) / sizeof(arr[0]);
cout << "请输入要左旋的次数:>" << endl;
cin >> count;
count %= len;
string_reverse(arr, len, count);
}

int main(){
test();
system("pause");
return 0;
}


程序运行结果:





解法三:

解题思路:

首先把要逆置的字符串连接成双倍字符串;

然后从双倍字符的第count位开始(count是要逆转的K个字符),到第count + len结束(len是字符串长度);

这一段就是逆转后的字符串了;

示意图如下所示:



程序源码:

#include<iostream>
#include<assert.h>
#include<stdio.h>
#include<Windows.h>

using namespace std;

void Print(char* arr, int len){
for (int i = 0; i < len; ++i){
cout << arr[i] << "   ";
}
cout << endl;
}

void string_reverse(char* arr, int len, int count){
assert(arr);
assert(len > 0);
assert(count > 0);
//设置双倍字符串
char *ptemp = (char *)malloc(len * 2 + 1);
if (NULL == ptemp)
return;
char *temp = NULL;
temp = ptemp;
strcpy(ptemp, arr);
strcat(ptemp, arr);
//在双倍字符串中拿出逆置后的字符串
strncpy(arr, temp + count, len);
free(ptemp);
}

void test(){
char *arr = "ABCD1234";
int count = 0;
int len = 0;
len = strlen(arr);
Print(arr, len);
cout << "请输入要左旋的次数:>" << endl;
cin >> count;
count %= len;
string_reverse(arr, len, count);
Print(arr, len);
}

int main(){
test();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  左旋字符串
相关文章推荐