Я пишу программу, которая считывает данные непосредственно с пользовательского ввода, и мне стало интересно, как я могу (без циклов) прочитать все данные до EOF со стандартного ввода. Я думал использовать cin.get( input, '\0' )
, но '\0'
- это не совсем символ EOF, который просто читает до EOF или '\0'
, в зависимости от того, что наступит раньше.
Или использование циклов - единственный способ сделать это? Если да, то какой способ лучше?
Единственный способ прочитать переменный объем данных из stdin - это использование циклов. Я всегда находил, что функция std::getline()
работает очень хорошо:
std::string line;
while (std::getline(std::cin, line))
{
std::cout << line << std::endl;
}
По умолчанию getline() читает до новой строки. Вы можете указать альтернативный символ завершения, но EOF сам по себе не является символом, поэтому вы не можете просто сделать один вызов getline().
Вы можете сделать это без явных циклов, используя потоковые итераторы. Я уверен, что он использует какой-то внутренний цикл.
#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;
}
С помощью циклов:
#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))
{
...
}
После исследования KeithB'ы решение с помощью функции std::istream_iterator, я обнаружил СТД: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;
}
Вероятно, самый простой и, как правило, эффективно:
#include <iostream>
int main()
{
std::cout << std::cin.rdbuf();
}
Если необходимо, используйте поток других типов, таких как СТД::ostringstream в качестве буфера вместо стандартного потока вывода здесь.
Печальное примечание: Я решил использовать C++ IO Для быть последовательным с Boost код. От ответа на этот вопрос я выбрал время (с std::getLine метод(с std::Кин, линия))`. С помощью G++ версии 4.5.3 (-О3) в Cygwin (mintty) у меня 2 МБ/с пропускной способности. В Microsoft Visual С++ 2010 (/О2) сделал это 40 Мбит/с на один и тот же код.
После переписывания ИО для чистого c когда (чем fgets(buf с, 100, stdin) программы)
пропускной подскочил до 90 МБ/с в обоих протестированных компиляторов. Это имеет значение для любого входного сигнала больше, чем 10 МБ...
Для получения всей строки можно использовать функцию std::istream::getline() (или, предпочтительно, версию, работающую со std::string). У обеих есть версии, позволяющие указать разделитель (символ конца строки). По умолчанию для строковой версии это '\n'.
Одним из вариантов является использование контейнера, например
std::vector<char> data;
и перенаправление все входящие в эту коллекцию до конца строки, т. е.
std::copy(std::istream_iterator<char>(std::cin),
std::istream_iterator<char>(),
std::back_inserter(data));
Однако, использовать контейнер, возможно, придется слишком часто перераспределять память, или вы будете в конечном с `с std::bad_alloc исключение, когда ваша система получает из памяти. Для того, чтобы решить эти проблемы, вы могли бы резерв фиксированной суммой-Н-элементов и процесс этих элементов в отдельности, т. е.
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();
}
Подожди, я правильно тебя поняла? Вы're, используя Cin для ввода с клавиатуры, и вы хотите прекратить чтение ввода, когда пользователь вводит символ EOF? Почему бы пользователю не введите символ EOF? Или ты имел в виду, вы хотите прекратить чтение из файла в ВФ?
Если вы'вновь действительно пытается использовать Кин читать Символ EOF, то почему бы просто не указать ВФ в качестве разделителя?
// Needed headers: iostream
char buffer[256];
cin.get( buffer, '\x1A' );
Если вы хотите прекратить чтение из файла на 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();
}
while(std::cin) {
// do something
}