| 1 | | - | The [[Reserved word|reserved word]] `case` starts a clause where alternatives are chosen. |
| 2 | | - | |
| 3 | | - | ## structure |
| 4 | | - | |
| 5 | | - | The general structure of `case`-clauses looks like this: |
| 6 | | - | |
| 7 | | - | ``` pascal |
| 8 | | - | case selector of |
| 9 | | - | caseValue0: <statement>; |
| 10 | | - | caseValue1,caseValue7: <statement>; |
| 11 | | - | caseValue10..caseValue20: <statement>; |
| 12 | | - | else <statements>; |
| 13 | | - | end; |
| 14 | | - | |
| 15 | | - | ``` |
| 16 | | - | |
| 17 | | - | The following constraints have to be met: |
| 18 | | - | |
| 19 | | - | - The data type of `selector` has to be an ordinal type. [[FPC|FreePascal]] additionally allows [[Character and string types|strings]]. |
| 20 | | - | - All case values have to be the same data type as `selector` is. |
| 21 | | - | - They have to be constant expressions, i.e. known at compile-time. |
| 22 | | - | - All `case`-labels have to be mutually disjoint. For every discrete value there applies exactly one or no cases. |
| 23 | | - | - A `case`-clause has to have at least one `case`-label. Imperative `case`-statements can have at most one anonymous cases (at most one `else`/`otherwise`-branches). |
| 24 | | - | |
| 25 | | - | The actual order of `case`-labels is not relevant. They may be ascending, descending, or mixed up, it does not matter. |
| 26 | | - | |
| 27 | | - | Originally, standard Pascal also set the constraint, that *all possible* values of the selector have to have a corresponding match. This is no longer the case with modern compilers. |
| 28 | | - | |
| 29 | | - | `case` can have both, imperative and declarative meanings, depending on where it is written. The former are “statements”, whereas the latter start a “variant part” of records. |
| 30 | | - | |
| 31 | | - | ### `case`-statements |
| 32 | | - | |
| 33 | | - | `case`-statements are a concise way of writing [[Branch|branches]]. They suit best, where alternative paths are taken *exclusively*. They may contain an [[Else|else]]-branch catching all cases that are not listed. |
| 34 | | - | |
| 35 | | - | ``` pascal |
| 36 | | - | program asciiTest(input, output, stderr); |
| 37 | | - | |
| 38 | | - | var |
| 39 | | - | c: char; |
| 40 | | - | |
| 41 | | - | begin |
| 42 | | - | read(c); |
| 43 | | - | case ord(c) of |
| 44 | | - | // empty statement, so the control characters are not |
| 45 | | - | // considered by the else-branch as non-ASCII-characters |
| 46 | | - | 0..$1F, $7F: ; |
| 47 | | - | $20..$7E: |
| 48 | | - | begin |
| 49 | | - | writeLn('You entered an ASCII printable character.'); |
| 50 | | - | end; |
| 51 | | - | else |
| 52 | | - | begin |
| 53 | | - | writeLn('You entered a non-ASCII character.'); |
| 54 | | - | end; |
| 55 | | - | end; |
| 56 | | - | end. |
| 57 | | - | ``` |
| 58 | | - | |
| 59 | | - | Note, `case`-statements accept expressions as selector. |
| 60 | | - | |
| 61 | | - | Instead of writing `else` the word `otherwise` is allowed, too. This is an [[Extended Pascal]] extension. |
| 62 | | - | |
| 63 | | - | While the same semantics can be achieved by consecutive [[If|if]]-[[Then|then]]-branches, utilizing a [[Case Compiler Optimization|case-statement allows the code generator to optimize the branch selection]]. |
| 64 | | - | |
| 65 | | - | #### comparative remarks |
| 66 | | - | |
| 67 | | - | There is no “fall-through” as it is the case with other languages such as shell or C. In Pascal exactly one case matches, is processed, and program flow continues after the final [[End|end]] of the `case`-statement. The [[Break|break-statement]] with its special meaning only appears in loops. |
| 68 | | - | |
| 69 | | - | ### variant part in records |
| 70 | | - | |
| 71 | | - | A [[Record|record]] may contain a variant part. The `case`-selector has to be the name of a data type, but an identifier for accessing the current variant can be provided, too. |
| 72 | | - | |
| 73 | | - | ``` pascal |
| 74 | | - | program variantRecordDemo(input, output, stderr); |
| 75 | | - | |
| 76 | | - | type |
| 77 | | - | sex = (female, male); |
| 78 | | - | clothingSize = record |
| 79 | | - | // FIXED PART |
| 80 | | - | shoulderWidth: word; |
| 81 | | - | armLength: word; |
| 82 | | - | bustGirth: word; |
| 83 | | - | waistSize: word; |
| 84 | | - | hipMeasurement: word; |
| 85 | | - | // VARIABLE PART |
| 86 | | - | case body: sex of |
| 87 | | - | female: ( |
| 88 | | - | underbustMeasure: word; |
| 89 | | - | ); |
| 90 | | - | male: ( |
| 91 | | - | ); |
| 92 | | - | end; |
| 93 | | - | begin |
| 94 | | - | end. |
| 95 | | - | ``` |
| 96 | | - | |
| 97 | | - | ## see also |
| 98 | | - | |
| 99 | | - | - [“The `case` statement” in the “FreePascal reference manual”](https://www.freepascal.org/docs-html/ref/refsu56.html) |
| 100 | | - | - [[Basic Pascal Tutorial/Chapter 3/CASE|“case” as part of the “Object Pascal introduction”]] |
| 101 | | - | |
| 102 | | - | ## external references |
| 103 | | - | |
| 104 | | - | - [Tao Yue: “Learn Pascal!”. Chapter “case”](https://lazarus-ccr.sourceforge.io/pascal/pas3cb.html) |
| 105 | | - | |
| 106 | | - | --- |
| 107 | | - | *From the Free Pascal wiki, page "Case", as it stood on 2023-10-17 after a change by FPC user, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
| 108 | | - | Category: Code |
| 1 | + | #REDIRECT [[Basic Pascal Tutorial/Chapter 3/CASE]] |