我正在尝试创建一个查找宏。使用三元运算符似乎是一种非常简洁的方法。这就是我到目前为止所拥有的:
#define SQL_LOOKUP_TABLE(x) (strncmp(x, "int", strlen(x)) == 0) ? "INTEGER" : SQL_LOOKUP_TABLE1(x)
#define SQL_LOOKUP_TABLE1(x) (strncmp(x, "char", strlen(x)) == 0) ? "TEXT" : SQL_LOOKUP_TABLE2(x)
#define SQL_LOOKUP_TABLE2(x) (strncmp(x, "double", strlen(x)) == 0) ? "REAL" : ""
我想在c中将类型作为字符串传递,然后以字符串形式返回相应的SQL类型。当我做这样的事情时它很有用:
printf("Ternary test: %s\n", SQL_LOOKUP_TABLE("double")); //output "REAL"
我真正想要做的是获取此信息并构建整个SQL CRUD语句。当我尝试在另一个宏内部构建字符串时,问题就出现了。这样的事情不起作用:
#define BUILD_A_STRING(x) "CREATE TABLE ( " SQL_LOOKUP_TABLE( x )
我收到错误:
error C2064: term does not evaluate to a function taking 337 arguments
快速注意,这确实有效(返回" REAL"):
#define BUILD_A_STRING(x) SQL_LOOKUP_TABLE( x )
为什么我无法在另一个宏内部调用宏并构建字符串?
编辑(存在提供TMI的风险): 这就是我真正想要做的事情:
typedef struct {
double yomama;
int x;
char shiboopy[100];
} test_data1;
#define EXPAND_AS_CREATE_STATEMENT(type, element, struct_name) SQL_LOOKUP_TABLE( #type) " " # element ", "
#define test_data1_TABLE(ENTRY) \
ENTRY(double, yomama, test_data1) \
ENTRY(int, x, test_data1) \
ENTRY(char, shiboopy, test_data1)
char* create_stmt = "CREATE TABLE test_data1 (" test_data1_TABLE(EXPAND_AS_CREATE_STATEMENT) ");"; \
基本上使用X宏来定义结构的数据类型,然后将其扩展为我可能需要的任何CRUD语句。
答案 0 :(得分:2)
词法字符串连接是一个预处理器操作。三元运算符是运行时操作。当尝试连接字符串时,预处理器将查找相邻的字符串文字,但将无法找到任何字符串,因为
"CREATE TABLE ( " SQL_LOOKUP_TABLE( x )
预处理
"CREATE TABLE ( " (strncmp(x, "int", strlen(x)) == 0) ? "INTEGER" : SQL_LOOKUP_TABLE1(x)
并且预处理器不了解strncmp
,strlen
或三元运算符。
要执行您想要的操作,您必须在预处理器运行时执行条件操作。然而,C预处理器过于简单化,需要更复杂的预处理器,如m4。
另一个不利的方法是在运行时进行串联,显然需要一点开销。
我建议你重新考虑你的设计。哈希表可能会派上用场:它会起作用,它更干净,更有效。
答案 1 :(得分:1)
我正在解释这个:
我真正想要做的是获取此信息并构建一个完整的SQL CRUD语句。
......而且这个:
这就是我真正想要做的事情:
......如果压倒一切:
我想在c中将类型作为字符串传递,然后以字符串形式返回相应的SQL类型。
我认为您不应该将该类型作为 C字符串传递;什么都没有得到你,因为你正在使用该字符串正在将它传递回宏(并且宏不能对字符串做任何事情)。如果您将标记传递给宏,则可以让C预处理器本身进行查找。
这就是我的意思:
#define SQL_LOOKUP_TABLE(x) DB_TYPE_FOR_ ## x
#define DB_TYPE_FOR_double "REAL"
#define DB_TYPE_FOR_int "INTEGER"
#define DB_TYPE_FOR_char "TEXT"
将令牌传递给此宏,而不是 stringified 令牌:
#define EXPAND_AS_CREATE_STATEMENT(type, element, struct_name) \
SQL_LOOKUP_TABLE(type) " " # element ", "
......而且这个:
"CREATE TABLE test_data1 (" test_data1_TABLE(EXPAND_AS_CREATE_STATEMENT) ");"
...只是扩展到这个:
"CREATE TABLE test_data (" "REAL" " " "yomama" ", " "INTEGER" " " "x" ", " "TEXT" " " "shaboopy" ", " ");"
...字符串文字串联后等同于:
"CREATE TABLE test_data (REAL yomama, INTEGER x, TEXT shaboopy, );"
没有strcmp
,没有三元链,不需要哈希表。现在,我不确定您的数据库引擎是否足够懒,可以接受参数列表中的尾随逗号,但这是另一个问题(最简单的解决方案是为X宏添加分隔符宏支持)。
答案 2 :(得分:0)
@ Downvoter'答案解释了你得到错误的原因。 我觉得在你的情况下使用一个函数会更好。 类似的东西:
char* build_str(char* type)
{
static char str[80];
char* sql_type_str = SQL_LOOKUP_TABLE(type);
strcat(str, "CREATE TABLE (");
strcat(str,sql_type_str);
/* strcat others params */
return str;
}
也许你必须详细说明你打算如何使用BUILD_STRING
。