创作一个sequence类

参考:《数据结构与面向对象程序设计》(C++版)Michael Main等编著

sequence类与bag类不一样,bag类删除一个元素可以直接将最后一个元素取代即可,但是在sequence中,删除一个元素需要保持原来的顺序,所以需要将删除的元素后面的每一个元素向前挪动一个位置,并且 used-1.

sequence1.h:

#ifndef MAIN_SAVITCH_SEQUENCE_H
#define MAIN_SAVITCH_SEQUENCE_H
#include <cstdlib> //提供size_t

namespace main_savitch_3
{
	class sequence
	{
	public:
		typedef double value_type;
		typedef std::size_t size_type;
		static const size_type CAPACITY = 30;
		sequence();
		void start();
		void advance();
		void insert(const value_type& entry);
		void attach(const value_type& entry);
		size_type index() { return current_index; }
		//删除当前数据项,索引是current_index
		void remove_current();
		//删除特定元素
		void remove_target(const value_type& target);
		size_type size() const;
		bool is_item() const;
		value_type current() const;
	private:
		value_type data[CAPACITY];
		size_type used;
		size_type current_index;
	};
}
#endif 

sequence.cpp:

#include "sequence1.h"
#include <iostream>
#include <cassert>
using namespace std;
namespace main_savitch_3
{
	//构造函数
	sequence::sequence()
	{
		used = 0;
		current_index = 0;
	}
	//start()函数将当前项置为0
	void sequence::start()
	{
		current_index = 0;
	} 
	//每执行一次advance当前项向前移动一位
	void sequence::advance()
	{
		++current_index;
	}
	//判断当前项是否有效,也就是是否超过used,注意current_index从0~used-1
	bool sequence::is_item() const
	{
		//注意current_index从0~used-1,所以为used也是超出了
		if (current_index >= used)
			return false;
		return true;
	}
	//返回当前项的元素
	sequence::value_type sequence::current()const
	{
		assert(is_item());
		return data[current_index];
	}
	//移除当前项,然后保持sequence,也就是后面序列全部往前挪动一位
	void sequence::remove_current()
	{
		for (size_type i = 0; i <used; ++i)
		{
			//开始寻找和当前项一样的下表
			if (i == current_index)
			{
				//然后从当前项开始,将下一项的呢内容复制给前一项,但是这里注意,这里没有销毁used-1那一项
				for (size_type j = current_index; j < used-1; ++j)
					data[j] = data[j + 1];
				data[used - 1] = NULL;//将used-1项元素置为0
				--used;
				break;
			}
		}
	}
	//插入操作
	void sequence::insert(const value_type& entry)
	{
		assert(size()< CAPACITY);
		data[used++] = entry;//将其插入之后data[used]再自增
	}
	void sequence::attach(const value_type& entry)
	{
		/*...*/
	}
	sequence::size_type sequence::size() const
	{
		return used;
	}
	//删除特定的元素
	void sequence::remove_target(const value_type& target)
	{
		for (size_type i = 0; i < used; ++i)
		{
			if (data[i] == target)
			{
				for (size_type j = i; j < used - 1; ++j)
				{
					data[j] = data[j + 1];
				}
				--used;
				break;
			}				
		}
	}
}

sequence_demo.cpp 

#include <iostream>
#include <cctype> //提供toupper
#include <cstdlib>//提供EXIT_SUCESS
#include "sequence1.h"
using namespace std;
using namespace main_savitch_3;

void get_numbers(sequence& numbers);
void show_numbers(sequence& numbers);
int main()
{
	//定义numbers为sequence类
	sequence numbers;
	//执行start()
	numbers.start();
	//输入数据
	get_numbers(numbers);
	cout <<"输出 used 的大小:"<< numbers.size()<< endl;
	cout << "输出当前项current_index的大小:" << numbers.index() << endl << endl;;
	numbers.advance();
	cout << "执行一次advance之后current_index的大小: " << numbers.index()<< endl;
	numbers.remove_current();
	cout << "删除了当前项之后后used的大小:" << numbers.size() << endl<<endl;
	//删除元素12
	cout << "尝试删除元素为15的元素" << endl;
	numbers.remove_target(15);
	cout << "删除一个元素之后used的大小:" <<numbers.size()<< endl<<endl;
	//输出操作之后的结果
	cout << "输出操作后sequence的结果" << endl;
	show_numbers(numbers);
	system("pause");
}
void get_numbers(sequence& numbers)
{
	//
	sequence::value_type input_number;
	cout << "请输入一组有序的数,以-1结束:" << endl;
	cin >> input_number;
	//以输入的数据作为判断依据,那么在循环里面必然出现再次输入
	while (input_number>=0)
	{
		//判断当前的已用空间是否达到CAPACITY
		if (numbers.size() < numbers.CAPACITY)
			//插入元素
			numbers.insert(input_number);
		else
			cout << "哦,满了,容量满了!" << endl;
		cin >> input_number;//再次输入
	}
}
void show_numbers(sequence& numbers)
{
	for (numbers.start(); numbers.is_item(); numbers.advance())
	{
		cout << numbers.current() <<" ";
	}
	cout << endl;
}

测试结果:

 

很明显,只是用main函数来测试会很容易打乱代码的逻辑,下面写一个程序交互测试代码

程序交互测试.cpp

#include<iostream>
#include<cctype> //提供toupper
#include<cstdlib>//提供EXIT_SUCESS
#include "sequence1.h"

using namespace std;
using namespace main_savitch_3;

void print_menu();
char get_user_command();
void show_sequence(sequence diaplay);
double get_number();

int main()
{
	sequence test;
	char choice;
	cout << "I have initialized an empty sequence of real numbers" << endl;
	do
	{
		print_menu();
		choice = toupper(get_user_command());
		switch(choice)
		{
		case '!':test.start();
			break;
		case '+':test.advance();
			break;
		case '?':if (test.is_item())
			cout << "There is an item." << endl;
				 else
			cout << "There is no current item." << endl;
			break;
		case 'C':if (test.is_item())
			cout << "Current item is : " << test.current() << endl;
				 else
			cout << "There is no current item." << endl;
			break;
		case 'P':show_sequence(test);
			break;
		case 'S':cout << "Size is " << test.size() << '.'<<endl;
			break;
		case 'I':test.insert(get_number());
			break;
		case 'A':test.attach(get_number());
			break;
		case 'R':test.remove_current();
			cout << "The current item has been remove" << endl;
			break;
		case 'Q':cout << "Ridicule is the best test of the truth." << endl;
			break;
		default:cout << choice << " is invalid" << endl;
		}
	} 
	while (choice != 'Q');
	return EXIT_SUCCESS;
}
void print_menu()
{
	cout << endl;
	cout << "The following choices are available:" << endl;
	cout << " ! Activate the start() function" << endl;
	cout << " + Activate the advance() function" << endl;
	cout << " ? Print the result from the is_item() function<<endl"<<endl;
	cout << " C Print The result from the current() function" << endl;
	cout << " P Print a copy of the entire sequence" << endl;
	cout << " S Print the result from the size() function" << endl;
	cout << " I Insert a new number with the insert(...) function" << endl;
	cout << " A Attach a new number with the attach(...) function" << endl;
	cout << " R Activate the remove_current() function" << endl;
	cout << " Q Quit this test program" << endl;
}
char get_user_command()
{
	char command;

	cout << "Enter choice:";
	cin >> command;

	return command;
}
void show_sequence(sequence display)
{
	for (display.start(); display.is_item(); display.advance())
		cout << display.current() << endl;
}
double get_number()
{
	double result;
	cout << "Please enter a real number for the sequence:";
	cin >> result;
	cout << result << " has been read." << endl;
	return result;
}

提醒:

1、这里可以注意一下 toupper这个函数,它是<cctype>库中的一部分,目的是将小写转换成大写,所以对应地应该还有tolower() 将字母转换成小写

2、可以看到这个测试代码中输出show_sequence(display)没有使用引用传递,是因为使用引用传递会改变参数值,这是我们不希望看出现的。值传递会隐含一次复制操作,所以在时间上和空间上会消耗大一些

 测试结果:

参考:《数据结构与面向对象程序设计》(C++版)Michael Main等编著 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值