Читает набор строк от пользователя


Я пытаюсь написать программу, которая будет считывать коллекцию строк от пользователя, а затем заканчивается в момент, когда он сталкивается с ".". Тогда я пишу вообще-в то время как петли.

Я наткнулся на что-то вроде этого:

string temp;
vector<string> params;
do
{
    cin >> temp;
    if (temp == ".")
        break;

    params.push_back(temp);

} while (temp != ".");

Я понял, что несмотря ни на что, цикл всегда завершается изнутри его тело, которое является точной результат, который хотят.

Но там что-то про кусок кода, который пахнет рыбой. Существуют ли более эффективные способы?

Другая вещь, чтобы отметить: я не хочу "." чтобы быть продвинутым на вектор, следовательно, поэтому я добавил, что мало , если (температура == ".") перерыв; заявление.



1122
22
c++
задан 4 мая 2011 в 12:05 Источник Поделиться
Комментарии
5 ответов

Не забудьте проверить состояние потока ошибок или EOF.

while (cin >> temp && temp != ".")
{
params.push_back(temp);
}


Редактировать: вы не обязательно должны придумать свои условия останова. Есть уже один — конец файла. Вы можете просто читать строки, пока вы не достигнете его. Таким образом, ваша программа будет работать с не-интерактивные входное красиво. Для создания конечного файла на терминал нажмите Ctrl+D на базе UNIX/Linux и сочетание клавиш ctrl+z для ОС Windows.

while (cin >> temp)
{
params.push_back(temp);
}

28
ответ дан 4 мая 2011 в 07:05 Источник Поделиться

Я предпочитаю:

cin >> temp;
while (temp != ".")
{
params.push_back(temp);
cin >> temp;
}

19
ответ дан 4 мая 2011 в 12:05 Источник Поделиться

string temp;
vector<string> params;
while (true)
{
cin >> temp;
if (temp == ".")
break;

params.push_back(temp);

}

Этот тест - правда в моем случае, темп != "." в вашей, никогда не запускается, кроме случаев, когда это правда. Так что это может быть правдой.

8
ответ дан 4 мая 2011 в 01:05 Источник Поделиться

Я предпочитаю строить какую-то инфраструктуру, что будут делать остальные тривиальный код. Инфраструктура может быть немного больше работы, но в долгосрочной перспективе экономия может быть существенной. В этом случае она принимает форму специальный итератор, который позволяет указать "Сентинел", который положит конец ввода. Он действует как обычный istream_iterator, за исключением того, что вы укажите дозорного значение при построении "конец диапазона" итератор.

// sentinel_iterator.h
#pragma once
#if !defined(SENTINEL_ITERATOR_H_)
#define SENTINEL_ITERATOR_H_
#include <istream>
#include <iterator>

template <class T,
class charT=char,
class traits=std::char_traits<charT>,
class distance = ptrdiff_t>

class sentinel_iterator :
public std::iterator<std::input_iterator_tag,distance,void,void,void>
{
std::basic_istream<charT,traits> *is;
T value;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_istream<charT,traits> istream_type;

sentinel_iterator(istream_type& s)
: is(&s)
{ s >> value; }

sentinel_iterator(T const &s) : is(0), value(s) { }

const T &operator*() const { return value; }
const T *operator->() const { return &value; }

sentinel_iterator &operator++() {
(*is)>>value;
return *this;
}

sentinel_iterator &operator++(int) {
sentinel_iterator tmp = *this;
(*is)>>value;
return (tmp);
}

bool operator==(sentinel_iterator<T,charT,traits,distance> const &x) {
return value == x.value;
}

bool operator!=(sentinel_iterator<T,charT,traits,distance> const &x) {
return !(value == x.value);
}
};

#endif

С этим в месте, считывание данных становится тривиальной:

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include "sentinel_iterator.h"

int main() {
// As per spec, read until a "." is entered:
std::vector<std::string> strings(
sentinel_iterator<std::string>(std::cin),
sentinel_iterator<std::string>("."));

// It's not restricted to strings either. Read numbers until -1 is entered:
std::vector<int> numbers(
sentinel_iterator<int>(std::cin),
sentinel_iterator<int>(-1));

// show the strings:
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));

// show the numbers:
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
return 0;
}

Получив на входе:

This is a string .
1 2 3 5 -1

Он производит вывод:

This
is
a
string
1
2
3
5

Он должен работать, по существу, любого типа, который определяет поток Extractor и проверки на равенство (т. е., говоря: х==г будет собирать и приносить значимые результаты).

4
ответ дан 5 мая 2011 в 03:05 Источник Поделиться

Если мы не говорим о языке-конкретные детали, то я бы предпочел что-то вроде этого:

// this is inspired by LINQ and C#
var params = Enumerable.Generate<string>(() => {string temp; cin >> temp; return temp; })
.TakeWhile(s => s != ".")
.ToVector();

Где Перечислимым.Создать () - некоторая лямда, которая считывает данные из Кин. Как правило, отвечая на вопрос 'как использовать перерывы?' Я думаю, что перерывы не должны быть использованы, по крайней мере, не в таких тривиальных сценариев.

3
ответ дан 4 мая 2011 в 11:05 Источник Поделиться