字符串的终极调教

字符串的终极调教


情景再现:本人在使用别人开源的一个库进行程序编写时,有一些库里的信息无法通过合适的函数获取,只能通过技术手段强行获取。

下图是开源库的输出示例,虽然只有三行,但是因为数字和逗号紧连着,想把数字剥离出来还是要下一番功夫的。思路是:将其先输出到一个txt文件中,然后再读入,用字符串处理技术将其中的各种信息剥离出来
在这里插入图片描述
第一步,数据输出为txt

gsNURBSinfo(gsMultiPatch<T> const& m_patch,
			gsMultiBasis<T> const& m_basis)
		{
			// 先输出
			std::ofstream out_info("NURBSinfo.txt");
			out_info << m_basis.basis(0);
			out_info.close();
			// 再读入
			getKnotVectorInfo();
		}

这里将输出的程序写在构造函数里了(因为编程需要,此段代码只是从本人项目中冗长的代码中截取的一小段,看官无需考虑这个问题),数据读入为一个单独的函数。

一些本文用到的变量,定义在类里的,也可以不考虑,代码注释中会介绍

public:
		std::string basis_type;	// 基函数的类型
		index_t nurbs_dim; // 基函数的维度,index_t是int的派生,可以看做是int
		index_t	nurbs_node;	// 结点总数
		real_t  tran_number; // 用于数据类型转换的局部变量,real_t是double的派生,可以看做是double
		IGAinfo info_iga;	// 单个节点向量的信息,定义了一个对象
		vector<IGAinfo> igainfo; // 容纳所有的节点向量的容器
		//vector<string> basis_info;

第二步,读入数据,并拆解
首先来解析第一行,“TensorBSplineBasis: dim=2, size=36.”
其中“TensorBSplineBasis:”这一串字符会因项目模型的不同而不同,需要保存下来;
另外注意到“dim=2,”这里的数字“2”后面还有一个“,”,共同构成了一个字符串,需要把数字“2”提取出来;
同样需要提取“size=36.”中的数字“36”。

// 打开刚才输出的txt文件
	std::ifstream info_in("NURBSinfo.txt");
// 设置几个局部变量
	std::string line;
	std::stringstream ss_buff;
	std::string temps;
// 拾取该行字符串数据
	getline(info_in, line);
	ss_buff.str("");
	ss_buff.str(line);
// ===========================================
// 第一行数据
	// std::string basis_type;	// 类中定义的成员变量,原程序中不在此位置
	ss_buff >> basis_type;	// “TensorBSplineBasis:”
// ===========================================
	ss_buff >> temps; // “dim=2,”
	// 获取数值
	std::string dim_str;
	for (auto ce : temps)// 基于范围的for循环,遍历每一个字符
	{
		if (isdigit(ce)) // 如果是数字
		{
			dim_str += ce;// 把数字型的字符保存下来
		}
	}
	// 字符串类型转为数字类型的函数
	nurbs_dim = trans_str_to_any(dim_str);//dim_str是string型,nurbs_dim是int型
// ===========================================
	ss_buff >> temps; // size=36.
	std::string size_str
	for (auto cf : temps)
	{
		if (isdigit(cf))
		{
			size_str += cf;
		}
	}
	nurbs_node = trans_str_to_any(size_str);// size_str是string型,nurbs_node是int型
	ss_buff.clear();
}

在以上的过程中为了将字符串类型的数字转化为数字类型,定义了trans_str_to_any() 函数,函数的实现如下,这里使用的是函数模板,需要返回值是什么类型就可以是什么类型。类型转化主要是通过 stringstream 这个流实现的,真的很好用啊。

template<typename T>
	T gsNURBSinfo<T>::trans_str_to_any(std::string s_str)
	{
		T res;
		std::stringstream Repeater;
		Repeater << s_str;//string型
		Repeater >> res; // 任意T类型,由目标返回值类型决定
		return res;
	}

然后来解析第二行,“ Direction 0: [ 0 0 0 0.25 0.5 0.75 1 1 1 ] (deg=2, size=9, minSpan=0.25, maxSpan=0.25)”
这一行要复杂得多,“[ ]”中的数据量根据模型的不同是变化的。最难的不是获取“[ ]”中的数据,而是获取“minSpan=0.25,”中的“0.25”,试想一下,你会怎么做,这是一个字符串,数字夹在了字符中间,可以使用 isdigit() 函数提取数字,但是“.”不是数字。看我操作

// 获取一行待处理的数据
	getline(info_in, line);
	// 使用关键字判断是不是需要的数据行
	if (line.find("Direction") != std::string::npos)
	{
		ss_buff.str("");
		ss_buff.str(line);
		ss_buff >> temps;	// Direction
		ss_buff >> temps;	//	0:
		info_iga.knot_direction = knot_dir;
		// 提取“[ ]”中的数据
		ss_buff >> temps;	// [
		ss_buff >> temps;	// 0
		std::string judge_symbol("]");
		while(temps != judge_symbol) 
		{ // temps中如果不是"]"就循环
			tran_number = trans_str_to_any(temps); // tran_number是double型
			info_iga.knot_vector.push_back(tran_number);//info_iga.knot_vector是vector型
			ss_buff >> temps;	// 依次是0 0 0.25 0.5 0.75 1 1 1 ]
		}
// =============================================
		ss_buff >> temps; // (deg=2,
		std::string dig_str;
		for (auto ca : temps)
		{	// 提取数字2
			if (isdigit(ca))
			{
				dig_str += ca;
			}
		}
		info_iga.knot_degree = trans_str_to_any(dig_str);// info_iga.knot_degree是int型
// ============================================
		ss_buff >> temps; // size=9,
		std::string siz_str;
		for (auto cb : temps)
		{	// 提取数字9
			if (isdigit(cb))
			{
				siz_str += cb;
			}
		}
		info_iga.knot_size = trans_str_to_any(siz_str);
// ============================================
		ss_buff >> temps; // minSpan=0.25,
		std::string mins_str;	
		for (char cc : temps)
		{	// 提取数字0.25
			if (isdigit(cc) || cc == '.')
			{
				mins_str += cc;
			}
		}
		info_iga.knot_minSpan = trans_str_to_any(mins_str);
// ===========================================
		ss_buff >> temps; // maxSpan=0.25)
		std::string maxs_str;
		for (char cd : temps)
		{	// 提取数字0.25
			if (isdigit(cd) || cd == '.')
			{
				maxs_str += cd;
			}
		}
		info_iga.knot_maxSpan = trans_str_to_any(maxs_str);
// ===========================================
		ss_buff.clear();
		igainfo.push_back(info_iga);
		info_iga.initialize();
		++knot_dir;
	}

第三行和第二行的操作是完全一致的。
可以输出一下结果

// gsInfo是cout的派生
	gsInfo << basis_type << " ";
	gsInfo << "dim=" << nurbs_dim << ", ";
	gsInfo << "size=" << nurbs_node << ".\n";
	for (index_t j = 0; j < igainfo.size(); ++j)
	{
		gsInfo << "  Direction " << j << ": [ ";
		for (index_t k = 0; k < igainfo[j].knot_vector.size(); ++k)
		{
			gsInfo << igainfo[j].knot_vector[k] << " ";
		}
		gsInfo << "] (";
		gsInfo << "deg=" << igainfo[j].knot_degree
			<< ", size=" << igainfo[j].knot_size
			<< ", minSpan=" << igainfo[j].knot_minSpan
			<< ", maxSpan=" << igainfo[j].knot_maxSpan;
		gsInfo << ")\n";
	}

看一下效果
在这里插入图片描述
以下是完整程序,顺序上与前文讲的不太一样。

template 
< class T>
	void gsNURBSinfo<T>::getKnotVectorInfo()
	{
		std::ifstream info_in("NURBSinfo.txt");

		std::string line;
		std::stringstream ss_buff;
		std::string temps;

		index_t knot_dir = 0;

		while (!info_in.eof())
		{
			getline(info_in, line);

			if (line.find("Direction") != std::string::npos)
			{
				ss_buff.str("");
				ss_buff.str(line);

				ss_buff >> temps;	// Direction
				ss_buff >> temps;	//	0:
				info_iga.knot_direction = knot_dir;

				// 节点向量
				ss_buff >> temps;	// [
				ss_buff >> temps;	// 0
				std::string judge_symbol("]");
				while(temps != judge_symbol)
				{
					tran_number = trans_str_to_any(temps);
					info_iga.knot_vector.push_back(tran_number);	//	节点向量
					ss_buff >> temps;	// 0 0 1 1 1 ]
				}
				// =============================================
				ss_buff >> temps; // (deg=2,
				std::string dig_str;
				for (auto ca : temps)
				{
					if (isdigit(ca))
					{
						dig_str += ca;
					}
				}
				info_iga.knot_degree = trans_str_to_any(dig_str);
				// ============================================
				ss_buff >> temps; // size=9,
				std::string siz_str;
				for (auto cb : temps)
				{
					if (isdigit(cb))
					{
						siz_str += cb;
					}
				}
				info_iga.knot_size = trans_str_to_any(siz_str);
				// ============================================
				ss_buff >> temps; // minSpan=0.25
				std::string mins_str;
				//char m_dot('.');	
				for (char cc : temps)
				{
					if (isdigit(cc) || cc == '.')
					{
						mins_str += cc;
					}
				}
				info_iga.knot_minSpan = trans_str_to_any(mins_str);
				// ===========================================
				ss_buff >> temps; // maxSpan=0.25)
				std::string maxs_str;
				for (char cd : temps)
				{
					if (isdigit(cd) || cd == '.')
					{
						maxs_str += cd;
					}
				}
				info_iga.knot_maxSpan = trans_str_to_any(maxs_str);

				ss_buff.clear();

				igainfo.push_back(info_iga);
				info_iga.initialize();
				//igainfo[knot_dir]=(info_iga);
				++knot_dir;
			}

			else if (!line.empty())
			{ // TensorBSplineBasis: dim=2, size=36.
				ss_buff.str("");
				ss_buff.str(line);

				ss_buff >> basis_type;	// TensorBSplineBasis:
				// ===========================================
				ss_buff >> temps; // dim=2,
				// 获取数值
				std::string dim_str;
				for (auto ce : temps)
				{
					if (isdigit(ce)) // 如果是数字
					{
						dim_str += ce;
					}
				}
				nurbs_dim = trans_str_to_any(dim_str);
				// ===========================================
				ss_buff >> temps; // size=4.
				std::string size_str;
				for (auto cf : temps)
				{
					if (isdigit(cf))
					{
						size_str += cf;
					}
				}
				nurbs_node = trans_str_to_any(size_str);

				ss_buff.clear();
			}

		}

		gsInfo << basis_type << " ";
		gsInfo << "dim=" << nurbs_dim << ", ";
		gsInfo << "size=" << nurbs_node << ".\n";

		for (index_t j = 0; j < igainfo.size(); ++j)
		{
			gsInfo << "  Direction " << j << ": [ ";
			for (index_t k = 0; k < igainfo[j].knot_vector.size(); ++k)
			{
				gsInfo << igainfo[j].knot_vector[k] << " ";
			}
			gsInfo << "] (";
			gsInfo << "deg=" << igainfo[j].knot_degree
				<< ", size=" << igainfo[j].knot_size
				<< ", minSpan=" << igainfo[j].knot_minSpan
				<< ", maxSpan=" << igainfo[j].knot_maxSpan;
			gsInfo << ")\n";
		}

	}

	// 字符串转换为数字的函数模板
	template<typename T>
	T gsNURBSinfo<T>::trans_str_to_any(std::string s_str)
	{
		T res;
		std::stringstream Repeater;
		Repeater << s_str;
		Repeater >> res;
		return res;
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值