我做了一个宏。我担心它可能有点“过于顽皮”,因为宏是邪恶的。
以下是没有宏的代码:
case SDLK_a:
_buffer_.InsertAtCursor('a');
_buffer_.MutableCursor().Right();
break;
这是宏定义及其用法:
#define SDLK_KEY_CASE_MACRO(X, Y) \
{\
case X: \
_buffer_.InsertAtCursor(Y); \
_buffer_.MutableCursor().Right(); \
break;\
}
SDLK_KEY_CASE_MACRO(SDLK_b, 'b');
SDLK_KEY_CASE_MACRO(SDLK_c, 'c');
SDLK_KEY_CASE_MACRO(SDLK_d, 'd');
SDLK_KEY_CASE_MACRO(SDLK_e, 'e');
SDLK_KEY_CASE_MACRO(SDLK_f, 'f');
SDLK_KEY_CASE_MACRO(SDLK_g, 'g');
SDLK_KEY_CASE_MACRO(SDLK_h, 'h');
SDLK_KEY_CASE_MACRO(SDLK_i, 'i');
SDLK_KEY_CASE_MACRO(SDLK_j, 'j');
SDLK_KEY_CASE_MACRO(SDLK_k, 'k');
SDLK_KEY_CASE_MACRO(SDLK_l, 'l');
SDLK_KEY_CASE_MACRO(SDLK_m, 'm');
SDLK_KEY_CASE_MACRO(SDLK_n, 'n');
SDLK_KEY_CASE_MACRO(SDLK_o, 'o');
SDLK_KEY_CASE_MACRO(SDLK_p, 'p');
SDLK_KEY_CASE_MACRO(SDLK_q, 'q');
SDLK_KEY_CASE_MACRO(SDLK_r, 'r');
SDLK_KEY_CASE_MACRO(SDLK_s, 's');
SDLK_KEY_CASE_MACRO(SDLK_t, 't');
SDLK_KEY_CASE_MACRO(SDLK_u, 'u');
SDLK_KEY_CASE_MACRO(SDLK_v, 'v');
SDLK_KEY_CASE_MACRO(SDLK_w, 'w');
SDLK_KEY_CASE_MACRO(SDLK_x, 'x');
SDLK_KEY_CASE_MACRO(SDLK_y, 'y');
SDLK_KEY_CASE_MACRO(SDLK_z, 'z');
显然,这为我节省了大量的打字和大量的代码。代码也编译并运行正常。
答案 0 :(得分:3)
与任何理智的系统一样,SDL_SCANCODE_A
(又名SDLK_a
)处于连续的整数范围内,并按顺序一直到SDL_SCANCODE_Z
。 'a'
到'z'
也是如此。
if( val >= SDLK_a && val <= SDLK_z ) {
_buffer_.InsertAtCursor( 'a' + (val-SDLK_a) );
_buffer_.MutableCursor().Right();
} else {
// handle other cases
}
这比宏墙更有效,更短,更清晰。
您可能需要重复数字。
对于特殊字符(制表符,引号等),我不会依赖于被激怒的东西。那里你想要一张短桌
struct SDL_table {
unsigned code;
char value;
};
SDL_table table[] = {
{SDL_SCANCODE_TAB, '\t'},
// ... etc
};
然后,在早期检查失败后,快速搜索该表
auto it = std::find_if( std::begin(table), std::end(table), [&](SDL_table t) { return t.code == val; } );
if (it != std::end(table)) {
_buffer_.InsertAtCursor( it->value );
_buffer_.MutableCursor();
} else {
// deal with unrecognized scancode
}
此时我可能会重构_buffer_
代码。
char SDLK_to_char( unsigned sdlk ) {
if( sdlk >= SDLK_a && sdlk <= SDLK_z )
return 'a' + (val-SDLK_a);
if( sdlk >= SDLK_0 && sdlk <= SDLK_9 )
return '0' + (sdlk-SDLK_0);
struct SDLK_entry {
unsigned code;
char value;
};
static const SDLK_entry table[] = {
{SDL_SCANCODE_TAB, '\t'},
// ... etc
};
auto it = std::find_if( std::begin(table), std::end(table),
[&](auto&& t) { return t.code == sdlk; }
);
if (it != std::end(table))
return it->value;
return 0; // null for failure
}
然后
char c = SDLK_to_char( sdlk );
if (c) {
_buffer_.InsertAtCursor( c );
_buffer_.MutableCursor().Right();
}
答案 1 :(得分:2)
好吧,我会避免使用宏 - 即使我必须用案例写出完整的switch
。
但首先我会考虑另一种方法。
例如,将SDLK_...
翻译成...
的查找表。在C ++中,您可以将其基于std::map
像:
std::map<SDLK_type, char> look_up_table = {{SDLK_a, 'a'}, {SDLK_b, 'b'}};
auto i = look_up_table.find(SDLK_value);
if (i != look_up_table.end())
{
char c = i->second;
_buffer_.InsertAtCursor(c);
_buffer_.MutableCursor().Right();
}
else
{
std::cout << "Not found" << std::endl;
}