⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 doc2view.cpp

📁 树状显示SIGACT 理论计算机科学家谱系图.析取数据源并建立合适结构.
💻 CPP
字号:
// Read the TCS Genealogical Database file and display its tree structure
// using indentation, with names ordered by Ph.D. date.
#include <algorithm>
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <map>
#include <set>
#include "earlier.h"
using namespace std;

typedef string Name;
typedef string Year;
typedef string Place;
typedef map<string, string> PropertyMap;
typedef multiset<string, earlier> DateOrderedMset;
typedef map<string, DateOrderedMset> AcademicRelation;
typedef DateOrderedMset::iterator IterMset;
typedef AcademicRelation::iterator IterRel;

// 进入界面
void welcome()
{
	cout << "************ 树状显示SIGACT 理论计算机科学家谱系图*************\n";
}


// 获取数据源文件句柄放于ifs参数
void getDataSource(ifstream& ifs)
{
	// 源数据文件名称
	string file_name;
	// 输入文件名称
	cout << "请输入包含族谱数据的文件名称: " ;
	cin >> file_name;
	// 打开文件
	ifs.open(file_name.c_str());
	// 如果打开失败,报告异常,退出
	if (!ifs.is_open()) 
	{
		cout << "异常:文件"<< file_name << "没有找到 " 
			<< endl;
		exit(1);
	}
}

// 构造数据关系模型
void modelView(AcademicRelation& advisors, 
			   AcademicRelation& students,
			   ifstream& ifs)
{
	string name, advisor, place, year;
	// 析取数据源并建立合适结构
	while(ifs)
		// 如果未到文件末尾
	{
		// 忽略注释
		if (ifs.peek() == '#')
		{
			getline(ifs,name,'\n');
			continue;
		}
		// 逐行读取4个域
		getline(ifs, name, '\t');
		getline(ifs, advisor, '\t');
		getline(ifs, place, '\t');
		getline(ifs, year ,'\n');
			// 一行结束,间隔符为换行符
		// 构造博士毕业时间、地点属性结构
		earlier::placeProp[name] = place;
		earlier::dateProp[name] = year;
		// 不确定的导师信息统一用"---"表示
		if (advisor == "?")
			advisor = "---";
		// 构造导师--学生关系结构
		students[advisor].insert(name);
		advisors[name].insert(advisor);
	}
	// 关闭源数据文件
	ifs.close();
}

// 构造族谱森林的根节点集合
// 没有导师信息的科学家为根节点
DateOrderedMset& setupRootSet( AcademicRelation& advisors, 
							   AcademicRelation& students)
{
	// 初始化根节点集合为导师信息为"---"的学生
	DateOrderedMset& roots = students["---"];
	// 定义遍历导师映射的迭代器
	IterRel iter_rel;
	// 定义遍历各个学生对应导师集合的迭代器
	IterMset iter_set; 
	// 是否存在导师信息?
	bool existAdvisor;
	// 遍历导师映射
	for (iter_rel = advisors.begin(); iter_rel != advisors.end(); ++iter_rel) 
	{
		existAdvisor = false;
		// 当前学生的导师集合容器开始迭代器
		IterMset iter_set_b = iter_rel->second.begin(); 
		// 当前学生的导师集合容器结束迭代器
		IterMset iter_set_e = iter_rel->second.end(); 
		for (iter_set = iter_set_b; iter_set != iter_set_e; ++iter_set)
		{
			// 如果该学生的导师为---(未知),则初始化时已经在根集合中
			// 如果该学生的导师在数据库中查找出来,则该学生肯定不属于根集合
			// 以上两种情况下,将existAdvisor设为true,不予后续处理
			if (*iter_set == string("---") || 
				advisors.find(*iter_set) != advisors.end())
				existAdvisor = true;
		}
		// 如果不存在导师(信息)
		if (!existAdvisor) 
		{
			string first_advisor = *(iter_rel->second.begin());
			// 检查它是否已经存在于根集合中:
			//   因为multiset roots是依据name的日期属性排序
			//   因此这个find操作是线性时间复杂度
			//   对于当前问题规模,这不是一个麻烦 
			if ( find(roots.begin(), roots.end(), first_advisor)
				 == roots.end())
			roots.insert(first_advisor);
				// 如果不在根集合中,则插入根集合
		}
	}
	return roots;
}

// 打印以root_name为根的学术树
// 以合适的缩进格式表示师承关系
// 显示他(她)的所有后代师承
// 递归调用
void tree_view(const string& root_name, 
			   AcademicRelation& students,
			   PropertyMap& placeProp, 
			   PropertyMap& dateProp,
			   ostream& out,
			   int indentation_level = 0)
{
	// 根据缩进层次显示合适的行缩进量
	for (int k = 0; k != indentation_level; ++k)
		out << "      ";
	// 打印学生的博士学位信息
	// 格式如: Brian Kernighan (Princeton 1969)
	out << root_name << " (" << placeProp[root_name] << " " 
		<< dateProp[root_name]<< ")" << endl;
	DateOrderedMset& L = students[root_name];
	DateOrderedMset::const_iterator j;
	// 打印该科学家的所有学生信息
	// 遍历他的整个学生集合
	// 按照日期顺序,并增加一层缩进
	for (j = L.begin(); j != L.end(); ++j)
		// 递归调用
		tree_view (*j, students, placeProp, dateProp, out,
					indentation_level+1);
}

// 显示根节点集合代表的各棵树
void forest_view(const DateOrderedMset& roots,
				 AcademicRelation& students)
{
	DateOrderedMset::const_iterator iter;
	//遍历根节点集合,输出各个根对应树
	cout << "请选择输出SIGACT 理论计算机科学家谱系图" << endl
		<< "1. 输出到屏幕\n" << "2. 输出到文件\n"
		<< "请输入1或2选择:";
	int selector;
	cin >> selector;
	if (selector == 1)
		// 输出到屏幕
		for (iter = roots.begin(); iter != roots.end(); ++iter)	
		{
			tree_view(*iter, students, earlier::placeProp, earlier::dateProp, cout);
			system("pause");
			cout << endl;
		}
	else
		//输出到文件
	{
		cout << "请给出输出文件名" << endl;
		string viewName;
		cin >> viewName;
		ofstream ofs(viewName.c_str());
		cout << "文件创建中..." << endl;
		for (iter = roots.begin(); iter != roots.end(); ++iter)
			// 输出到文件
			tree_view(*iter, students, earlier::placeProp, earlier::dateProp, ofs);
		// 关闭文件
		ofs.close();
		cout << "文件创建成功!" << endl;
	}	
}


int main()
{
	// 程序进入界面,说明程序功能
	welcome();
	// 获取数据源文件句柄
	ifstream ifs;
	getDataSource(ifs);	 
	// 定义师生关系映射变量
	AcademicRelation advisors, students;
	// 从数据源构建各科学家关系和属性
	modelView(advisors,students,ifs);
	// 初始化根节点集合为导师信息为"---"的学生
	DateOrderedMset roots = setupRootSet(advisors,students);
	// 显示整个结果集合
	forest_view(roots,students);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -