新手C ++程序员在这里。我正在尝试编写一个命令行应用程序,它接受两个参数,一个输入文件和一个输出文件。但是,如果输入文件或输出文件名是“ - ”,我需要程序读取/输出到标准输入/输出。我的问题是在C ++中,我不知道如何在没有编译器不知道输入/输出流被初始化的情况下如何做到这一点。这是我的代码。
if(argv[1] == "-") {
istream input;
cout << "Using standard input" << endl;
}
else {
ifstream input;
cout << "Using input file " << argv[1] << endl;
input.open(argv[1], ios::in);
if(!input) {
cerr << "Cannot open input file '" << argv[1]
<< "', it either does not exist or is not readable." << endl;
return 0;
}
}
if(argv[2] == "-") {
ostream output;
cout << "Using standard output" << endl;
}
else {
ofstream output;
cout << "Using output file " << argv[2] << endl;
output.open(argv[2], ios::out);
if(!output) {
cerr << "Cannot open output file '" << argv[2] << "' for writing."
<< " Is it read only?" << endl;
return 0;
}
}
从这里我不能打电话给运营商&gt;&gt;在输入上,因为,我猜,编译器不知道它已被初始化。
答案 0 :(得分:5)
您可以将引用用于流,然后将其初始化以引用文件流或标准输入或输出。但是,初始化必须在单个命令中进行,因此即使您不使用它们,也必须声明文件流。
ifstream file_input;
istream& input = (strcmp(argv[1], "-") == 0) ? cin : file_input;
ofstream file_output;
ostream& output = (strcmp(argv[2], "-") == 0) ? cout : file_output;
请注意&
和input
声明中的output
。它们表明我们没有声明一个单独的流对象,而只是声明一个引用到一些其他流对象,我们根据argv[x]
的值有条件地选择它。
然后,如果需要,您可以打开文件。缺点是我们需要检查两次“ - ”字符串而不是每次输入或输出一次。
if (strcmp(argv[1], "-") == 0) {
cout << "Using standard input" << endl;
} else {
cout << "Using input file " << argv[1] << endl;
file_input.open(argv[1]);
if (!file_input) {
cerr << "Cannot open input file '" << argv[1]
<< "', it either does not exist or is not readable." << endl;
return 1;
}
}
此后,您可以从input
读取并写入output
,然后将使用文件或标准I / O流。
请注意我对您的代码所做的其他更改。首先,我致电strcmp
而不是使用==
运营商;在将char*
与文字进行比较时,操作员不会按照您的想法执行操作。接下来,当打开文件失败时,我返回1而不是0.零表示成功的程序,而非零表示操作系统程序失败。
答案 1 :(得分:1)
您可以在条件之外声明成员,因为ifstream
继承istream
而ofstream
继承ostream
。要避免切片,请使用指针:
istream* input = NULL;
bool isFile = false;
if(argv[1] == "-") {
input = new istream;
}
else {
input = new ifstream;
isfile = true;
}
然后,只要您想使用input
,只需将其转换为正确的类型:
if (isFile)
{
ifstream* finput = (ifstream*)input;
}
这不是唯一的解决方案;可能有更干净的
问题是,你必须在条件内部声明块之外的流,因此它不会超出范围,因为你想在外面使用它。