对于switch的break语句,是否有更好的编程语言?

时间:2010-06-10 13:17:20

标签: java c language-agnostic programming-languages switch-statement

语法太多,语法相同:

switch (someValue) {

  case OPTION_ONE:
  case OPTION_LIKE_ONE:
  case OPTION_ONE_SIMILAR:
    doSomeStuff1();
    break; // EXIT the switch

  case OPTION_TWO_WITH_PRE_ACTION:
    doPreActionStuff2();
    // the default is to CONTINUE to next case

  case OPTION_TWO:
    doSomeStuff2();
    break; // EXIT the switch

  case OPTION_THREE:
    doSomeStuff3();
    break; // EXIT the switch

}

现在所有人都知道break语句是必需的,因为当switch语句丢失时,case会继续到下一个break。我们有OPTION_LIKE_ONEOPTION_ONE_SIMILAROPTION_TWO_WITH_PRE_ACTION的示例。问题是我们只需要非常非常非常需要“跳到下一个案例”。我们经常在case结束时放假。

初学者很容易忘记它。我的一位C老师甚至向我们解释过,好像这是C语言的一个错误(不想谈论它)。

我想问一下我是否还有其他语言(或忘了)处理这样的开关/案例:

switch (someValue) {

  case OPTION_ONE:  continue; // CONTINUE to next case
  case OPTION_LIKE_ONE:  continue; // CONTINUE to next case
  case OPTION_ONE_SIMILAR:
    doSomeStuff1();
    // the default is to EXIT the switch

  case OPTION_TWO_WITH_PRE_ACTION:
    doPreActionStuff2();
    continue; // CONTINUE to next case

  case OPTION_TWO:
    doSomeStuff2();
    // the default is to EXIT the switch

  case OPTION_THREE:
    doSomeStuff3();
    // the default is to EXIT the switch

}

第二个问题:C中为什么会有这样的历史意义?可能会继续使用下一个案例的次数远远超过我们现在使用的情况吗?

17 个答案:

答案 0 :(得分:11)

this文章中,我可以枚举一些不需要break类似语句的语言:

  1. Ada(没有通过)
  2. 埃菲尔(没有穿透)
  3. Pascal(没有穿透)
  4. 去 - fallthrough
  5. Perl - continue
  6. Ruby(没有通过)
  7. VB,VBA,VBS,VB.NET(没有通过)
  8. 继续被其他人继续......
  9. 你的第二个问题非常有趣。假设只有C,我相信这个决定保持了语言的凝聚力。由于break jump ,因此必须明确写入。

答案 1 :(得分:9)

Scala模式匹配我认为在这些情况下是一个巨大的改进。 :)

object MatchTest2 extends Application {
  def matchTest(x: Any): Any = x match {
    case 1 => "one"
    case "two" => 2
    case y: Int => "scala.Int"
  }
  println(matchTest("two"))
}

来自scala-lang.org的样本

答案 2 :(得分:6)

VB .NET处理它的方式更像你期望它应该如何工作。

Select Case i
    Case 1 to 3
        DoStuff(i)
    Case 4,5,6
        DoStuffDifferently(i)
    Case Is >= 7
        DoStuffDifferentlyRedux(i)
    Case Else
        DoStuffNegativeNumberOrZero(i)
End Select

根本没有堕落,没有使用Goto

答案 3 :(得分:4)

以下是答案: http://en.wikipedia.org/wiki/Switch_statement

它被称为直通语句(示例中为continue),它以下列语言存在:
Go,Perl,C#

在C#中,如果没有breakgoto case语句,则无法编译(除非没有预先行动)。

答案 4 :(得分:3)

PASCAL没有堕落

答案 5 :(得分:3)

我认为你的问题的答案是以这种方式为中心的两个行为,都与C源生成的汇编代码有关。

第一个是在汇编中,执行当前指令,除非有跳转或其他流控制指令,否则将执行下一个地址的指令。执行switch语句到程序集的简单编译会生成只会开始执行第一条指令的代码,这将是查看是否存在匹配条件...

第二个相关原因是branch table or jump list的概念。基本上,编译器可以获取它对您的值的了解,并为同一事物创建一些非常高效的机器代码。例如,像atoi这样的简单函数,它转换数字的字符串表示形式并以整数形式返回。简化事情以支持一个数字,你可以写一些类似的代码:

int atoi(char c) {
  switch (c) {
    case '0': return 0;
    case '1': return 1;
    // ....
  }
}

天真的编译器可能只是将其转换为一系列if / then块,这意味着对于数字9将采用大量的CPU周期,而0几乎立即返回。使用分支表,编译器可以发出一些[psuedo]程序集,它会立即“跳转”到正确的return子句:

0x1000 # stick value of c in a register
0x1004 # jump to address c + calculated offset
# example '0' would be 0x30, the offset in for this sample
# would always be 0x0FD8... thus 0x30 + 0x0FD8 = 0x1008
0x1008 # return 0 

道歉:我的集会和C技能都很生疏。我希望这有助于澄清事情。     0X

答案 6 :(得分:2)

嘿,不要忘记COBOL的评估:

EVALUATE MENU-INPUT
    WHEN "0" PERFORM INIT-PROC
    WHEN "1" THRU "9" PERFORM PROCESS-PROC
    WHEN "R" PERFORM READ-PARMS
    WHEN "X" PERFORM CLEANUP-PROC 
    WHEN OTHER PERFORM ERROR-PROC
END-EVALUATE.

答案 7 :(得分:1)

Ada没有漏洞,并且要求显式处理所有值,或者添加“others”子句以处理其余值。

SQL CASE语句也没有落实。 XSLT并没有落空。

似乎是C语言和派生语言都有这个漏洞。这是非常阴险的,我见过的唯一真正的用途就是实现duff's device

http://www.adaic.org/whyada/intro4.html

答案 8 :(得分:1)

纯粹猜测,但是:

我偶尔写C或Java,其中我说的是:

switch (tranCode)
{
  case 'A':
  case 'D':
  case 'R':
    processCredit();
    break;
  case 'B':
  case 'G':
    processDebit();
    break;
  default:
    processSpecial();
}

也就是说,我故意使用fall-thru让几个值触发相同的操作。

我想知道这是C的发明者在创建SWITCH语句时想到的,这是正常用法。

答案 9 :(得分:1)

OP谈到“堕落”,但很少有人对此表示赞同。

很多次,但是我的设计是不可扩展的。也就是说,“切换(kbHit)”语句,其中有几百个键,这是一个维护噩梦,以及“神方法”的常用位置,以及大堆的意大利面条代码。

使用switch通常是面向对象编程不佳的标志。正如另一个人回答的那样,“在48个源文件中使用Switch”,在他的一个应用程序中,显示了一个程序员,他并没有严重依赖这个结构。根据他的指标,我猜测他可能至少是一个优秀的结构化程序员,并且可能也理解OOP / OOD。

OOP(不一定只有C ++)程序员,甚至没有强制使用对象描述技术的纯C用户,可以实现“控制反转”容器,该容器发布“密钥被击中”并允许订阅者插入他们的处理程序“键盘代码x”。这可以使您更轻松地阅读代码。

答案 10 :(得分:1)

虽然不完全符合您的要求,但Groovy有一个very powerful switch statement

答案 11 :(得分:1)

Python根本没有。

我已经习惯了一些人,但是在我的C#时代,我有一些可怕的记忆在追逐大量的switch块。没有它我会更开心。

答案 12 :(得分:0)

语言太多了我无法回答肯定没有这样的语言,只要它是语法中C的“派生”,因为其他语言使用不同的语法并且案例不会“继续”自然存在,例如Fortran语言。我不知道使用明确的“继续”继续下列情况的语言。

我认为这是历史原因,因为这种情况可以在“低级别”编程。此外,案例的语法方面是标签,而break就像循环一样,所以你可以想象一个像这样的等价物:

if ( case == 1 ) goto lab1;
if ( case == 2 ) goto lab2;
if ( case == 3 ) goto lab3;    
//...
default:
  // default
  goto switch_end;
lab1:
  // do things
  goto switch_end; // if break is present
lab2:
  // do things, and follow to lab3
lab3:
  // lab3 stuffs
  goto switch_end;
//
...
switch_end:  // past all labS.

答案 13 :(得分:0)

在面向对象语言中,您使用Chain of Responsibility模式。如何实施可能会有所不同。您在示例中描述的是通过滥用switch语句将状态机与行为混合在一起。对于您的特定示例,具有链评估为State模式的参数的责任链模式,在其沿着链向下变化时,将是适当的实现。

答案 14 :(得分:0)

Tcl不会自动失效。

答案 15 :(得分:0)

更多没有语言的语言:

XSLT JSTL 大陵 PL / 1

答案 16 :(得分:0)

利马这样做:

if someValue == ?1 ::
   OPTION_ONE: fall
   OPTION_LIKE_ONE: fall
   OPTION_ONE_SIMILAR:
     doSomeStuff1[]
     ;; the default is to EXIT the switch

   OPTION_TWO_WITH_PRE_ACTION:
     doPreActionStuff2[]
     fall                 ;; fall through to the next case

   OPTION_TWO:
     doSomeStuff2[]

   OPTION_THREE:
     doSomeStuff3[]