c++作业(一):字符串旋转

题目描述

定义字符串的旋转操作为:

左旋转 L :把字符串前面的若干个字符移动到字符串的尾部,如把字符串abcdef左旋转2位得到字符串cdefab。

右旋转 R :把字符串后面的若干个字符移动到字符串的头部,如把字符串abcdef右旋转2位得到字符串efabcd

输入格式

第一行一个整数N(1<=N<=20)表示有N组测试数据。

接下来的N行,每行有一个字符串S(长度1<S<=15); 操作M; 旋转的位数n(0<=n<=20)。当操作M为L时,代表将字符串左旋转n 位,M为R时,代表将字符串右旋转n位,M为除了R和L的其它无效操作时,按要求输出。

方法一
#include <iostream>
using namespace std;
void changestring(string s, char a, int n)
{
	int i = 0;
	char temp = 0;
	if (a == 'L')
	{
		for (int i = 0;i < n;i++)//移动n位
		{
			for (int i = 0;s[i + 1] != '\0';i++)//移动
			{
				temp = s[i];
				s[i] = s[i + 1];
				s[i + 1] = temp;
			}
		}
		for (int i = 0;s[i] != '\0';i++)//输出
		{
			if(i%2==0) cout << s[i];
		}
		cout << endl;
	}
	else if (a == 'R')
	{
		for (int i = 0;i < n;i++)
		{
			for (int i = s.length();i > 1;i--)
			{
				temp = s[i - 1];
				s[i - 1] = s[i - 2];
				s[i - 2] = temp;
			}
		}
		for (int i = 0;s[i] != '\0';i++)//输出
		{
			if (i % 2 == 0) cout << s[i];
		}
		cout << endl;
	}
	else
	{
		for (int i = 0;s[i] != '\0';i++)//输出
		{
			if (i % 2 == 0) cout << s[i];
		}
		cout << endl;
	}

}
int main()
{
	int N=0;
	cin >> N;
	string arr_string [20];//最多有二十个字符串
	char arr_direction[20];//储存左移右移
	int arr_int[20];//储存移动位数
	for (int i = 0;i < N;i++)
	{
		cin >> arr_string[i]>> arr_direction[i]>> arr_int[i];
	}
	for (int i = 0;i < N;i++)
	{
		changestring(arr_string[i], arr_direction[i], arr_int[i]);
	}
}

我一开始的思路是建立一个字符串数组,把每一个输入的字符串放进去。然后左旋转n位就是依次交换,这样的操作进行n次。

我在编写这个作业时发现的自己的问题:

①记不清数组的定义格式

数据类型+数组名+[]([]中间是数组的大小)

②要知道数组的长度必须得是固定的,因此不可以把输入的n作为数组的长度,所以我们要按照题目给的最多有20组测试数据,所以把数组长度设置为20。

③输入得和题给完全一致,cin>>…>>…这种形式代表空格输入。

④注意要写成第一个选择分支是if,下面的都是else if,最后是else。如果前面都是if最后else的话,就会造成if执行了也会进入else的情况(一个if和一个else对应)

⑤在右旋转时,我要从后往前交换,一直报错是因为当时一直用arr[i],i是从字符串长度开始递减的,所以事实上应该是arr[i-1],否则就会数组溢出了。

⑥发现自己对字符串的运用不够熟悉。

1.字符串判断空的条件是'\0',是右斜杠!!(我总是打成/)

2.字符串是一个特殊的char型数组,里面的每一位值储存在这个数组中,但是最后一位是‘\0'。正常的char型数组最后一位不是‘\0',但是如果你赋值的位数小于实际char型数组因此需要将循环条件写成s[i]!='\0',否则会造成数组访问越界。

3.因此一开始我想把字符串里面每个字符放到char型数组中是没有必要的,但是也有直接放到数组的方式。

方法一:

const char*k=NULL;

k=s1.c_str();

for(int i=0;k[i]!='\0';i++)

{

cout<<k[i]

}

思路就是定义一个k指针(是常量指针,就是指针的指向可以改变,但是指针指向内存的值不可以改变。复习:char const *k,指针指向不可以改变,但是指针指向内存的值可以改变)。

string这个类有很多封装的成员方法,c_str的意思就是返回当前字符串的首地址,但是是临时指针,因此必须得是const char *。这样k指针指向的就是字符串首地址,根据数组的本质是一个指针我们就知道k数组此时储存的就是字符串的数据了。

方法二

char s1[20];

strcpy(s1,s.c_str());

for(int i=0;s1[i]!='\0';i++) cout s1[i];

这个strcpy函数传入的参数不可以就是string,而是得是char型数组,所以我们用s.c_str获得这个数组!这样就把后面的char型数组的值复制给了前面的char型数组!

#include <iostream>
#include<string>
using namespace std;
void changestring(string s, char a, int n)
{
	int i = 0;
	char temp = 0;
	if (a == 'L')
	{
		string s1;
		string s1_m;
		s1 = s.substr(0, n);//截取从字符串下标为0开始,长度为n的字符串
		s1_m = s.substr(n, s.length() - n);//截取从字符串的第n+1位开始,长度为字符串长度-n的字符串
		
		s1_m.insert(s1_m.length() , s1);//在原下标位s.length()的位置前插入s1
		for (int i = 0;s1_m[i] != '\0';i++)//输出
		{
			if (i % 2 == 0) cout << s1_m[i];
		}
		cout << endl;
	}
	else if (a == 'R')
	{
		string s2;
		string s2_m;
		s2 = s.substr(s.length() - n, n);//截取从字符串下标为s.length()-n开始,长度为n的字符串
		s2_m = s.substr(0, s.length() - n);//截取从字符串第一位开始,长度为字符串长度-n的字符串
		s2_m.insert(0, s2);//在原下标位1的位置前插入
		for (int i = 0;s2_m[i] != '\0';i++)//输出
		{
			if (i % 2 == 0) cout << s2_m[i];
		}
		cout << endl;
	}
	else
	{
		for (int i = 0;s[i] != '\0';i++)//输出
		{
			if (i % 2 == 0) cout << s[i];
		}
		cout << endl;
	}

}
int main()
{
	int N=0;
	cin >> N;
	string arr_string [20];//最多有二十个字符串
	char arr_direction[20];//储存左移右移
	int arr_int[20];//储存移动位数
	for (int i = 0;i < N;i++)
	{
		cin >> arr_string[i]>> arr_direction[i]>> arr_int[i];
	}
	for (int i = 0;i < N;i++)
	{
		changestring(arr_string[i], arr_direction[i], arr_int[i]);
	}
}

这个思路是受题目的启发:删除前n位,移到后面;删除后n位,移到前面。

再次习得一些string的函数:

s1=s.substr(i,n); 是截取字符串下标为i开始,长度为n的字符串返回。

s1.insert(i,s2);是指在字符串下标为i的位置前,插入s2字符串

当然,我们这题可以直接用+来拼接字符串。

但是不知道为什么,这种方法在oj系统上内存超了,不能过。(下节课问助教)

方法三
#include<iostream>
#include<string>
using namespace std;
int main()
{
	char a[10001];
	char b[10001];
	int n, i_, m;
	cin >> a;//输入到字符型数组中
	cin >> m;//移动的位数
	n = strlen(a);
	for (int i = 0;i < n;i++)
	{
		i_ = (i + m) % n;
		b[i_] = a[i];
	}
	b[n] = '\0';
	cout << b;
	return 0;
}

这是同学告诉我的方法,创建一个新的char型数组,然后按照对应序号放进去。

#include<iostream>
using namespace std;
struct my_char
{
	char ch[15];
	int n;
	char direction;
};
void reverse(my_char a)
{
	int num = strlen(a.ch);
	char m_ch[15];
	if (a.direction == 'L')
	{
		for (int i = 0;a.ch[i] != '\0';i++)
		{
			m_ch[(i + num - a.n) % num] = a.ch[i];
		}
	}
	else if (a.direction == 'R')
	{
		for (int i = 0;a.ch[i] != '\0';i++)
		{
			m_ch[(i+a.n)%num] = a.ch[i];
		}
	}
	
	int i = 0;
	while (i < num)
	{
		if(i%2==0) cout << m_ch[i];
		i++;
	}
	cout << endl;
}
int main()
{
	int N;//储存几组数据
	cin >> N;
	my_char arr[20];//最多有20组数据
	for (int i = 0;i < N;i++)
	{
		cin >> arr[i].ch >> arr[i].direction >> arr[i].n;
	}
	for (int i = 0;i < N;i++)
	{
		reverse(arr[i]);
	}
}

自己运行成功了,但是不知道为什么OJ上编译失败,下节课问助教。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值