天天看點

C/C++的switch/case語言如何支援字元串?

作者:泗水亭長

問題背景

本人以前軟體開發過程中遇到一個問題,收到各種指令(指令為字元串)時,分情況處理。

但C/C++得switch語句并不支援直接對字元串進行分情況處理。

C/C++的switch/case語言如何支援字元串?

C/C++的switch語句隻支援整形和枚舉類型

蟒蛇語言Python通過match/case語句異常強大,支援對不同的字元串進行分情況處理:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>           

作為最新型語言Kotlin,其when語句也具有非常優雅的字元串分情況處理能力:

fun handleString(input: String) 
{ 
    when (input) 
    { 
      "case1" -> println("Handling case 1") 
      "case2" -> println("Handling case 2") // 可以添加更多的case 
      else -> println("Unknown case") 
    } 
} 

fun main() 
{ 
    handleString("case1") // 輸出: Handling case 1 
    handleString("someOtherString") // 輸出: Unknown case 
}           

遺憾的是,C/C++的switch/case語句不能支援這項功能。

為此,很多程式員也在探讨變通的方案。

我的基于Hash函數方案

本人在不斷時間中,探索出一個比較優雅的方案,分享給有緣程式員:

#include <iostream>

using namespace std;

constexpr unsigned int Hash(const char* str)
{
    const unsigned int  prime = 16777619;
    const unsigned int  offset_basis = 2166136261;
    unsigned int        hash = offset_basis;

    while (*str)
    {
        hash ^= (unsigned int)*str++;
        hash *= prime;
    }

    return hash;
}

void op(const char *op)
{
    switch(Hash(op))
    {
      case Hash("OP1"):
        cout << "OP1" << endl;
        break;

      case Hash("OP2"):
        cout << "OP2" << endl;
        break;

      default:
        cout << "Other" << endl;
        break;
    }
}

int main()
{
    char *s1 = "OP1";
    char *s2 = "OP2";

    op(s1);
    op(s2);
}           

在程式中,我們先定義了一個傳回哈希函數,将字元串轉換為32位無符号整數。由于該函數的傳回值是constexpr類型,是以case語句中的Hash函數會在編譯階段就會将其中的字元串轉換為32位無符号整數值。

運作時,switch語句用同樣的Hash函數計算出字元串的Hash值,并與case語句中已經編譯形成的值進行比較。

這裡的哈希函數我是通過文心一言找到的(問題:請給出比MD5更簡單的哈希函數的C語言代碼),算法名稱叫FNV雜湊演算法,全名為Fowler-Noll-Vo算法,由Glenn Fowler、Landon Curt Noll和Phong Vo提出,并在1991年首次引入。FNV雜湊演算法能夠快速哈希大量資料并保持較小的沖突率,是以用在C/C++的switch/case語句中幾乎不會出現問題。

本方法屬于作者原創,屬于目前最理想的方案。竊以為這個方法對程式員來比較有用,不敢私藏,分享給廣大程式員朋友。