Я кодирую программу, которая считывает данные непосредственно из пользовательского ввода, и мне было интересно, как я могу (без циклов) читать все данные до EOF со стандартного ввода. Я рассматривал возможность использования, cin.get( input, '\0' )
но на '\0'
самом деле это не символ EOF, который просто читается до EOF или '\0'
, в зависимости от того, что наступит раньше.
Или использование петель - единственный способ сделать это? Если да, то как лучше всего?
Использование петель:
#include <iostream> using namespace std; ... // numbers int n; while (cin >> n) { ... } // lines string line; while (getline(cin, line)) { ... } // characters char c; while (cin.get(c)) { ... }
ресурс
источник
Вы можете сделать это без явных циклов, используя итераторы потока. Я уверен, что внутри он использует какой-то цикл.
#include <string> #include <iostream> #include <istream> #include <ostream> #include <iterator> int main() { // don't skip the whitespace while reading std::cin >> std::noskipws; // use stream iterators to copy the stream to a string std::istream_iterator<char> it(std::cin); std::istream_iterator<char> end; std::string results(it, end); std::cout << results; }
источник
Изучив использование решения KeithB
std::istream_iterator
, я обнаружилstd:istreambuf_iterator
.Тестовая программа считывает весь ввод по конвейеру в строку, а затем снова записывает ее:
#include <iostream> #include <iterator> #include <string> int main() { std::istreambuf_iterator<char> begin(std::cin), end; std::string s(begin, end); std::cout << s; }
источник
std::istreambuf_iterator
вместоstd::istream_iterator
, но зачем?Вероятно, самый простой и в целом эффективный:
#include <iostream> int main() { std::cout << std::cin.rdbuf(); }
При необходимости используйте поток других типов, например,
std::ostringstream
как буфер вместо стандартного потока вывода.источник
std::ostringstream std_input; std_input << std::cin.rdbuf(); std::string s = std_input.str()
. у вас есть все входные данныеs
(будьте осторожны,std::string
если входные данные слишком велики)Вы можете использовать функцию std :: istream :: getline () (или, желательно, версию, которая работает с std :: string ), чтобы получить всю строку. У обоих есть версии, которые позволяют указать разделитель (символ конца строки). По умолчанию версия строки - '\ n'.
источник
Печальное примечание: я решил использовать C ++ IO, чтобы обеспечить согласованность с кодом на основе ускорения. Из ответов на этот вопрос выбрал
while (std::getline(std::cin, line))
. Используя g ++ версии 4.5.3 (-O3) в cygwin (mintty), я получил пропускную способность 2 МБ / с. Microsoft Visual C ++ 2010 (/ O2) сделала 40 МБ / с для того же кода.После перезаписи ввода-вывода на чистый C
while (fgets(buf, 100, stdin))
пропускная способность подскочила до 90 МБ / с в обоих протестированных компиляторах. Это имеет значение для любого ввода размером более 10 МБ ...источник
std::ios::sync_with_stdio(false);
перед циклом while.cin.tie(NULL);
может также помочь, если вы чередуете чтение и запись.while(std::cin) { // do something }
источник
// do something
он не содержит дополнительных проверок возвращаемых значений операций ввода-вывода, а проверка, которую он содержит, не имеет смысла.Подождите, я правильно вас понял? Вы используете cin для ввода с клавиатуры и хотите прекратить чтение ввода, когда пользователь вводит символ EOF? Зачем пользователю вводить символ EOF? Или вы имели в виду, что хотите прекратить чтение из файла в EOF?
Если вы на самом деле пытаетесь использовать cin для чтения символа EOF, то почему бы просто не указать EOF в качестве разделителя?
// Needed headers: iostream char buffer[256]; cin.get( buffer, '\x1A' );
Если вы хотите прекратить чтение из файла в EOF, просто используйте getline и еще раз укажите EOF в качестве разделителя.
// Needed headers: iostream, string, and fstream string buffer; ifstream fin; fin.open("test.txt"); if(fin.is_open()) { getline(fin,buffer,'\x1A'); fin.close(); }
источник
Один из вариантов - использовать контейнер, например
std::vector<char> data;
и перенаправлять весь ввод в эту коллекцию до тех пор, пока не
EOF
будет получен, т.е.std::copy(std::istream_iterator<char>(std::cin), std::istream_iterator<char>(), std::back_inserter(data));
Однако используемому контейнеру может потребоваться слишком частое перераспределение памяти, иначе вы закончите с
std::bad_alloc
исключением, когда в вашей системе закончится память. Для решения этих проблем вы можете зарезервировать фиксированное количествоN
элементов и обрабатывать это количество элементов изолированно, т.е.data.reserve(N); while (/*some condition is met*/) { std::copy_n(std::istream_iterator<char>(std::cin), N, std::back_inserter(data)); /* process data */ data.clear(); }
источник