Есть несколько мест, где ваш код может быть улучшен.Я думаю, что наиболее заметным местом для улучшения является то, что вы пытаетесь сделать слишком много в одной функции.Ваша цель не дублировать код - это хорошо, но модульный подход.Переместите общий код в его собственную функцию, например:
void do_stuff(std::istream & currentStream)
{
std::string myLine;
// go line by line and translate it
while (getline(currentStream, myLine)) {
if (currentStream.eof()) {
break;
}
std::cout << rot13(myLine) << std::endl;
}
}
Эта функция должна содержать все, что совместно используется двумя путями кода.(Я изменил указатель на ссылку, чтобы вызывающие сразу знали, что нулевой указатель недопустим.) Когда вы меняете основную функцию так, чтобы она вызывала эту, вы должны заметить, что некоторые вещи становятся проще.В частности, нет необходимости в динамическом размещении (что не приводит к попытке delete &cin
- что выглядело плохо).Вы можете легко использовать локальную переменную для своего файлового потока.
int main(int argc, const char ** argv)
{
if (argc == 3) {
// Handle optional file input
std::ifstream fileStream(argv[2]);
fileStream.open(argv[2]);
if (fileStream.fail()) {
std::cerr << "FILE COULD NOT BE OPENED\n";
return 1;
}
do_stuff(fileStream);
fileStream.close();
} else {
do_stuff(std::cin);
}
return 0;
}
Перемещая общий код в отдельную функцию, вы получаете возможность остаться в предложении if
.Нет необходимости определять, нужно ли закрывать *currentStream
, так как вы никогда не покидали ветвь кода, создавшую файл.
Есть еще одно место, где вы могли бы упростить вещи.Не звоните open
и close
.Вы используете конструктор ifstream
, который принимает имя файла, поэтому конструктор уже вызывает для вас open
.(Когда вы явно вызываете open
, вы говорите компьютеру закрыть файл и re - открыть его.) Точно так же деструктор вызовет для вас close
;это ключевой момент RAII .
. Избавление от ненужных вызовов оставляет:
int main(int argc, const char ** argv)
{
if (argc == 3) {
// Handle optional file input
std::ifstream fileStream(argv[2]);
if (fileStream.fail()) {
std::cerr << "FILE COULD NOT BE OPENED\n";
return 1;
}
do_stuff(fileStream);
// Keep in mind that, even though there is no C++ code here, there is something
// important being done after the call to do_stuff. Specifically, the destructor
// for fileStream is called, which closes the file for you.
} else {
do_stuff(std::cin);
}
return 0;
}