第一章 C++编程基础——1.6指针


  本文开始涉及C、C++中比较头疼的知识: 指针
  【代码已上传至自己github,供参考: github
  回到上一篇文章: 第一章 C++编程基础——1.5学习使用C++中的Array和Vector 遗留的问题。第一、上限是六个数列,依次猜完,程序则没有预期的结束;第二,这个方法每次都以同样的顺序显示六组元素,我们的目的是增加程序的弹性。
  本文将通过指针(pointer),舍弃以名称指定的方式,间接访问每个 vector,达到透明化的目的。我们可以操作指针(代表某特定内存地址),不需要直接操作对象。之前了解了如何定义一个对象:

1、指针

int ival=1024

  指针内含某特定类型对象的内存地址。如果我们要定义某个特定类型的指针时,必须在类型名称之后加上*

int *pi;//pi是个int类型对象的指针

  如果我们希望去的对象所在的内存地址而不是对象值,应该使用取址运算符&

int *pi=&ival;//将pi的初试值设为ival所在的内存地址

  如果要访问一个由指针所指的对象,我们可以对该指针进行提领,即取得“位于该智能所指内存地址上”的对象,在指针之前使用*

if(*pi!=1024)//读取vial值
	*pi=1024;//写值到vial

  指针总结:
1、指针含义说明

pi;//表示pi所代表的内存地址
*pi;//表示vial的值

2、指针可能不指向任何对象,程序运行时可能发生错误,也就是野指针。一个未指向任何对象的指针,它的地址一般为0,也称之为null指针、野指针,所以我们可以对指针进行初始化:

int *pi=0


案例:
  我们定义6个vector对象(代表六个数列):

vector<int> fibonacci,Lucas,Pell,Triangular,Square,Pentagonal;

  我们用一个指针来指向一个“元素类型为int”的vector,形式为:
  type_of_object_pointer_to *name_of_pointer_object
  type_of_object_pointer_to:数据类型
  name_of_pointer_object:对象名
  我们用来指向vector<int> ,则命名我pv,初值为0。

int *pv=0

  这种方式可以依次指向数列的vector,比较繁琐,会牺牲程序的透明性。那么,另一种方案就是将每个数列的内存地址存入vector中,我们可以通过索引的方式,透明访问这些数列:

const int seq_cnt=6;
//定义指针数组,长度为6
//每个指针都指向vector<int>对象
vector<int> *seq_addrs[seq_cnt]={
&fibonacci,&Lucas,&Pell,
&Triangular,&Square,&Pentagonal;
}

  其中,seq_addrs表示array,元素类型为vector<int> *seq_addrs[0]则表示fibonacci vector的地址。因此,我们可以通过索引值的方式,不通过名称来访问每个vectir:

vector<int> *current_vec=0;
for(int i=0;i<seq_cnt;i++){
	current_vec=seq_addrs[i];//所有要显示的元素通过current_vec访问
}

  最后,主要解决顺序问题。之前用户总是依据fibonacci,Lucas,Pell,Triangular,Square,Pentagonal的顺序进行猜测。我们希望数列随机出现,这里用到了C语言标准库中的rand()srand()函数:

#include <cstdlib>
srand(seq_cnt);//srand()的参数是随机数生成器的种子
seq_index=rand()%seq_cnt;//rand()会返回“0-int所能表示最大数”的一个整数,我们的索引在0-5之间,索引采用取余的方式。
current_vec=seq_addrs[seq_index];
}

  两个函数必须使用cstdlib头文件

2、案例更新

  下面就是依据上一篇文章进行改进的代码:

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
int main() {
	int usr_guess;      //用户猜测的数字
	bool num_seq = true; //显示下一组数列
	bool guess_again = true; //用户想再猜一次
	int guess_num = 0;  //用户猜的总次数
	int guess_right = 0;//用户猜对次数
	char usr_rsp;      //用户的回答  内循环用
	char try_again;    //用户的回答  外循环用
	double usr_score = 0.0;//评分比值,采用double双精度类型
	const int max_tries = 3;//设置最多猜测次数

	const int seq_size = 18;//设置数列最大长度




	int elem_seq[seq_size] = { //每个数列存储前三个数字进行猜测
		1,2,3, //Fibonacci(斐波那契)
		3,4,7, //Lucas(卢卡斯)
		2,5,12, //Pell
		3,6,10, //Triangular
		4,9,16, //Square
		5,12,22 //Pentagonal
	};
	//将每个数列前三个数存入vector
	vector<int> fibonacci(elem_seq, elem_seq + 3);
	vector<int> lucas(elem_seq+3, elem_seq + 6);
	vector<int> pell(elem_seq+6, elem_seq + 9);
	vector<int> Triangular(elem_seq+9, elem_seq + 12);
	vector<int> Square(elem_seq+12, elem_seq + 15);
	vector<int> Pentagonal(elem_seq+15, elem_seq + 18);



	const int max_seq = 6;
	string seq_names[seq_size] = {
		"Fibonacci",
		"Lucas",
		"Pell",
		"Triangular",
		"Square",
		"Pentagonal"
	};
	//将每个数列地址存入seq_addrs数组
	vector<int> *seq_addrs[max_seq] = {
		&fibonacci,&lucas,&pell,&Triangular,&Square,&Pentagonal
	};
	vector<int> *current_vec = 0;
	int seq_index;
	srand(max_seq);



	while (num_seq == true) {
		int try_cnt = 0;//猜的次数与最多次数比较
		bool got_it = false; //用户是否猜对

		//对数列进行随机化
		seq_index = rand() % max_seq;
		current_vec = seq_addrs[seq_index];//获取数列

		//开始猜测数字
		cout << "The first two elements of the squence are: "
			<< (*current_vec)[0]<< ","
			<< (*current_vec)[1] << "."
			<< "\nWhat is the next element?\n";

		//用户猜错且想再次猜
		while (guess_again == true && got_it == false && (try_cnt++ <= max_tries))
		{

			std::cout << "please input your num:" << endl;
			std::cin >> usr_guess;
			guess_num++;

			//如果猜正确
			if (usr_guess == (*current_vec)[2]) {

				std::cout << "Your guess is right!"
					<< (*current_vec)[2]
					<< " is the next element in the "
					<< seq_names[seq_index]
					<< " sequence.\n";
				got_it = true;
				guess_right++;
			}
			//用户猜错
			else {
				//判断猜的次数  switch
				switch (try_cnt)
				{
				case(1):
					std::cout << "Oops!Nice guess but not quiye it! \n" << endl;
					break;
				case(2):
					std::cout << "Hmm.Sorry.Wrong a second time.\n" << endl;
					break;
				case(3):
					std::cout << "Ah,this is harder than it looks.\n" << endl;
					break;
				default:
					std::cout << "It must be getting pretty frustrating by now! \n" << endl;
					break;
				}
				//是否再试一次
				std::cout << "Error!Want to try again?(y/n):";
				std::cin >> usr_rsp;
				if (usr_rsp == 'N' || usr_rsp == 'n')
					guess_again = false;
			}
		}//内层循环结束

		std::cout << "want to try another sequence again?(y/n):";
		std::cin >> try_again;
		if (try_again == 'N' || try_again == 'n')
			num_seq = false;

	}//外循环结束
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cqy阳

预祝上岸,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值