C++学习与实践(二):vector类型与iterator迭代器

前言


这周基本在看项目代码及其中的类图关系,都还过的去。继续补上之前的基础,相当于再次复习。

vector类型


简单来说,vector类型类似于C语言的数组类型,表示一段连续的内存区域,每个元素被顺序存储在该段内存中。随机访问效率高。
vector类型两种习惯用法:数组习惯(与C数组用法一致,略)和STL习惯

知识点

  • 不能像数组一样显示初始化,但可以将其初始化为一个已有数组的全部或部分;
<span style="font-family:SimSun;font-size:18px;">int ia[6] = {-2, -1, 0, 1, 2, 1024};			 // 正确

vector <int> ivec(ia, ia+6);                     // 正确
vector <int> ivec(6) = {-2, -1, 0, 1, 2, 1024};  // 错误</span>
  • vector与string一样,同类型可以相互赋值;
<span style="font-family:SimSun;font-size:18px;">vector <string> user_names(svec); 
// ...(user_names初始化)
vector <string> svec = user_names; </span>

STL习惯


定义一个空vector,再向其中插入元素,而不再仅仅是索引元素,以及向元素赋值。
  • 数组用法与STL用法不要混用
<span style="font-family:SimSun;font-size:18px;">vector< int > ivec;
ivec[0] = 1024;  // 错误,ivec为空,并没分配内存,因此还没有元素,不能索引并赋值。</span>
  • 任何一个插入操作都是增加vector的大小,而不是覆盖某个现有元素
  • STL习惯用法下,vector的一个或多个元素可以被删除;

容量与长度


容量是指在容器下一次需要增长自己之前能够被加入到容器的元素总个数,调用capacity()获得;长度是指容器当前拥有的个数,调用size()获得。

简单来说,vector实际分配的容量(即内存空间)比当前所需的空间(即长度)要多,而多的确切大小由具体实现定义。在标准库的Rogue Wave实现版本下,第一次分配的元素缺省容量接近或等于1024字节,然后它随每次重分配而加倍。另外,可以通过resize()重置容器长度

iterator迭代器


iterator提供一种一般化方法,对顺序或关联容器类型中的每个元素进行连续访问。移动iterator就是移动指向元素的指针。
每种容器提供的begin()和end()成员函数,均返回一个指向第一个或者末位元素的iterator。

知识点

  • iterator的定义语法略长;
<span style="font-family:SimSun;font-size:18px;">vector <Context>::iterator iter = Ctx.begin();
// iterator是vector类中定义的typedef。vector <Context>::iterator引用了vector。
// 容器类型还定义const iterator类型,它允许只读方式访问容器的底层元素,用于遍历const容器。</span>
  • iterator同指针一样,可以通过算术移位,适用于vector或deque,而不适用于List;
<span style="font-family:SimSun;font-size:18px;"> vector <Context>::iterator iter = Ctx.begin() + Ctx.size()/2; // 移植指向中间元素</span>

初始化

  • 用“一对iterator标记的起始元素和末元素后一位置之间的拷贝”;
<span style="font-family:SimSun;font-size:18px;">vector<string> svec; 
// ...(svec初始化) 
// 用svec的全部元素初始化svec2 
vector<string> svec2(svec.begin(), svec.end());</span>
  • 用“数组的首元素指针和末元素后一位置的指针”;
<span style="font-family:SimSun;font-size:18px;">string words[4] = {"stately", "plump", "buck", "mulligan"};
vector <string> vwords(words, words+4); </span>
  • 特定的istream_iterator类型,可直接插入文本元素(需要增加#include <iterator>头文件);
<span style="font-family:SimSun;font-size:18px;">istream_iterator<string> infile( cin );   // 将输入流iterator绑定到标准输入上
istream_iterator<string> eos;             // 标记流结束位置的输入流iterator
vector<string> svec( infile, eos );       // 利用通过cin输入的值初始化svec</span>

实例


酒桌上的酒令游戏,如下:
1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。
2. 让所有人按次序报数。
3. 报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Cute(萌);如果所报数字是第二个特殊数(5)的倍数,那么要说Da(哒);如果报数字是第三个特殊数(7)的倍数,那么要说Evil(坏)。
4. 报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说CuteDa, 以此类推。如果同时是三个特殊数的倍数,那么要说CuteDaEvil。
5. 报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Cute。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Cute,不报CuteDa。

现在,我们需要你完成一个程序来模拟这个游戏,(可以模拟输入一个数,返回所报内容)并考虑规则的扩展性,编程语言不限。

实现

<span style="font-family:SimSun;font-size:18px;">// test.cpp
#include <assert.h>
#include <string>
using namespace std;

extern void CtxInit();
extern string Game(const int data);

void Test_Rule_1()
{
	assert("Cute" == Game(3));
	assert("Cute" == Game(66));

	assert("Da" == Game(5));
	assert("Da" == Game(200));

	assert("Evil" == Game(7));
	assert("Evil" == Game(707));
}

void Test_Rule_2()
{
	assert("CuteDa" == Game(15));
	assert("CuteDa" == Game(45));

	assert("DaEvil" == Game(70));
	assert("DaEvil" == Game(140));

	assert("CuteEvil" == Game(21));
	assert("CuteEvil" == Game(42));
}

void Test_Rule_3()
{
	assert("CuteDaEvil" == Game(105));
	assert("CuteDaEvil" == Game(210));
}

void Test_Rule_4()
{
	assert("Cute" == Game(35));
	assert("Cute" == Game(53));
	assert("Cute" == Game(375));
}

void main()
{
	CtxInit();

	Test_Rule_1();
	Test_Rule_2();
	Test_Rule_3();
	Test_Rule_4();

	getchar();
}</span>
<span style="font-family:SimSun;font-size:18px;">// game.cpp
#include <string>
#include <vector>
using namespace std;

typedef struct Special_Words 
{
	int spcial_num;
	string words;
} Context;

vector <Context> Ctx;

void CtxInit()
{
	Context First = {3, "Cute"};
	Ctx.push_back(First);

	Context Second = {5, "Da"};
	Ctx.push_back(Second);

	Context Third = {7, "Evil"};
	Ctx.push_back(Third);
}

string Game(int data)
{
	string result;
	int temp = data;
	
	do
	{
		int first_num = temp % 10;
		if (first_num == Ctx.begin()->spcial_num)
		{
			result = Ctx.begin()->words;
			return result;
		}

		temp = temp / 10;
	} while (temp != 0);

	for (vector <Context>::iterator iter = Ctx.begin();
		 iter != Ctx.end(); ++iter)
	{
		if (0 == data % iter->spcial_num)
		{
			result += iter->words;
		}
	}

	return result;
}</span>

总结


改下《慢慢》这首歌的歌词,“慢慢慢慢有了感觉,慢慢慢慢我没忽略...”做这道练习,测例在我对实现代码进行重构,整理思路时起了很大作用,自我感觉良好了很多。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值