动态选择要引用的 #define

  • 本文关键字:#define 引用 选择 动态 c
  • 更新时间 :
  • 英文 :


我正在编写一个HTTP 1.0下载器,并使用以下 #define 替换来格式化查询:

#define GET_FORMAT "GET %s%s HTTP/1.0rnHost: %srnUser-Agent: getterrnrn"
#define HEAD_FORMAT "HEAD %s%s HTTP/1.0rnHost: %srnUser-Agent: getterrnrn"
#define GET_FORMAT_RANGE "GET %s%s HTTP/1.0rnHost: %srnRange: %srnUser-Agent: getterrnrn"
#define HEAD_FORMAT_RANGE "HEAD %s%s HTTP/1.0rnHost: %srnRange: %srnUser-Agent: getterrnrn"

我目前使用这样的东西来替换查询字符串的"%s"部分。我觉得它可以更优雅:

char* query_string_formatter(char* page, char* host, int get){ 
switch(get) {
case 0:
//HEAD
{
char* query = malloc(strlen(host) + strlen(page) + 1 + HEAD_FORMAT_LEN);
if (page[0] == '/') {
sprintf(query,HEAD_FORMAT, "", page, host);
} else { 
sprintf(query, HEAD_FORMAT, "/", page, host);
}
return query;
}
default: 
//GET
{
char* query = malloc(strlen(host) + strlen(page) + 1 + GET_FORMAT_LEN);
if (page[0] == '/') {
sprintf(query,GET_FORMAT, "", page, host);
} else { 
sprintf(query, GET_FORMAT, "/", page, host);
}
return query;
}
}
}

但是我喜欢用这样更优雅的东西代替它:

...
sprintf(query, format, "",page,host);

其中格式是 GET 或 HEAD,而不是有几个嵌套的 if 语句和重复的代码

为了防止代码重复,您可以使用变量来记住之前的格式

char* query_string_formatter(char* page, char* host, int get){
char* query = malloc(strlen(host) + strlen(page) + 1 + HEAD_FORMAT_LEN);
char *format;
if (get)
format = GET_FORMAT;
else
format = HEAD_FORMAT;
if (page[0] == '/') 
sprintf(query, format, "", page, host);
else
sprintf(query, format, "/", page, host);
return query;
}

甚至更短但可读性较差:

char* query_string_formatter(char* page, char* host, int get){
char* query = malloc(strlen(host) + strlen(page) + 1 + HEAD_FORMAT_LEN);
sprintf(query, get ? GET_FORMAT : HEAD_FORMAT, page[0] == '/' ? "" : "/", page, host);
return query;
}

另外:确保HEAD_FORMAT_LEN包含"\0"结尾,或在malloc中添加更多 1。

就个人而言,我会完全消除宏,并做类似的事情

const char *format_string[] = {"GET %s%s HTTP/1.0rnHost: %srnUser-Agent: getterrnrn",
"HEAD %s%s HTTP/1.0rnHost: %srnUser-Agent: getterrnrn"};
char* query_string_formatter(const char* page, const char* host, int get)
{ 
if (get != 0) get = 1;
char* query = malloc(strlen(host) + strlen(page) + 1 + strlen(format[get]);
sprintf(query, format[get], (page[0] == '/' ? "" : "/"), page, host);
return query;
}

或者,可以将上述定义format_string放在函数query_string_formatter()中。 将其保留在函数之外的文件范围,允许同一源文件中的多个函数使用该数组。

您没有指定,但我假设 - 在您的代码中 -HEAD_FORMAT_LENGET_FORMAT_LEN可以分别替换为strlen(HEAD_LEN)strlen(GET_LEN)。 这或多或少与您的用法一致 [事实上,使用strlen()可能会稍微过度分配使用malloc()但这实际上比分配不足要好 - 您希望缓冲区长度至少是要复制到它的长度]。

您可能可以进一步合理化,因为两种格式字符串之间的唯一区别是在开始时使用子字符串"GET""HEAD"

您尚未展示如何使用宏GET_FORMAT_RANGEHEAD_FORMAT_RANGE的任何示例,但是 - 如果在代码中以类似的方式使用它们 - 则可以以类似的方式消除它们。

最新更新