2010-09-26 2 views
10

У меня есть функция, которая читает ввод пользователя из std :: cin, и я хочу написать unittest, который вставляет некоторые строки в std :: cin, так что последующее извлечение из std :: cin будет прочитайте эту строку вместо паузы для ввода с клавиатуры.Ввод строки в 'cin'

В идеале я бы изменил подпись функции, чтобы передать пользовательский istream в качестве параметров, но я не могу этого сделать, поскольку у меня есть фиксированный интерфейс, который я не могу изменить.

cin.putback() is почти то, что я хотел, однако он вставляет только один символ за раз, и он вставляет их в обратном порядке (но я где-то читал, что отбрасывал символ, который не был первоначально может быть опасно, хотя на сайте не выясняется, почему). Я попробовал несколько методов, чтобы ввести строку в внутренний буфер cin cin.rdbuf(), но никто не будет работать. Я также рассмотрел возможность использования внешнего сценария тестирования или создания подпроцесса, однако я бы хотел сначала рассмотреть тест в чистом C++.

Итак, есть ли способ поместить строки в цин? Или вы знаете, как лучше ввести «поддельный ввод с клавиатуры»?

ответ

8

Если вы действительно, действительно хотите использовать зЬй :: CIN, попробуйте следующее:

int main() { 
    using namespace std; 
    streambuf *backup; 
    istringstream oss("testdata"); 
    backup = cin.rdbuf(); 
    cin.rdbuf(oss.rdbuf()); 
    string str; 
    cin >> str; 
    cout << "read " << str;  
} 

Вы можете восстановить streambuf STD :: CIN, когда вы сделали из резервной копии. Я не гарантирую его переносимость: P

+0

+1. или 'stringbuf sb (" testdata "); streambuf * backup = cin.rdbuf (&sb); 'Это совместимый и разумно переносимый, но не очень хороший способ. О да, и ему, возможно, придется делать' cin.clear() ', чтобы избежать условия EOF после того, как вход закончился : vP. – Potatoswatter

+0

+1 именно то, что я просил (я все еще лично задаюсь вопросом, не делает ли что-то подобное это хорошая идея, даже для кода тестирования whitebox). –

13

Вместо того, чтобы завинчиваться с помощью cin, вы можете иметь свою программу для принятия общей std::istream&. При нормальной работе просто передайте его cin. Во время модульного теста передайте ему поток ввода-вывода вашего собственного создания.

+2

Это решение действительно замечательно. Вы можете передать открытый файл через 'ifstream', если вы хотите передать файл в качестве тестового ввода, или вы можете просто передать' istringstream', если хотите просто передать строку в качестве тестового ввода. – RPGillespie

0

cin.butback() гарантированно работает не более одного символа, поэтому вы не можете поместить всю строку. Используйте поток, который обертывает cin и позволяет произвольную длину последовательности putback(). Я думаю, что Boost.Iostream имеет нечто подобное, и если это не так, может оказаться полезным реализовать такую ​​оболочку.

Смежные вопросы