65.9K
CodeProject 正在变化。 阅读更多。
Home

经纬度字符串解析器和格式化器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (11投票s)

2006年9月21日

4分钟阅读

viewsIcon

84520

downloadIcon

1345

一个用于经纬度值的类,可以将字符串解析为双精度数,或者将双精度数格式化为字符串。

Sample Image - llstr.gif

引言

CLongLatString 类用于解析经度或纬度的多种表示形式,将其转换为 double 类型,或者将表示地理坐标的 double 类型格式化为美观的地理坐标字符串。

背景

地球被划分为经纬度地理网格线。经度测量从英国格林威治向东和向西的角度距离。纬度测量从赤道向北和向南的角度距离。等经度线在两极汇聚,而等纬度线是环绕地球的平行线。这只是众多地理坐标系统中的一种,但它是迄今为止最通用和最被理解的系统。

这些坐标通常以半球(N、S、E、W)、度、分和秒来表示。有些人使用十进制度,度分,或度分秒的组合。有些人用正负号代替半球(东为正)。此外,许多分隔符和放置方式使格式更加复杂,有些省略了分隔符,通常最后一项是小数,而前面的项是整数,有些则将所有数据连在一起以节省空间,而半球项可以位于坐标中的任何位置。

各种地理坐标格式的一些示例

	45:26:46N,     65:56:55W
	45:26:46.302N, 65:56:55.903W
	45°26’21"N,    65°58’36"W
	45N26 21,      65W58 36
	45.446195N,    65.948862W
	45.446195,     -65.948862
	N45° 26.7717’, W65° 56.93172’

使用代码

我认为,这个类具有相当强大的自动解析数据并提取数值的能力。例如,这允许您为每个地理坐标提供一个编辑框,而不是一个用于半球的组合框和单独的度、分、秒输入字段。

CLongLatString 类处理这些各种经纬度格式,以便可以轻松地处理和转换为双精度值,用于其他地理方法。该对象为每个值维护一个双精度数和一个字符串。保留字符串是因为有时需要保留原始数据,以保持精度。您可以像使用 printf 风格的值(例如 `%C, %c, %H %h %D, %d, %M, %m, %S, and %s` 作为参数)将 CTimetime_t 格式化一样,从双精度数输出字符串值。

CLongLatString 不处理成对的坐标 - 每个对象最好单独处理一个值,以指示它是经度还是纬度。因此,如果您使用纯双精度数初始化数据,则还必须指明该值是经度还是纬度,才能获得有意义的结果。

有大量的构造函数和一个复制构造函数。您可以根据需要使用字符串或双精度数进行初始化。还有转换运算符和赋值运算符,因此您可以轻松地转换为双精度数或标准字符串。

	CLongLatString llstrLat1("45N54.2356");
	CLongLatString llstrLat2("-45.98739874", LL_LATITUDE);
	CLongLatString llstrLat5(-45.98739874, LL_LATITUDE);
	CLongLatString llstrLat7("N", "45", "34", "33");
	CLongLatString llstrLat8("N455698735", "HDDMMmmmmm");

如果您要使用双精度数或包含文本双精度数的字符串的赋值运算符,则必须初始化该对象以告知它是经度还是纬度。

	CLongLatString llstrLat(LL_LATITUDE);
	llstrLat = -5.877789;
	std::string str = llstrLat.Format("%Dd%M\’%S\"%H");
	cout << str.c_str() << endl;
	// Output -    5d52’40"S
	llstrLat = -5.997789;	// Can be reused - still a latitude
	str = llstrLat.Format("%Dd%M\’%S\"%H");
	cout << str.c_str() << endl;

或者一个更复杂的例子

	std::string str = llstrLat.Format("%H%02D %.5m");
	// Output -    S05 52.66734

输出格式

	%H - hemisphere - single character of N,S,E,W
	%C - integer co-ordinate, may be negative or positive
	%c - decimal co-ordinate, the entire co-ordinate, 
             may be negative or positive
	%D - integer degrees, always positive
	%M - integer degrees, always positive
	%S - integer seconds, always positive, rounded
	%d - decimal degrees, always positive
	%m - decimal minutes, always positive
	%s - decimal seconds, always positive
	%% - for %

可以使用标准的 printf 格式,例如 %03D 为整数度创建带有前导零的三位空间,或者 %.5m 将小数分钟写出五位。大写标识符使用与十进制(整数)格式相同的 printf 标识符,而小写标识符使用浮点格式。所有其他标志都将起作用,因为整个子字符串将传递给 snprintf C 函数。

有用于整数形式和十进制形式的每个项的整数 Get...() 方法。如果您需要为每个项单独提取字符串形式,可以重用 Format() 方法。

例如

	CLongLatString llstrLat(-5.9879875, LL_LATITUDE);
	std::string strHemi = llstrLat.Format("%H");
	std::string strDeg = llstrLat.Format("%02D");
	std::string strMin = llstrLat.Format("%02M");
	std::string strSec = llstrLat.Format("%05.2s");

输入格式

输入格式有所不同,只能用于固定长度的情况(例如,"HDD MM.mmmmm" 用于 "N45 04.25764"),并且仅在格式非常混乱且连在一起时使用。对于大多数情况,度、分、秒由任何空格或大多数分隔符分隔,未指定的默认输入格式应该有效。 H 表示半球的位置,大写字母表示小数点左边的数字部分,小写字母表示小数点右边的数字。

例如

	std::string strInputFormat = "HDDMMmmmmm";
	CLongLatString llstrLat1("N650490807", strInputFormat);
	CLongLatString llstrLat2;
	llstrLat2.Set("N450490807", strInputFormat);
	llstrLat2.Set("N45°04.0807\’");
        // No input format needed if there are enough delimiters

一个注意事项 - 不要将指数表示法输入字符串 - 它会将 "E" 误解为 East(东)并损坏结果。务必在使用 atof() 对参数进行转换后再将其传递给构造函数或 Set 方法。

这就讲完了。您可以查看头文件中提供的方法,其中也重复了一些格式规范,这些方法都附带一行注释说明。如果存在任何科学准确性问题或严重错误,请告诉我。

© . All rights reserved.