SZU面向对象程序设计OJ复盘|思路分享

A. 成绩查询(指针运算)

题目描述:已知一组学生成绩,然后根据输入的序号查询成绩

要求:

1. 使用一个整数数组存储学生成绩,假设元素数是n。

2. 使用一个指针指向数组中间元素,即n/2的位置。

3. 使用++和--运算符,求出数组中间元素的前一个成绩和后一个成绩

4. 输入一个序号,然后计算这个序号的元素和中间元素的距离,然后使用指针去访问

例如有11个学生,指针指向中间的学生也就是第6个学生,若输入序号3,即查询第3个学生的成绩,第3和第6之间距离为3,那么指针应该怎么运算呢???

如果有两个中间学生,则将后面那个看为中间学生。

5. 整个程序除了输入时可以使用数组下标,其他部分尽量使用使用指针进行访问。

输入:

第一行输入t表示有t个测试实例

第二行先输入n,表示有n个学生,然后再输入n个成绩(正整数)

第三行输入1个序号,表示要查询成绩的学生的序号。

依次输入t个实例

按自然意义,序号是从1开始计算

提示:在数组中是从........

输出:

对于每个测试实例:

第一行输出数组中间元素的前一个成绩和后一个成绩

第二行根据序号输出1个成绩

输入样例:

2
7 66 99 88 44 77 33 11
2
11 60 80 50 20 90 35 70 40 10 95 30
9

输出样例:

88 77
99
90 70
10

代码参考: 

#include <iostream>
using namespace std;

int main(){
	int t;
	cin >> t;
	
	while(t--){
		int n;
		cin >> n;
		int socre[n] ;
		
		for(int i=0;i<n;i++){
			cin >> socre[i];// 读入
		}
		// 定义一个指针p,初始化为指向数组socre中间位置的元素
		int *p = &socre[n/2];
		
		cout << *(--p) <<" " ;// 先对指针p进行递减操作,然后输出p指向的元素(即中间元素的前一个)
		p++; // 记得复原
		cout << *(++p) << endl;// 先对指针p进行递增操作,然后输出p指向的元素(即中间元素的后一个)
		p--; // 同理复原
		
		int index;
		
		cin >> index;
		
		cout << *(p + (index -1 - n / 2)) << endl;
	}
	return 0;
}

tips:① int *p = &socre[n/2]; 这里如果n是奇数,p指向中间的元素。如果是偶数,p指向中间右侧的元素,因为n/2会自动向下取整(例如7/2为3,第三个也就是中间元素,8/2为4,第四个是中间偏右那个元素)

② 对指针加减后记得复原

③ 按自然意义,序号是从1开始计算,而在数组中是从0开始标号,输入样例给的是数组号,所以按数学规律计算它跟指针p的关系就行

B. 月份查询(指针数组)

题目描述

已知每个月份的英文单词如下,要求创建一个指针数组,数组中的每个指针指向一个月份的英文字符串,要求根据输入的月份数字输出相应的英文单词

1月 January

2月 February

3月 March

4月 April

5月 May

6月 June

7月 July

8月 August

9月 September

10月 October

11月 November

12月 December

输入:

第一行输入t表示t个测试实例

接着每行输入一个月份的数字

依次输入t行

输出:

每行输出相应的月份的字符串,若没有这个月份的单词,输出error

输入样例:

3
5
11
15

输出样例:
May
November
error

代码参考:

#include <iostream>
using namespace std;

int main(){
	int t;
	cin >> t;
	char *p[12];// 创建一个有12个指针的数组,即一个数组里,每个元素都是一个指针(char类型的地址)
	// 用char类型的二维数组保存十二个月份
	char months[12][50] = {"January","February","March","April",
							"May","June","July","August",
							"September","October","November","December"};

	for(int i=0;i<12;i++){
		p[i] = months[i];// 让每个指针都指向对应月份,不用&month[i],因为它本身就是地址了
	}
          
	while(t--){
		int m;
		cin >> m;
		if(m>=1 && m<=12){
			cout << p[m-1] << endl; // 数组名为实际月份-1
		}
		else{
			cout << "error" << endl;
		}
	}
	return 0;
}

tips:①基本的指针数组创建,把char*看成每个数组元素类型就好,char* p[12]跟char c[12]只是保存的元素不同

② 二维数组概念,也叫嵌套数组,即外层是一个数组,而每个数组元素又是一个内层数组,所以months[i]能表示第i个外层数组元素,也即其内层数组的开始地址

C. 字符串比较(指针参数)

题目描述:

编写一个函数比较两个字符串,参数是两个字符指针(要求显式定义,例如char *S, char *T),比较字符串S和T的大小。如果S大于T,则返回1,如果S小于T则返回-1,如果S与T相等则返回0。

比较规则:

1.把两个字符串的相同位置上的字符进行比较,字符的大小比较以ASCII值为准

2.在比较中,如果字符串S的字符大于字符串T的字符的数量超过小于的数量,则认为S大于T,如果等于则S等于T,如果小于则S小于T

例如S为aaccdd,T为eebbbb,每个位置比较得到S前两个字母都小于T,但后4个字母都大于T,最终认为S大于T

3.如果两个字符串长度不同,则更长的字符串为大

在主函数中输入两个字符串,并调用该函数进行判断,在判断函数中必须使用函数参数的指针进行字符比较

输入:

输入t表示有t个测试实例

接着每两行输入两个字符串

依次输入t个实例

输出:

每行输出一个实例的比较结果

输入样例:

3
aaccdd
eebbbb
AAbb++
aaEE*-
zznnkk
aaaaaaa

输出样例:

1
0
-1

参考代码:

#include <iostream>
#include <string>
using namespace std;

int cmp(char* s, char* t){
	int result = 0;
	int len1, len2;
	
	len1 = strlen(s);
	len2 = strlen(t);
	
	if(len1 == len2){
		// 若长度相等,依次比较
		int cnt_s = 0;
		int cnt_t = 0;
		
		for(int i = 0;i < len1;i++){
			// 统计大小比较结果
			if(*s > *t){
				cnt_s++;
			}
			else if(*s < *t){
				cnt_t++;
			}
			// 指针加加
			s++;
			t++;
		}
		// 根据结果按要求返回
		if(cnt_t == cnt_s){
			result = 0;
		}
		else if(cnt_s > cnt_t){
			result = 1;
		}
		else{
			result = -1;
		}
	}
	// 谁长返回相应值
	else if(len1 < len2){
		result = -1;
	}
	else{
		result = 1;
	}
	return result;
}

int main(){
	int t;
	cin >> t;
          
	while(t--){
		char str1[50] , str2[50];
		cin >> str1 >> str2;// 输入并保存字符串
		// 分别让两个字符指针指向它们
		char *s = str1;
		char *t = str2;
		cout << cmp(s,t) << endl;
	}
	return 0;
}

tips:比较简单,cmp函数按规矩写就好。

D. 密钥加密法(指针应用)

题目描述:

有一种方式是使用密钥进行加密的方法,就是对明文的每个字符使用密钥上对应的密码进行加密,最终得到密文

例如明文是abcde,密钥是234,那么加密方法就是a对应密钥的2,也就是a偏移2位转化为c;明文b对应密钥的3,就是b偏移3位转化为e,同理c偏移4位转化为g。这时候密钥已经使用完,那么又重头开始使用。因此明文的d对应密钥的2,转化为f,明文的e对应密钥的3转化为h。所以明文abcde,密钥234,经过加密后得到密文是cegfh。

如果字母偏移的位数超过26个字母范围,则循环偏移,例如字母z偏移2位,就是转化为b,同理字母x偏移5位就是转化为c

要求:使用三个指针p、q、s分别指向明文、密钥和密文,然后使用指针p和q来访问每个位置的字符,进行加密得到密文存储在指针s指向的位置。

除了变量定义和输入数据,其他过程都不能使用数组下标法,必须使用三个指针来访问明文、密钥和密文。

提示:当指针q已经移动到密钥的末尾,但明文仍然没有结束,那么q就跳回密钥头

输入:

第一行输入t表示有t个测试实例

第二行输入一个字符串,表示第一个实例的明文

第三行输入一个数字串,表示第一个实例的密钥

依次输入t个实例

输出:

每行输出加密后的密文

输入样例:

2
abcde
234
XenOS
56

输出样例:

cegfh
CksUX

 代码参考:

#include <iostream>
#include <string>
using namespace std;


int main(){
	int t;
	cin >> t;
          
	while(t--){
		char str1[50] , str2[50], ans[50];
		cin >> str1 >> str2;
		
		char *p = str1;// 明文
		char *q = str2;// 密钥
		char *s = ans; // 密文
		int len = strlen(str1);
		
		for(int i = 0;i < len;i++){
			
			if(*q == '\0'){
				q = str2; // 密钥用完就重头开始用
			}
			
			char ch = *p + (*q - '0');// 加密
			
			if(ch < 65 ){
				// 加密后发现<a 即不是字母了,+26使其回到对应位置
				ch += 26;
			}
			else if((ch > 90 && ch < 97) || (ch > 122) ){
				// 同理,在小写与大写之间,或者大于大写,减去26即可
				ch -= 26;
			}
			
			*s = ch; // 将ch存入密文字符串中
			// 指针加加
			p++;
			q++;
			s++;
		}
		cout << ans << endl;
	}
	return 0;
}

tips:①首先注意到密钥是数字,但是我们要用的时候是一位一位用,所以不能用Int类型存,只能用字符串存,但在加密时要转换为数字,所以要减去0的ascall码得到对应数字。

② 小复杂的是,加密后密文不在字母范围内,需要分成三种情况处理。

 E. 蛇形矩阵(指针与动态内存分配)

题目描述:

蛇形矩阵,是由1开始的自然数一次排列成的N*N的正方形矩阵,数字依次由外而内的递增。如 N=3时蛇形矩阵为:

1 2 3

8 9 4

7 6 5

N=6时蛇形矩阵为:

1     2   3   4   5   6

20 21 22 23 24   7

19 32 33 34 25   8

18 31 36 35 26   9

17 30 29 28 27 10

16 15 14 13 12 11

输入蛇形矩阵宽度,动态分配二维数组,设置蛇形矩阵并输出结果。

输入:

测试次数t

每组测试数据一行:数组大小N(>0)

输出:

对每组测试数据,输出计算得到的蛇形矩阵。每行元素间以空格分隔,最后一个元素后无空格。

每组测试数据之间以空行分隔。

输入样例:

3
3
6
2

输出样例:

1 2 3
8 9 4
7 6 5

1 2 3 4 5 6
20 21 22 23 24 7
19 32 33 34 25 8
18 31 36 35 26 9
17 30 29 28 27 10
16 15 14 13 12 11

1 2
4 3

 代码参考:

 

#include <iostream>
#include <string>
using namespace std;

int main(){
	int t;
	cin >> t;
          
	while(t--){
		int n;
		cin >> n;
		// 动态分配
		int ** matrix =new int*[n];
		for(int i=0;i<n;i++){
			matrix[i] = new int[n];
		}
		// 为每个元素赋值
		int value = 1;
		int min_row = 0, max_row = n-1;
		int min_col = 0, max_col = n-1;
		
		while(value <= n*n){
			// 从左到右
			for(int i=min_col;i<=max_col;i++){
				matrix[min_row][i] = value;
				value++;
			}
			min_row++;
			// 从上到下
			for(int i=min_row;i<=max_row;i++){
				matrix[i][max_col] = value;
				value++;
			}
			max_col--;
			// 从右往左
			for(int i=max_col;i>=min_col;i--){
				matrix[max_row][i] = value;
				value++;
			}
			max_row--;
			// 从下到上
			for(int i=max_row;i>=min_row;i--){
				matrix[i][min_col] = value;
				value++;
			}
			min_col++;
		}
		
		for(int i=0;i<n;i++){
			for(int j=0;j<n-1;j++){
				cout << matrix[i][j] << " ";
			}
			
			cout << matrix[i][n-1] << endl;
		}
		
		cout << endl;
		
		for(int i = 0; i < n; ++i) {
			delete[] matrix[i]; // 删除每行的列元素
		}
		delete[] matrix; // 删除行指针
		
	}
	return 0;
}

tips: ①动态分配二维数组,就那几行代码,记下来会用就行。

②蛇形一开始找不到规律,本来想着找下一行跟前一行关系,再逐行赋值,发现很难描述...参考网上代码才知道要按规律像走迷宫一样按123456...来赋值。一次循环分为四步,先从左到右,再从上到下,再从右往左,最后从下到上,开始下次循环。怎么样让“画”出的圈越来越小呢,通过控制行、列就行,走完一步,增大/减小相应行列。 

 

 

 F. 三角函数求和(函数指针)(程序填空题)

 

题目描述:

以下代码计算[a,b)范围内,0.1为步长的三角函数(sin或cos或tan)之和。请补齐sigma函数。

输入:

多组测试数据,每行数据格式为:

三角函数类型(sin或cos或tan)  起始范围a  终止范围b

输出:

对每组测试数据输出[a,b)内,步长0.1的三角函数和。

 输入样例

sin 0.1 1.0
tan 0.1 1.0
cos 1 1.5

输出样例:

5.01388
6.95511
1.79372

参考代码:

#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
/********** Write your code here! **********/
// 一个接受函数指针作为参数的函数
double sigma(double (*f)(double), double a, double b) {
	double sum =0.0;
	for(double i=a;i<b;i+=0.1){
		sum += f(i);
	}
	
	return sum;
}


/*******************************************/
int main()
{
	char s[20];
	double a, b;
	while (cin >> s >> a >> b)
	{
		if (!strcmp(s,"sin"))
			cout << sigma(sin, a, b) << endl;
		else if (!strcmp(s,"cos"))
			cout << sigma(cos, a, b) << endl;
		else 
			cout << sigma(tan, a, b) << endl;
	}
	return 0;
}

tips:①记住接受函数指针作为参数的函数怎么写就行

  • 28
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值