如果没有选项,标准习语是:
int returnCode = 0;
void
processFile( std::string const& filename )
{
if ( filename == "-" ) {
process( std::cin );
} else {
std::ifstream in( filename.c_str() );
if ( !in.is_open() ) {
std::cerr << argv[0] << ": cannot open " << filename << std::endl;
returnCode = 1;
} else {
process( in );
}
}
}
int
main( int argc, char** argv )
{
if ( argc == 1 ) {
processFile( "-" );
} else {
for ( int i = 1; i != argc; ++ i ) {
processFile( argv[i] );
}
}
std::cout.flush()
return std::cout ? returnCode : 2;
}
但是,有许多变体。我发现自己这样做
我经常写一个MultiFileInputStream 类
(template> 构造函数接受一对迭代器;然后
执行或多或少与上面相同的代码。 (全部
像往常一样,重要的代码在相应的流缓冲区中。)
同样,我有一个类来解析选项(看起来
就像一个不可变的 std::vector<std::string> 一旦选项
已被解析。所以上面会变成:
int
main( int argc, char** argv )
{
CommandLine& args = CommandLine::instance();
args.parse( argc, argv );
MultiFileInputStream src( args.begin(), args.end() );
process( src );
return ProgramStatus::instance().returnCode();
}
(ProgramStatus 是另一个有用的类,它处理错误
输出和返回码。并刷新std::cout 和
调用returnCode()时调整错误代码。)
我确信任何编写 Unix 过滤器程序的人都开发了
类似的类。
关于问题 2:sync_with_stdio 是静态的
std::ios_base 的成员,所以你可以在没有对象的情况下调用它:
std::ios_base::sync_with_stdio( false );。我觉得这个少
误导,因为调用会影响 所有 iostream 对象。
如果 IO 处理是一个阻塞点,一定要这样做,但是
大多数时候,我不打扰。这样的节目很少见
需要任何类型的优化。 (请注意,如果您调用
sync_with_stdio,那么你应该不使用任何 C 风格的 IO。
但我看不出有任何理由使用它。)
关于问题3:错误信息转到std::cerr,
总是。您还希望确保返回非零回报
代码,即使错误不是致命的。比如:
myprog file1 > tmp && mv tmp file1
都是常见的,如果你有问题,不要
生成输出,如果您不返回,那将是一场灾难
非零错误代码。 (这就是为什么我总是冲洗然后
检查std::cout 的状态。很久很久以前,一个用户
我的程序执行了上述操作,文件非常大,并且
磁盘已满。后来就没有那么满了。自那以后:
总是刷新std::cout,并检查它是否工作,之前
返回OK。)