如何将其写为switch语句?

时间:2016-08-09 22:31:42

标签: c if-statement switch-statement

我在尝试将if语句集合重写为switch语句时遇到了一些麻烦。

这不是一个练习或任何事情,我真的很喜欢switch语句的外观。然而,我在使用if条件中的函数时遇到了麻烦。

const char* lookup(const char* path)
{
    //if a path exists, compare path to given extensions
    //if there is a match, return the appropriate output
    if (path != NULL) {
        //using strcasecmp is useful b/c capitalization is overlooked when looking for a match
        if (strcasecmp(path, "CSS") == 0) return "text/css";
        if (strcasecmp(path, "HTML") == 0) return "text/html";
        if (strcasecmp(path, "GIF") == 0) return "image/gif";
        if (strcasecmp(path, "ICO") == 0) return "image/x-icon";
        if (strcasecmp(path, "JPG") == 0) return "image/jpeg";
        if (strcasecmp(path, "JS") == 0) return "text/javascript";
        if (strcasecmp(path, "PHP") == 0) return "text/x-php";
        if (strcasecmp(path, "PNG") == 0) return "image/png";
    }
    //if there is no path, return NULL
    return NULL;
}

有可能做到这一点,有什么好处还是我在浪费时间?

3 个答案:

答案 0 :(得分:4)

正如评论所指出的那样,你不能。你可以做的是让它由表驱动,这可能是@Lambda Ninja想要的更干。像这样的东西?

typedef struct pair_s {
    const char *first;
    const char *second;
} pair;

const char *lookup(const char *path)
{
    static pair content_types[] = {
        { "CSS", "text/css" },
        { "HTML", "text/html" },
        { "GIF", "image/gif" },
        { "ICO", "image/x-icon" },
        // ... etc.
        { "", "" }, // terminator
    };

    for (int i = 0; *content_types[i].first != '\0'; i++) {
        if (strcasecmp(path, content_types[i].first) == 0)
            return content_types[i].second;
    }

    return NULL;
}

答案 1 :(得分:1)

因为C开关只能测试基元类型,所以需要将字符串映射到其中一种类型。 令人高兴的是,您要测试的字符串只有足够的字符以适应int,因此您可以使用按位运算符将字符组合成唯一值,可通过开关测试:

#define VAL_CSS  ( ((('C'<<8)|'S')<<8)|'S')
#define VAL_HTML ((((('H'<<8)|'T')<<8)|'M')<<8|'L')
#define VAL_GIF  ( ((('G'<<8)|'I')<<8)|'F')
#define VAL_ICO  ( ((('I'<<8)|'C')<<8)|'O')
#define VAL_JPG  ( ((('J'<<8)|'P')<<8)|'G')
#define VAL_JS   (   ('J'<<8)|'S')
#define VAL_PHP  ( ((('P'<<8)|'H')<<8)|'P')
#define VAL_PNG  ( ((('P'<<8)|'N')<<8)|'G')

const char* lookup(const char* path) { /* "ext" might be a better name than "path" */
  if (path != NULL)
    if (strlen(path) <= sizeof(uint32_t)) { /* check it'll fit */
      uint32_t val = 0;
      while (*path) 
        val = val<<8 | toupper(*path++); /* same as in #defines */

      switch (val) {
        case VAL_CSS:  return "text/css";        break;
        case VAL_HTML: return "text/html";       break;
        case VAL_GIF:  return "image/gif";       break;
        case VAL_ICO:  return "image/x-icon";    break;
        case VAL_JPG:  return "image/jpeg";      break;
        case VAL_JS:   return "text/javascript"; break;
        case VAL_PHP:  return "text/x-php";      break;
        case VAL_PNG:  return "image/png";       break;
      }
    }

  return NULL;
}

答案 2 :(得分:-3)

这看起来像是地图的候选人。

php中的例子:

$formats = array ("CSS"  => "text/css", "HTML" => "text/html", etc);
//to use:
return $formats[path]; //returns text/css if path is equal to CSS