2014-11-26 1 views
1

제 과제물로, 사용자 로그인 정보를 저장하고 있습니다. 나는 명령 인 문자열을 가져 가고있다. 명령은 생성, 로그인, 제거 등이 될 수 있습니다. 총 10 개의 옵션, 즉 10 개의 다른 문자열이 가능합니다. 누구든지 10 개의 if 및 else if 문 대신에 이것을 작성하는보다 효율적인 방법을 설명 할 수 있습니까? 기본적으로 if (string == "one"), else if (string == "two")의 묶음을 사용하는 것 이외에는 어떻게 포맷/구조화해야합니까? 고마워요C++ 적은 조건문을 사용하는 방법?

+0

이 아마도 당신이'의미 ==를'. 당신은 룩업 테이블을 만들 수 있습니다. 그러나 10 개의 서로 다른 코드가 있다면 10 개의 코드를 작성할 수있는 방법이 없습니다! –

+0

그래서 문자열이 "create", "clear", "login"등이 될 수 있다면 각기 다른 조건문을 사용해야합니까? – Steven

+1

예 또는 테이블에 저장해야합니다. –

답변

0

아마도 std::map<std::string, int>을 만들고지도 조회를 사용하여 전달 된 명령의 코드를 얻을 수 있습니다. 나중에 해당 번호로 전환 할 수 있습니다. 또는 enum Command을 만들고 std::map<std::string, Command>을 가지고 스위치를 사용하십시오.

예 :

enum Command 
{ 
    CREATE, 
    LOGIN, 
    ... 
}; 

std::map<std::string, Command> commandNameToCode; 
// fill the map with appropriate values 
commandNameToCode["create"] = Command::CREATE; 

// somehow get command name from user and store in the below variable (not shown)  
std::string input; 

// check if the command is in the map and if so, act accordingly 
if(commandNameToCode.find(input) != commandNameToCode.end()) 
{ 
    switch(commandNameToCode[input]) 
    { 
    case CREATE: 
     // handle create 
     break; 
    ... 
    } 
} 
1

당신은 당신을위한 비교를 수행지도를 사용할 수 있습니다. 이 같은

뭔가 :

초기화지도 :

map.at(rx.msg_type)(rx.msg_data); 

처리기 :

,536

std::map<std::string, std::function<void(std::string&)>> map; 
map["login"] = std::bind(&Class::DoLogin, this, std::placeholders::_1); 
map["create"] = std::bind(&Class::DoCreate, this, std::placeholders::_1); 

메시지를 수신 당신이 클래스를 CreateAction 내부에 여전히해야 할 명령하는 결정하는 조건문이 필요합니다,

string action; 
command = CreateAction(action); 
command.Do(...); 

당연히 :

void Class::DoLogin(const std::string& data) 
{ 
    // do login 
} 
+1

ITT'std :: placesholders' –

+0

하하, 네, 그들은 장소를 잡아 먹습니다! Erm, typo :) –

1

나는 당신의 강사가 다른 재사용 가능한 기능에 기능을 추출하려는 것으로 기대 만들어진.

AbstractCommand CreateAction(action) 
{ 
    if (action == "login") 
     return LoginCommand(); 
    else if (action == "remove") 
     return RemoveCommand(); 
    ..... etc etc 
} 

그리고 당신은 정말 당신이 어떤자가 등록 명령을 만들 수있는 것보다 모든 조건문을 제거하려는하지만

당신이 보일 것입니다 ...... 더 많은 코드와 클래스를 포함하는 경우 Command PatternFactory Pattern

+0

관련 디자인 패턴을 가리키는 데 좋은 대답입니다. –

1

같은 기능을하는 포인터 및 찾아보기 테이블을 사용할 수 있습니다.

typedef void (*Function_Pointer)(void); 
void Create(void); 
void Login(void); 
void Remove(void); 

struct Function_Option_Entry 
{ 
    const char * option_text; 
    Function_Pointer p_function; 
}; 

Function_Option_Entry option_table[] = 
{ 
    {"one", Create}, 
    {"two", Login}, 
    {"three", Remove}, 
}; 
const unsigned int option_table_size = 
    sizeof(option_table)/sizeof(option_table[0]); 

//... 
std::string option_text; 
//... 
for (i = 0; i < option_table_size; ++i) 
{ 
    if (option_text == option_table[i].option_text) 
    { 
    option_table[i].p_function(); 
    break; 
    } 
} 
1

간단한 해시 기능과 switch을 사용하십시오.
C 및 C++는 정수 값만 전환 할 수 있기 때문에 해시 함수를 사용해야합니다.

template<size_t N> constexpr char myhash(const char &x[N]) { return x[0]^(x[1]+63); } 
char myhash(const string& x) { return x.size() ? x[0]^(x[1]+63) : 0; } 

switch(myhash(s)) { 
case myhash("one"): 
    if(s != "one") goto nomatch; 
    // do things 
    break; 
case myhash("two"): 
    if(s != "two") goto nomatch; 
    // do things 
    break; 
default: 
nomatch: 
    // No match 
} 

std::string을 사용하지 않는 경우 약간의 조정이 필요합니다.

+0

멋진 해시 아이디어, +1,'goto'가 C/C++에서 금지되어야합니다. 현재 코드에서는 괜찮지 만 사용자의 악용은 악몽을 만듭니다. – vsoftco

+0

@vsoftco : 고마워. 나는 그 일에 맞는 도구를 사용하기 위해 캠프에 단단히 노력하고있다. 비록 그것이 두려운'goto' 일지라도. Djikstra가 구조화 된 프로그래밍 (아무것도 * * * goto)을 사용하여 시작했을 때 유명 기사를 썼음을 항상 기억하십시오. (그렇습니다. 즉, 조금 과장된 표현을 사용했음을 의미합니다. , 많이는 아니지만). – Deduplicator

+0

좋은 생각이지만 해시 함수는 하나의 기호 만 포함하는 문자열로 작동합니까? – antonpp

1

모든 특정 문자열에 대해 함수를 만드는 것이 좋습니다. 예를 들어 문자열 "create"를 수신하면 함수 "doCreate()"를 호출하고 "login"문자열을 수신하면 함수를 호출합니다. doLogin()

이 함수에 대한 유일한 제한은 모두 같은 서명을 가졌어.

typedef void (*func_t)(); 

아이디어는 이러한 기능에 문자열에서 표준 : :지도를 만드는 것입니다 : 예에서는이 같은 SMH이었다 위. 따라서 특정 문자열 이름의 이름으로 맵에서 올바른 함수를 간단하게 선택할 수 있기 때문에 10을 작성하지 않아도됩니다. 나에게 작은 예를의 방법으로 그것을 설명하자`=`보다는 내가 그것을 어떻게든지에 도움이 될 것입니다 희망

typedef void (*func_t)(); 
void doCreate() 
{ 
    std::cout << "Create function called!\n"; 
} 

void doLogin() 
{ 
    std::cout << "Login function called!\n"; 
} 

std::map<std::string, func_t> functionMap; 

void initMap() 
{ 
    functionMap["create"] = doCreate; 
    functionMap["login"] = doLogin; 
} 

int main() 
{ 
    initMap(); 
    std::string str = "login"; 
    functionMap[str](); // will call doLogin() 

    str = "create"; 
    functionMap[str](); // will call doCreate() 

    std::string userStr; 
    // let's now assume that we also can receive a string not from our set of functions 
    std::cin >> userStr; 
    if (functionMap.count(userStr)) 
    { 
      functionMap[str](); // now we call doCreate() or doLogin() 
    } 
    else 
    { 
      std::cout << "Unknown command\n"; 
    } 

    return 0; 
} 

=)

+0

++ 1 : 마지막으로,이 페이지의 일부 괜찮은 코드. –

+1

@LightnessRacesinOrbit : 문제는 기본적으로 크래시가 발생했습니다. 데이터가 사용자가 제공하고 사전 심사 대상이 아니기 때문에 아마도 원하지 않을 것입니다. 또한 나는 그것이 더 효율적이라고 의심한다 (OPs 소원). – Deduplicator

+0

@Deduplicator : 기본 케이스는 큰 문제가 아니며 작은 수표를 추가하여 해결할 수 있다고 생각합니다. 효율성에 관해서 ... 실제로 저는 OP 권리를 이해하지 못할 수도 있지만 제 의견으로는 효율성에 대한 확장 성 및 가독성에 대한 질문이 더 많습니다. 어쨌든, 그만큼 비용이 많이 듭니까? – antonpp

관련 문제