动态选择要引用的#define

时间:2019-09-07 08:19:04

标签: c

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

#define GET_FORMAT "GET %s%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: getter\r\n\r\n"
#define HEAD_FORMAT "HEAD %s%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: getter\r\n\r\n"
#define GET_FORMAT_RANGE "GET %s%s HTTP/1.0\r\nHost: %s\r\nRange: %s\r\nUser-Agent: getter\r\n\r\n"
#define HEAD_FORMAT_RANGE "HEAD %s%s HTTP/1.0\r\nHost: %s\r\nRange: %s\r\nUser-Agent: getter\r\n\r\n"

我目前正在使用类似的东西来替换查询字符串的'%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;
        }
    }

}

但是id喜欢用更优雅的方式替换它:

...

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

格式为GET或HEAD,而不是嵌套多个if语句和重复代码

2 个答案:

答案 0 :(得分:2)

为防止代码重复,您可以使用变量在

之前存储格式
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。

答案 1 :(得分:1)

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

const char *format_string[] = {"GET %s%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: getter\r\n\r\n",
                               "HEAD %s%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: getter\r\n\r\n"};

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的任何示例,但是-如果在代码中以类似的方式使用它们,则可以在类似的方式。