在案例范围内限制开关情况

时间:2014-08-27 20:07:31

标签: case d

我试图在案例切换中包含UTF-8标识符但我收到此错误:

  

错误:有399个案例,案件范围超过256个案件

D代码:

    switch(value)
    {
        case 'a': ..  case 'z':
        case 'A': ..  case 'Z':
        case 0xC0: .. case 0x24F:

为什么编译器会施加这样的限制?为了达到最佳目的?我能克服它吗?

3 个答案:

答案 0 :(得分:5)

这样做是为了获得更多空间。

您在此处看到的限制不在规范http://dlang.org/statement中,并且仅适用于编译器中的CaseRangeStatements:我所拥有的版本中的src / dmd / statement.c第3437行:

if (lval - fval > 256)
{   error("had %llu cases which is more than 256 cases in case range", lval - fval);
    lval = fval + 256;
}

因此,修复方法是将该范围分成几个部分并将它们放在一起:

        switch(value)
{
    case 'a': ..  case 'z':
    case 'A': ..  case 'Z':
    case 0xC0: .. case 0x14F: // this compiles
    case 0x150: .. case 0x24F: // since it is broken up

然后你以同样的方式处理它们。

编译器源代码没有说明为什么会有这样的检查,但github历史记录表明它是为了响应这个错误而提交的:https://issues.dlang.org/show_bug.cgi?id=3139

[s]因此,编译器中的实现细节是为了避免无限循环。[/ s]

编辑:实际上,256检查是在那之前,我读错了补丁,唐除了它之外还添加了一张支票。看起来256件事先于github所以我不知道为什么它被特别添加,但我仍然非常有信心它与循环和内存问题有关,只是编译器实现细节和错误。

答案 1 :(得分:2)

摆脱限制的另一种方法是使用委托数组,并使用字符作为选择器选择要调用的方法。然后你的开关看起来有点像这样:

void main(string args[])
{
    alias caseProc = void delegate();
    caseProc[1024] callTable;

    void numberProc(){}
    void latinProc(){}
    void otherProc(){}

    for(auto i = 0; i < callTable.length; i++)
    {
        if (i >= '0' && i <= '9')
            callTable[i] = &numberProc;
        else if ((i >= 'a' && i <= 'z') | (i >= 'A' && i <= 'Z'))
            callTable[i] = &latinProc;
        else
            callTable[i] = &otherProc;
    }
}

答案 2 :(得分:0)

D中的开关最多只能包含256个案例。你必须改变这样做的整个方式。

if (value >= 'a' && value <= 'z')
{
    // ...
}
else if (value >= 'A' && value <= 'Z')
{
    // ...
}
else if (value >= 0xC0 && value <= 0x24F)
{
    // ...
}

或者像这样,如果你想处理所有相同的情况。

if (value >= 'a' && value <= 'z' || value >= 'A' && value <= 'Z' || value >= 0xC0 && value <= 0x24F)
{
  // ...
}