bupt信通院上机第一学期实验四(30-37) 指针

方法论

1.编程基本素养和能力:
看到一个编程题,就应将其不断地拆解为一个个可解决的小问题。之后要做的就是将每个小问题写成一个个代码段,以及考虑一下大方向上的代码连接问题。
2.通过书本和视频理解概念和在解决问题中应用理解是完全不同的,不仅要理解,还要通过会写代码编程来解决问题。

实验30 求最大值并指针输出

题目描述

编写相应的程序用指针实现:从键盘输入3个整型数va、vb、vc,通过一个指向整型的指针iptr,输出3个数中的最大值。
输入
1 2 3
输出
3

思路

对于比较大小,C++提供了一个方便的运算符?: ,可以用它来无限嵌套来比较任意个数的的大小;
比较大小的思想:先比较前两个数,再拿大(小)的数和下一个数比较

代码

#include<iostream>
using namespace std;
int main() {
	int va, vb, vc,x;
	cin >> va >> vb >> vc;
	x = va > (vb > vc ? vb : vc) ? va : (vb > vc ? vb : vc);
	int* iptr = &x;
	cout << *iptr;
	return 0;

实验31 求一维、二维数组元素平均值

题目描述

编写一个函数get_average()获取整型数组元素的平均值。要求这个函数既可以用来求一维数组元素的平均值,也可以求二维数组元素的平均值。
在main()函数中通过具体的一维数组Array_1D和二维数组Array_2D测试这个函数。
假定一维数组为a[5],二维数组为b[2][3],一维数组和二维数组的变量值由键盘分别输入,在屏幕上输出一维数组和二维数组的平均值,平均值间用一个空格分开。
输入
1 2 3 4 5
1 2 3 4 5 6
输出
3 3.5

程序化

定义重载函数分别求一维数组和二维数组的平均值;
对二维数组的元素进行操作-双层循环(如从键盘输入二维数组元素);

代码

//数组求和函数
#include <iostream>
using namespace std;
//要求一维数组和二维数组的平均值,可用重载函数(一维数组和二维数组是不同的形参)
float get_average(int a[5]) {
	//int a[5];
	//程序化:形参在主函数中已经定义,不能再在此函数中定义
	//sum定义和初始化应该在循环外,循环内定义的变量只在循环内生存
	//易错:sum应该是float,而非int
	float sum = 0;
	for (int i = 0; i < 5; i++) 
		sum += a[i];
	return sum / 5;
}
float get_average(int b[2][3]) {
	//int b[2][3];
	float sum = 0;
	//程序化:对二维数组的元素进行操作-双层循环
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 3; j++)
			sum += b[i][j];
	return sum / 6;
}
int main() {
	int a[5], b[2][3];
	//程序化:从键盘输入一维数组元素
	for (int i = 0; i < 5; i++)
		cin >> a[i];
	//程序化:从键盘输入二维数组元素
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 3; j++)
			cin >> b[i][j];
	cout << get_average(a) <<" "<< get_average(b) << endl;
}

实验32字符串的变换

题目描述

编制程序,调用指针作为参数的函数,实现下面两字符串变量的交换。 char* ap=“hello”; char* bp=“how are you”; 交换的结果为:ap 指向"how are you",bp 指向"hello"。 (注意:输出语句中的;和.为英文符号)
输入
输出
ap指向how are you;
bp指向hello.

程序化

交换思想代码;

代码

这题比较简单,直接上代码

#include<iostream>
#include<string>
using namespace std;
void swap(char* ap, char* bp)
{
	char* cp;
	cp = ap;
	ap = bp;
	bp = cp;
}
int main()
{
	const char* ap = "hello", * bp = "how are you";
	swap(ap, bp);
	cout << "ap指向" << ap<<";"<< endl;
	cout << "bp指向" << bp<<".";
	return 0;
}

实验33 动态申请内存及元素排序

题目描述

动态申请一个一维整型数组,要求用户从键盘输入元素个数,采用new运算符分配空间,从键盘输入数组变量的值.
写一个函数void Func(int* A, int nSize),使A把0移至后面,非0整数移至数组前面并保持有序(升序)。
将排序后的数组变量的值输出到屏幕上,各数值间用一个空格隔开。
输入
10 1 2 3 4 5 0 7 8 0 10
输出
1 2 3 4 5 7 8 10 0 0

思路

这道题说明一般数组和指针本质是一样的,可通用;
思路1.先给数组排序(之前也说过,这里不再赘述),再把数组中的0移向末尾
思路2.(师兄教的高端做法)思路1的两步可以合成一步,多定义一个bool型函数而已

程序化

1.把数组元素中的0移至最后,其余元素升序排列;

2.从键盘输入动态一维数组元素的两种方法;

3.易错点:一些地方的表达式的值必须是bool值(如条件语句的条件),特别注意=和==的区别;

4.最后一个元素输出时无间隔的问题;

代码

#include<iostream>
using namespace std;
int main() {
	int n;cin >> n;
	//1.程序化:申请动态一维数组
	int* p = new int[n]; 
	int* p1 = p;
	//2.程序化:从键盘输入动态一维数组·法一
	/*for (int i = 0; i < n; i++) {
		int k; cin >> k;
		*p1 = k; *p1++;
	}*/
	//程序化:从键盘输入动态一维数组·法二
	for (int i = 0; i < n; i++)
		cin >> p[i];
	//3.排序
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n - i - 1; j++) {
			if (*(p1 + j) > * (p1 + j + 1)) {
				int hold = *(p1 + j + 1);
				*(p1 + j + 1) = *(p1 + j);
				*(p1 + j) = hold;
			}
		}
	//4.移0
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n - i - 1; j++) {
			if (*(p1 + j) == 0) {
				int hold = *(p1 + j + 1);
				*(p1 + j + 1) = *(p1 + j);
				*(p1 + j) = hold;
			}
		}
	//5.分步输出
	for (int i = 0; i < n - 1; i++)
		cout << p[i] << " ";
	cout <<*(p1+n-1);
	//6.释放
	delete[]p;
	return 0;
}

师兄的思路

#include <iostream>
using namespace std;
int n; 
bool compare(int a, int b) {
   if (!a) return 1;
   if (!b) return 0;
   return a > b;
  }
     
int main() {
	cin >> n;
    int *p = NULL;
    p = new int[n];
    int *pos = p, *pp = p;
    for (int i = 0; i < n; i++) {
    	int k; cin >> k;
    	*pos = k; pos++;
    }
    for (int i = 0; i < n; i++)
    	for (int j = 0; j < n - i - 1; j++) {
    		if (compare(*(pp + j), *(pp + j + 1))) {
    			int t = *(pp + j);
    			*(pp + j) = *(pp + j + 1);
    			*(pp + j + 1) = t;
    			} 
    		}
    for (int i = 0; i < n - 1; i++) 
    		cout << *(p + i) << " ";
    cout << *(p + n - 1);
    delete [] p;
    return 0;
    }

实验34 字符串比较与排序

题目描述

用字符指针数组,将给定的5个字符串(可以是任意5个国家名字)进行排序并输出。
输入
China American France Spain Greece
输出
American
China
France
Greece
Spain

程序化

1.比较字符串大小->用C++提供的函数strcmp(char*s1,char*s2),其返回值为<0、=0、>0;

2.用函数strcmp(char*s1,char*s2)来比较一组字符串(与冒泡算法思想的结合);

3.冒泡算法思想;

4.字符串处理->一定记得包含cstring头文件;

5.根据题目要求(用字符指针数组+数组中得包含各种字符串)+一维字符指针数组只能储存一串字符串->用二维数组储存多串字符串(直接向a[i]中输入字符串);

6.再将a[i]赋给一维指针数组name[i],用*name[i]作为strcmp函数形参;

7.对二维数组的理解->相当于以一维数组为元素(每行)的一维数组;

8.如何将一维数组设为二维数组的元素(每行)->详见代码

代码

#include <iostream>
#include <cstring>
using namespace std;
int main() {
	//1.首先定义一个一维指针数组和二维数组
	char* name[5];
	char a[5][100];
	//2.键盘输入赋值
	for (int i = 0; i < 5; i++) {
		cin >> a[i];
		name[i] = a[i];
	}
	//3.strcmp比较,以此为条件依据进行冒泡排序(条件语句+冒泡排序)
	//冒泡算法
	for(int i=0;i<5;i++)
		for (int j = 0; j < 4 - i; j++) {
			if (strcmp(name[j], name[j + 1]) > 0) {
				//以字符指针作为中间存储存字符串
				char* t = name[j];
				name[j] = name[j + 1];
				name[j + 1] = t;
			}
		}
	//4.输出
	for (int i = 0; i < 5; i++)
		cout << name[i] << endl;
	return 0;
}

实验35 结构体与指针并排序输出元素

题目描述

已知有3名学生及五门课程的成绩,要求根据学生的各科平均分排序(降序),并输出学生的所有信息和平均分(用指针数组完成)。
输入
Jane 90 80 75 60 85
Mark 85 78 98 85 86
Lily 56 65 75 68 80
输出
Mark 85 78 98 85 86 86.4
Jane 90 80 75 60 85 78
Lily 56 65 75 68 80 68.8

思路

1.又有字符串又有int又有float真不好办呢。。。
->(1)用结构数组(结构数组的使用:用struct自定义一个数据类型<包含各种成员>,再用这数据类型定义一个变量或一个数组);
(2)本题有三组+每组都有字符串又有int又有float->
定义一个结构数组(其中包含多个结构变量)

2.(1)对结构数组的理解:不同类型数据(每一类可是数组)的集合;
(2)访问结构数组的成员的方法:点操作符.

3、结构指针的成员的访问方法:箭头操作符->

4、如何从键盘往结构数组中输入数据;

5、每个循环结构里可以做很多事情(比如这里就不止有一条输出语句)

代码

文笔不够,代码来凑

#include <iostream>
using namespace std;
int main() {
	//1.自定义一个结构数据类型,用该类型定义一个结构数组
	struct student {
		char name[10];
		int score[5];
		float aver;
	};
	student stu[3];
	//2.从键盘往数组中输入数据
	for (int i = 0; i < 3; i++) {
		cin >> stu[i].name;
		float num = 0;
		for (int j = 0; j < 5; j++) {
			cin >> stu[i].score[j];
			num += (float)stu[i].score[j];
		}
		stu[i].aver = num / 5;
	}
	//3.定义一个结构指针,将结构数组的值赋给它
	student* p[3];
	for (int i = 0; i < 3; i++) 
		p[i] = &stu[i];
	//4.根据aver的大小进行排序
	for (int i = 0; i < 2; i++)
		if (p[i]->aver < p[i+ 1]->aver) {
			student* temp;
			temp = p[i];
			p[i] = p[i + 1];
			p[i + 1] = temp;
			}
	//5.输出
	//程序化:每个循环结构里可以做很多事情(比如这里就不止有一条输出语句)
	for (int i = 0; i < 3; i++) {
		cout << p[i]->name<<" ";
		for (int j = 0; j < 5; j++)
			cout << p[i]->score[j] << " ";
		cout << p[i]->aver;
	}
	return 0;
}

实验36 数组合并并排序

题目描述

将两个数组a和b合并,合并后的数组按升序输出。 说明:
1)数组a和b的大小和元素的值从键盘输入;先输入数组大小,再输入数组的值;
2)合并后的数组输出时,各数值间以空格分开。
输入
2 1 2
4 1 2 3 4
输出
1 1 2 2 3 4

思路

先申请动态内存并赋给指针,再将两数组都存进去。再对指针内容统一排序。
易出bug:注意是先要输入数组大小,在输入数组;
注意指针初值是否改变,常将多个指针指向同一动态内存。

程序化

1.根据题目要求的输入顺序来放cin的位置;

2.对指针相关概念的理解;

3.数组都可以弄成指针;

4.对指针进行多次初值操作;

5.动态申请内存——new和delete成对出现;

代码

#include<iostream>
using namespace std;
int main() {
	int a, b;
	//注意题目要求的输入顺序
	cin >> a;
	//数组[]中只能是常量表达式,因此只能用指针
	//先申请整型动态内存
	int* p= new int[110];
	//再将申请的内存分配给指针p1,p2
	int* p1 = p;
	int* p2 = p;
	//再往指针里写入从键盘输入的数据,将两个数组都写入p1
	//因为p1得值在输入数时会改变,因此这里再用一个指针p2指向同一动态内存,以便后面冒泡排序和输出
	//这里要求对指针相关概念要理解到位
	for (int i = 0; i < a; i++)
	{
		int c; cin >> c;
		//*p1指指针所指向的第一个元素(*间接运算指通过指针间接访问其所指向的内容)
		//p1指内容的首地址,*p1指内容(非字符指针)
		//若为字符指针,cout<<p1是输出指向的字符串(唯一特殊)
		//p1指指针首地址,p1++是指针的运算,含义是当前地址的下一地址
			*p1 = c; p1++;
	}
	cin >> b;
	for (int i = 0; i < b; i++) {
		int d; cin >> d;
		*p1 = d; p1++;
	}
	//知识点·冒泡排序程序化:双层循环结构,第一层是遍数(即控制第二层执行次数的),第二层是每一遍排序
	//程序化:第二层中循环条件为j<a+b-i-1的原因是升序排列中每次排序后的最后一个一定是最大的,j<a+b也行但没必要
	for (int i = 0; i < a + b; i++) {
		for (int j=0; j < a + b - i - 1; j++) {
			if (*(p2 + j) > * (p2 + j + 1)) {
				int hold = *(p2 + j);
				*(p2 + j) = *(p2 + j + 1);
				*(p2 + j + 1) = hold;
			}
		}
	}
	//程序化(最后一个数无空格):这里最后输出因为最后一个数没有空格,所以单独用一条语句输出(易错)
	for (int i = 0; i < a + b - 1; i++)
				cout << *(p2 + i) << " ";
	cout << *(p2 + a + b - 1) << endl;
	//最后别忘了释放动态内存(记住申请和释放始终成对出现)
	delete[]p;
	return 0;
}

实验37 元素插入与排序

题目描述

请编写函数实现将一个数值插入到数组中适当的位置,使新数组按降序排列,并将插入的位置输出到屏幕上。
说明:1)原数组大小和数值由键盘输入,动态创建数组;
2)插入的数值由键盘输入。
3)如果插入数据与原数组中某数据相同,则插在该数据之前。
输入
10 1 4 5 2 3 6 7 8 10 9
11
输出
1

思路:

先排序,再确定插入的位置,最后根据位置调整插入

代码

#include <iostream> 
using namespace std;
int flag = 0;
int main() {
	//准备程序化:申请动态内存并赋给指针,输入数组
	int n, in;
	cin >> n;
	int* p = new int[1000];
	//注意指针的初值是否改变,因为很多时候后面还会从指针的初值开始操作,这时候就会出现bug
	int* p1 = p;
	int* p2 = p;
	for (int i = 0; i < n; i++) {
		int k; cin >> k;
		*p1 = k; p1++;
	}
	cin >> in;
	//冒泡排序
	for(int i=0;i<n;i++)
		for (int j = 0; j < n - i - 1; j++) {
			if (*(p1 + j) < *(p1 + j + 1)) {
				int hold = *(p1 + j);
				*(p1 + j) = *(p1 + j + 1);
				*(p1 + j + 1) = hold;
			}
		}
	int pos = 0;
	for (int i = 0; i < n; i++)
		//若该位置的数不大于in,
		if (*(p + i) <= in) {
			pos = i;
			flag = 1;
		}
	//这里引入flag是因为考虑到当in最小时这种特殊情况,所以将其单独考虑
	//如何写这种特殊情况的代码呢?——若in最小,即flag=0,此时pos=n
	if (!flag)pos = n;
	//根据应插入的位置进行调整和插入:将后面的数都往后退一格,in插入
	for (int i = n; i > pos; i--) {
		*(p + i) = *(p + i - 1);
		*(p + pos) = in;
	}
	//因为p本身代表1,因此in位置为pos+1
	cout << pos + 1 << endl;
	delete[]p;
	return 0;
}
  • 20
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值