"code complete (code encyclopedia)" Chapter 18 table-driven method code

 01 Problem description:

02 Notes on the table-driven approach:

The simplest example: the user inputs a number of months and outputs the corresponding number of days.

The simplest approach to this problem is to

if(1月) 31天
if(2月) 28天
if(3月) 31天
if(4月) 30天
if(5月) 31天
if(6月) 30天
if(7月) 31天
if(8月) 31天
if(9月) 30天
if(10月) 31天
if(11月) 30天
if(12月) 31天

Use a one-dimensional array instead of a very long if, which is the table-driven method.

int M = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

cout << M[n-1];

key point

1. Mapping (sometimes the input content does not correspond to the subscript one by one)

2. What is stored in the watch

03 Pseudo-code of table-driven solution to this problem

while (1) 
{
    读一个“浮标ID”

    读表,可查询到该 *浮标ID* 后面跟的字段名称和数据类型

    遍历该条记录的每个字段的格式信息
    {
        (读表,可查询到该 *浮标ID* 后面跟的字段名称和数据类型)

        如果该项是int类型
            读入int
            打印字段名(在表里)
            打印int
        如果该项是string类型
            读入string
            打印字段名(在表里)
            打印string
        如果该项是double类型
            读入double
            打印字段名(在表里)
            打印double
        //... 可继续添加
    }
}

You can use polymorphism to get rid of the above if
 

04 complete code:

# include <iostream>
# include <string>

// 标签种类数最大值
# define MAXMsgKinds 10

// 每条记录的字段数量最大值
# define MAXFIELDS 10

struct EveryField {
	int dataTypeIndex;
	std::string fieldTitle;
};

struct EveryRecord {
	int numFields;
	std::string recordTitle;
	EveryField fields[MAXFIELDS];
};

class CBaseMsg { // Msg改为Field会更恰当
public:
	virtual void inputData(void) = 0;
	virtual void printData(void) = 0;
};

class CIntMsg : public CBaseMsg {
public:
	int data;
	void inputData(void) override { std::cin >> data; }
	void printData(void) override { std::cout << data << std::endl; }
};

class CDoubleMsg : public CBaseMsg {
public:
	double data;
	void inputData(void) override { std::cin >> data; }
	void printData(void) override { std::cout << data << std::endl; }
};

class CStringMsg : public CBaseMsg {
public:
	std::string data;
	void inputData(void) override { std::cin >> data; }
	void printData(void) override { std::cout << data << std::endl; }
};

// 若要添加字段数据类型,如bool,则仅需写一个派生类,然后在程序第81行添加new CBoolMsg即可。

void init(EveryRecord * T)
{
	T[0].numFields = 2;
	T[0].recordTitle = "【个人资料】";
	T[0].fields[0] = { 0, "【幸运数】" }; //int
	T[0].fields[1] = { 2, "【姓名】" }; // string

	T[1].numFields = 3;
	T[1].recordTitle = "【期末成绩】";
	T[1].fields[0] = { 1, "【数学】" }; //double
	T[1].fields[1] = { 1, "【语文】" }; //double
	T[1].fields[2] = { 1, "【外语】" }; //double

	T[2].numFields = 5;
	T[2].recordTitle = "【一天的体温变化】";
	T[2].fields[0] = { 1, "【凌晨】" };		//double
	T[2].fields[1] = { 1, "【清晨】" };		//double
	T[2].fields[2] = { 1, "【正午】" };		//double
	T[2].fields[3] = { 1, "【下午】" };		//double
	T[2].fields[4] = { 1, "【傍晚】" };		//double

	// 若要添加记录类型(原书中的“浮标ID”),则仅需继续写T[3]的内容即可,其余位置不变。
}

int main(void)
{
	EveryRecord T[MAXMsgKinds];// 表驱动法:用一张表来描述每种消息的格式

	init(T); //初始化表

	// 3代表字段的数据类型的数量,本例中,目前添加了3中数据类型,分别是int double string
	CBaseMsg * MsgTypeList[3] = { new CIntMsg , new CDoubleMsg , new CStringMsg };

	int msgTag;
	while (true)
	{
		std::cin >> msgTag;
		std::cout << T[msgTag].recordTitle << std::endl;;
		for (int i = 0; i < T[msgTag].numFields; ++i)
		{
			MsgTypeList[T[msgTag].fields[i].dataTypeIndex]->inputData();
			std::cout << T[msgTag].fields[i].fieldTitle;
			MsgTypeList[T[msgTag].fields[i].dataTypeIndex]->printData();
		}
		std::cout << std::endl;
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45339670/article/details/131620615