- 1、指针
- 2、案例更新
本文开始涉及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对象(代表六个数列):
vectorfibonacci,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;
这种方式可以依次指向数列的vector,比较繁琐,会牺牲程序的透明性。那么,另一种方案就是将每个数列的内存地址存入vector中,我们可以通过索引的方式,透明访问这些数列:
const int seq_cnt=6; //定义指针数组,长度为6 //每个指针都指向vector对象 vector *seq_addrs[seq_cnt]={ &fibonacci,&Lucas,&Pell, &Triangular,&Square,&Pentagonal; }
其中,seq_addrs表示array,元素类型为vector
vector*current_vec=0; for(int i=0;i current_vec=seq_addrs[i];//所有要显示的元素通过current_vec访问 }
最后,主要解决顺序问题。之前用户总是依据fibonacci,Lucas,Pell,Triangular,Square,Pentagonal的顺序进行猜测。我们希望数列随机出现,这里用到了C语言标准库中的rand()和srand()函数:
#includesrand(seq_cnt);//srand()的参数是随机数生成器的种子 seq_index=rand()%seq_cnt;//rand()会返回“0-int所能表示最大数”的一个整数,我们的索引在0-5之间,索引采用取余的方式。 current_vec=seq_addrs[seq_index]; }
两个函数必须使用cstdlib头文件
2、案例更新下面就是依据上一篇文章进行改进的代码:
#include#include #include #include 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 fibonacci(elem_seq, elem_seq + 3); vector lucas(elem_seq+3, elem_seq + 6); vector pell(elem_seq+6, elem_seq + 9); vector Triangular(elem_seq+9, elem_seq + 12); vector Square(elem_seq+12, elem_seq + 15); vector 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 *seq_addrs[max_seq] = { &fibonacci,&lucas,&pell,&Triangular,&Square,&Pentagonal }; vector *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; }



