С помощью пациента Дэвиса я узнал разницу между печатным вводом, завершенным с помощью Ctrl + D , и документом, о котором я не знал.(Моя дань уважения Дэвису Херрингу.)
Однажды я получил его, остальное в C ++ было довольно простым, как показано в моем MCVE .
line-count.cc
:
#include <fstream>
#include <iostream>
#include <string>
unsigned process(const std::string &fileName, std::istream &in)
{
unsigned nLines = 0;
if (in.bad()) {
std::cerr << "ERROR: Cannot open '" << fileName << "'!\n";
return 0;
}
for (std::string buffer; std::getline(in, buffer); ++nLines);
std::cout << "File: '" << fileName << "', " << nLines << " counted.\n";
return nLines;
}
int main(int argc, char **argv)
{
unsigned nLines = 0;
for (int i = 1; i < argc; ++i) {
const std::string arg = argv[i];
if (arg == "-") {
nLines += process(arg, std::cin);
std::cin.clear();
} else {
std::ifstream fIn(arg.c_str());
nLines += process(arg, fIn);
}
}
std::cout << "Total: " << nLines << " counted.\n";
return 0;
}
Скомпилировано и протестировано в cygwin64 :
$ g++ -std=c++11 -o line-count line-count.cc
$ ./line-count line-count.cc - line-count.cc -
File: 'line-count.cc', 32 counted.
1
2
3
File: '-', 3 counted.
File: 'line-count.cc', 32 counted.
1
2
3
File: '-', 3 counted.
Total: 70 counted.
$
Итак, это действительно трюк с std::cin.clear()
, который сбрасывает флаг EOF ввходной поток и делает возможным повторное чтение с /dev/stdin
.
. В случае OP, std::cin.ignore()
после std::cin.clear()
ИМХО неверно.Он отбрасывает первый символ вновь включенного стандартного ввода, что делает следующую обработку неправильной (не считая первого символа).
Дэвис (снова) дал краткое, но очевидное объяснение, которое я даю своими словами:
При Ctrl D стандартный вход получает EOF при следующей попытке чтения;и запоминает его во внутренних флагах.Тем не менее, флаг можно сбросить.Если больше нет ввода, следующая попытка чтения потерпит неудачу, но в противном случае ввод можно просто продолжить.
Может быть, стоит подчеркнуть внутренний флаг EOF в std::ios
.Без std::cin.clear()
попытка чтения потерпит неудачу, даже если будет доступно больше ввода.Пока внутренние std::stream
флаги не приводят к хорошему состоянию, попытка чтения не будет выполняться на более низком уровне, даже если это может быть успешным.