2013-06-17 4 views
1

저는 이전 (Conditionally Breaking A Long Sequence Of Inputs?)에서 진화 한 질문을 가지고 있지만, 지금까지 아무도 저에게 만족스러운 대답을 줄 수 없었으며, 모든 노력은 실패했습니다.문자를 기반으로 사용자 입력을 초기에 중단 할 수 없습니까?

필자는 사용자가 입력 할 필요가 없으면 일찍 깨뜨릴 수 있도록 노력하고 있습니다. 즉, 아래 코드의 경우 :

cout << '\n' << "Monster A's name is: "; 
cin >> nameA; 
cout << '\n' << "Monster A rolled: "; 
cin >> rollM_A; 
cout << '\n' << "Monster A's Dex is: "; 
cin >> DexA; 
cout << '\n' << "Monster A's Mod is: "; 
cin >> ModA; 
cout << '\n' << "Monster A's Level is: "; 
cin >> LvlA; 

//etc. 

최대 12 개의 몬스터가 실제로 지원됩니다. 사용자가 3-4 개 정도만 사용하려는 경우 나머지를 건너 뛰고 많은 키 입력을 저장할 수 있기를 바랍니다. 나는 이미 모든 변수를 0으로 초기화하고 나중에 저장소 벡터에서 0 요소를 제거하는 기능을 가지고 있습니다. 빠진 것이 입력 체인에서 멀어지고 있습니다. 나는 다음과 같이 while 루프 포장의 다양한 형태를 시도 :

while(cin.get() != '#') { 
    cout << '\n' << "Monster A's name is: "; 
    cin >> nameA; 
    //etc... 
} 

그러나 원하는 문자를 입력시

이 코드는 단순히 출력 모든 프롬프트 ("괴물의 이름입니다"등)을 통해 이상 계속 진행하거나 추가 입력을 허용하지 않습니다. # 입력에 루프를 남겨 두어야 할지라도 코드가 무한 루프에 갇혀있는 것처럼 보입니다.

아이디어가 있으십니까? 누군가가 대체 솔루션을 제공 할 수 있다면 적어도 한동안이 문제에 매달려 있었고, 적어도 내 자신의 결함을 알려주는 것이 매우 감사 할 것입니다.

감사합니다.

답변

2

std :: cin 연산자 >>가 "End of line"문자 (Enter 키)를 사용하지 않으므로 코드 조각이 무한 루프를 유발하므로 여전히 스트림에 있습니다.

그래서 두 번째로 cin.get()에 도착하면 여전히 버퍼에 문자가 있습니다 (괴물의 이름을 확인할 때부터 입력). cin.get()은 그것을 취하고, '#'이 아닌지 확인하고, 같은 작업을하는 다음 std :: cin으로 이동합니다.

while(cin.get() != '#') 
{ 
    cout << '\n' << "Monster A's name is: "; 
    cin >> nameA; 
    //etc... 
    cin.ignore(); 
} 
+0

이것은 나를 위해 작동하지 않았다. 불행히도 그 행동은 동일합니다. –

+0

부속 : 대신이 목적을 위해 cin.clear()를 사용하면 흥미로운 행동을 보일 수 있습니다! 끝없이 스크롤하는 대신 목록이 한 번 스크롤되어 #로 깨진 위치로 돌아가고 중지됩니다. 이것은 나를 음모합니다. 내가 지금 가까이있는 것 같아. –

+0

알았습니다! cin.clear()와 cin.ignore()가 함께 작동 한 것 같습니다! 유일한 문제는 (매우 코스메틱 한) 캐릭터가 스킵하기 위해 두 번 입력되어야한다는 것입니다. 프롬프트를 통해 사용자에게 알려주도록해야합니다. 여기 도착에 도움 주셔서 감사합니다! : D –

-1

정보를 제공 할 수 있습니까? '#을 눌러이 질문을 무시하십시오'? 사용자가 어떤 키를 건너 뛸 것인지 추측하게하는 대신?

+0

OP 질문에 전혀 답하지 못합니다. –

+0

일단 작동 시키면 그럴 수 있습니다. 나는 하나만 건너 뛰고 싶지는 않지만 입력 목록 전체를 건너 뛰고 싶다. –

0

방금이 코드 세트를 테스트했으며 원하는대로 작동하는 것으로 보입니다. 물론 원래 응용 프로그램에 맞게 수정해야합니다.

오히려 while 루프로 전달 true 매개 변수를 갖는 것보다, 괴물의 개수의 한계를 반영하기 위해
std::string in; 

while (true) { 
    std::cout << "Enter a name\n"; 
    std::cin >> in; 
    if (in == "#") 
     break; 
    std::cout << "\nMonster A's name is: " << in << "\n"; 
} 

간단히 만들어 얼마나 많은 몬스터 카운터를 추가 한 것을 조건으로 중단 :

int num_monsters = 0; 
while (num_monsters <= 12) { 
    ... 
    num_monsters++; 
} 

희망이 도움이됩니다.

+0

나는 당신의 접근 방식을 수정하려고 노력할 것이다. 그러나 최소한의 선을 선호합니다. 제 생각에 if 문을 사용하면 모든 괴물 이름에 대해 하나의 문이 필요할 것입니다. 나는 당신의 세고 제안에 대해 조금 혼란스러워합니다. 내가 일찍 떠나려고하면 괴물의 수가 12가되지 않을 것이고 루프가 끝나지 않을 것입니다. –

+0

@Rome_Leader 카운터의 목표는 "최대 12 개의 몬스터가 지원됩니다"라는 귀하의 의견을 언급하는 것입니다. 내가 제공 한 코드에 카운터를 추가하지 않으면 사용자가'# '을 입력 할 때까지 계속됩니다. 즉, 사용자는 12 개 이상의 몬스터를 제공 할 수 있습니다. 카운터가 포함되어 있고 사용자가 '#'을 입력하면 루프가 계속 중단됩니다. 또한 if 문 사용에 대한 귀하의 우려에 대해 혼란 스럽습니다. 당신이 정교 할 수 있니? –

+0

글쎄, 지금은 문제를 해결했지만, 당신의 요점을 참조하십시오. 그것은 괴물 이름에 대해 별도의 변수 이름을 사용하는 원래 코드와 루프를 압축하는 여러분의 차이점을 기반으로했습니다. 문제 없다! –

0

객체 지향 및 구조에 다음 stdlib : 당신은 문자 무시함으로써이 문제를 해결할 수

#include <iostream> 
#include <string> 
#include <vector> 

using namespace std; 

class Monster { 
    string name; 
    int rolled, dex, mod, level; 

    template<class input, class output, class container> 
    friend input& read_monster(input& i, output& o, container &c) { 
     string n; 
     o << "\nMonster's name is: " << flush; 
     i >> n; 
     if(!i || (n == "#")) { 
     o << "\nEnd of monster list"; 
     i.setstate(ios::failbit); 
     return i; 
     } 
     Monster m; 
     m.name = n; 
     o << "\nMonster's rolled is " << flush; 
     i >> m.rolled; 
     if(!i) return i; 
     o << "\nMonster's dex is " << flush; 
     i >> m.dex; 
     if(!i) return i; 
     o << "\nMonster's mod is " << flush; 
     i >> m.mod; 
     if(!i) return i; 
     o << "\nMonster's level is " << flush; 
     i >> m.level; 
     if(!i) return i; 
     o << "\n"; 
     c.push_back(m); 
     return i; 
    } 

    template<class output> 
    friend output& operator<<(output& o, Monster&m) { 
     return o << "Monster('" << m.name <<"', R/" << m.rolled 
     << ", D/" << m.dex << ", M/" << m.mod << ", L/" << m.level 
     << ")\n"; 
    } 

    Monster() : name(), rolled(), dex(), mod(), level() {} 
}; 

int main(int, char**) { 
    vector<Monster> v; 
    while(read_monster(cin, cout, v) && (v.size() <= 12)) 
    ; 

    for(auto m: v) 
    cout << m; 
    return 0; 
} 
+0

와우, 그건 꽤 복잡해. 모든 노력과 노력에 감사드립니다. 물론 클래스와 벡터를 선언해야합니다. 나는 그런 광범위한 재 작성을 선호한다. –

+0

안녕하세요. 어쨌든 위의'템플릿 <클래스 입력, 클래스 출력, 클래스 컨테이너> input & read_monster (input & i, output & o, container & c)'는 거의 변경되지 않을 것입니다 (대부분 WRT 클래스 Monster와 속성 이름) 내 손님이 되라. – Massa

0

것은 당신이 라인 중심의 입력을하고있는 이후를, 당신은 정말 가 std::getline를 이용해야한다 읽다. 그리고 라인 지향적 입력 인 은 각각 객체를 정의하는 라인 블록으로 구성되어 있으므로 클래스를 생성하고 읽어야합니다. (또한 중간 선의 오류를 처리해야하므로 오류 처리가 더 많이 필요합니다.

std::string 
getLineFromPrompt(std::string const& prompt) 
{ 
    std::string results; 
    std::cout << prompt; 
    std::getline(std::cin, results); 
    return results; 
} 

template <typename T> 
bool 
tryGetValueFromPrompt(std::string const& prompt, T& value) 
{ 
    std::string line = getLineFromPrompt(prompt); 
    std::istringstream parser(line); 
    return parser >> value >> std::ws && parser.get() == EOF; 
} 

template <typename T> 
void 
getValueFromPrompt(std::string const& prompt, T& value) 
{ 
    while (! tryGetValueFromPrompt(prompt, value)) { 
     std::cout << "Illegal input, try again" << std::endl; 
    } 
} 

class Monster 
{ 
    std::string name; 
    int roll; 
    int dexterity; 
    int mod; 
    int level; 
public: 
    Monster(std::string const& name) 
     : name(name) 
    { 
     getValueFromPromt(name + " rolled:", roll); 
     getValueFromPromt(name + " dexterity:", dexterity); 
     getValueFromPromt(name + " mod:", mod); 
     getValueFromPromt(name + " level:", level); 
    } 
}; 

bool 
isEndFlag(std::string const& line) 
{ 
    return line.empty() || line[0] == '#'; 
} 

그리고 마지막으로, 루프 :

std::vector <Monster> monsters; 
std::string nextName = getLineFromPrompt(); 
while (! isEndFlag(nextName)) { 
    monsters.push_back(Monster(nextName)); 
    nextName = getLineFromPrompt(); 
} 

당신이 참조 각각의 우려를 감안 바와 같이)

물론, 이러한 우려 각각 에 별도의 기능을 분리해야 에 별도의 함수를 사용하면 훨씬 간단한 코드가 생성됩니다.

관련 문제