08-修改实现
10.2.5 修改实现
在前面的程序输出中,可能有一个方面让您恼火——数字的格式不一致。现在可以改进实现,但保持接口不变。ostream类包含一些可用于控制格式的成员函数。这里不做太详细的探索,只需像在程序清单8.8那样使用方法setf(),便可避免科学计数法:
std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
这设置了cout对象的一个标记,命令cout使用定点表示法。同样,下面的语句导致cout在使用定点表示法时,显示三位小数:
std::cout.precision(3);
第17章将介绍这方面的更多细节。
可在方法show()中使用这些工具来控制格式,但还有一点需要考虑。修改方法的实现时,不应影响客户程序的其他部分。上述格式修改将一直有效,直到您再次修改,因此它们可能影响客户程序中的后续输出。因此,show()应重置格式信息,使其恢复到自己被调用前的状态。为此,可以像程序清单8.8那样,使用返回的值:
std::streamsize prec =
std::cout.precision(3); // save preceding value for precision
...
std::cout.precision(prec); // reset to old value
// store original flags
std::ios_base::fmtflags orig = std::cout.setf(std::ios_base::fixed);
...
// reset to stored values
std::cout.setf(orig, std::ios_base::floatfield);
您可能还记得,fmtflags是在ios_base类中定义的一种类型,而ios_base类又是在名称空间std中定义的,因此orig的类型名非常长。其次,orig存储了所有的标记,而重置语句使用这些信息来重置floatfield,而floatfield包含定点表示法标记和科学表示法标记。最后,请不要过多考虑这里的细节。这里的要旨是,将修改限定在实现文件中,以免影响程序的其他方面。
根据上面的介绍,可在实现文件中将方法show()的定义修改成如下所示:
void Stock::show()
{
using std::cout;
using std::ios_base;
// set format to #.###
ios_base::fmtflags orig =
cout.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = cout.precision(3);
cout << "Company: " << company
<< " Shares: " << shares << ‘\n’;
cout << " Share Price: $" << share_val;
// set format to #.##
cout.precision(2);
cout << " Total Worth: $" << total_val << ‘\n’;
// restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
完成上述修改后(保留头文件和客户文件不变),可重新编译该程序。该程序的输出将类似于下面这样:
Company: NanoSmart Shares: 20
Share Price: $12.500 Total Worth: $250.00
Company: NanoSmart Shares: 35
Share Price: $18.125 Total Worth: $634.38
You can’t sell more than you have! Transaction is aborted.
Company: NanoSmart Shares: 35
Share Price: $18.125 Total Worth: $634.38
Company: NanoSmart Shares: 300035
Share Price: $40.125 Total Worth: $12038904.38
Company: NanoSmart Shares: 35
Share Price: $0.125 Total Worth: $4.38