数值的格式化是指数值格式在数值的内部表述和文本表述之间进行转化。IOstream操作符将实际转换工作委托给locale::numeric类型中的诸多刻面完成。通常是由以下3个刻面组成的。
1)numpunct。该刻面用于处理数值格式化及数值解析相关的标点符号。
2)num_put。该刻面用于处理数值格式化。
3)num_get。该刻面用于处理数值解析。
下面详细讲述“以num_put进行数值格式化”和“以num_get进行相应字符串解析”的相关知识。numpunct刻面提供了stream接口未能直接支持的部分灵活性。
1.数值点符号
numpunct刻面用于控制小数点、可有可无的千位分隔符和布尔值的文本表示符号。其成员见表12-19。
表12-19 numpunct刻面的成员
numpunct刻面是以字符型别charT作为模板参数的。decimal_point()和thousands_sep()返回的字符型别均是charT;truename()和falsename()返回一个basic_string<charT>。C++标准要求刻面numpunct<char>和numpunct<char_t>的具体实例化必须存在。
如果没有分隔符,长数字很难阅读。数值格式化和数值解析的标准刻面也要支持千位分隔符。通常情况下,阿拉伯数字是3个一组,组与组之间用逗号分隔。
例如,我们通常将“一百万”写作1,000,000。
但世界上很多地区不会这样写。例如,在德国不使用逗号(,),而是使用“点”号(.)。例如,“一百万”在德国写作1.000.000。而且在有些国家,数字不是以3个一组的方式分组的。例如,“一百万”在尼泊尔写作10.00.000
每组阿拉伯数字的个数均不尽相同。差异是必须由thousands_sep()决定的。函数grouping()返回的字符串即在此处。索引i处的数值代表第i组的数字个数;从右边数起,索引计数从0开始。若字符中的字符数量少于每个群组中的字符数量,最后确定的那组字符的数量将重复。若需要创造无限大组,应当使用numeric_limit<char>::max()的返回值。若不分组,则会给出一个空字符串。详见表12-20。
表12-20 一百万的各种表示方法(www.xing528.com)
如果直接使用数字可能是不正确的。例如,字符串“2”指定的是一个50个阿拉伯数字的数字分组,因为在ASCII编码中,字符“2”即是整数50。
2.数值的格式化
num_put刻面用于对数值的“表述文本”进行格式化。它是一个模板类,包含两个模板参数:字符型别charT和output迭代器型别OutIt。产生的字符会写入迭代器中所指的位置。output迭代器的默认型别是ostreambuf_iterator<charT>。num_put刻面提供多参数的put()函数,期间只有最后一个参数是不同的。可以使用的刻面主要包括以下一些:
上述语句是利用型别为charT的字符,在output迭代器to所指位置处填写value的文本表述式。确切格式由fmt的格式化标识确认。fill被用于作为填充字符,put()函数返回一个迭代器。该迭代器指向最后一个被写出的字符的下一位置。
num_put刻面提供一系列成员函数,分别接受型别为bool、long、unsigned long、double、long double及void∗的对象作为最后一个参数。short和int等内建型别的数值可以自动晋升为相应型别,即没有提供针对short和int的成员函数。
C++标准要求每个类locale内必须有numput<char>和numput<wchar_ t>两个具体实例化对象。另外,C++标准程序库还支持具备以下特性的所有实例化对象:以字符型别作为第一个模板参数;以输出型迭代器型别作为第二个模板参数。标准规格不要求每个lo-cale均储存具体的实例化对象,会导致无穷的刻面。
3.数值解析
num_get刻面用于解析数值的文本表述。与num_put刻面相比,num_get()刻面具有两个模板参数:字符型别charT和输入型迭代器型别InIt。num_get()刻面提供一系列的get()函数,期间只有最后一个参数是不同的。数值的格式多数是由fmt确定的。如果失败,err会被设置为ios_base::failbit;反之,err会被设置为ios_base::goodbit。所有数值将被放入value中。value的原有数值在解析后才被修改。若全部字符序列解析完毕,get()函数会返回第二个参数;若全部字符序列无法解析完毕,则会返回一个迭代器,指向“无法被解析为数值的那一部分”的第一个字符。
num_get刻面支持“用于读取型别为bool、long、unsignedshort、unsigned int、unsigned long,float、double、long double和void∗等对象”的函数。某些型别在num_put中没有对应的函数,写一个unsigned short值和写一个unsigned int值需要提升转型为unsigned long是相同的。读取一个unsignedlong型别的值再将其转换为unsigned short型别,和直接读取unsigned short的结果是不相同的。
C++标准要求每个类locale必须有num_get<char>和num_get<wchar_t>两个具体实例化对象。C++标准程序库还支持具备以下特性的所有实例化对象:以字符型别作为第一个模板参数,以输入型迭代器型别作为第二个模板参数。与num_put刻面相同,不是所有被支持的具体实例化对象均必须储存在locale对象中。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。