diff --git a/Doc/Sd1/Ref/Statements/dns-spoofing.png b/Doc/Sd1/Ref/Statements/dns-spoofing.png new file mode 100644 index 0000000000000000000000000000000000000000..136a2a27a9f55ac0c01082843d2edb091b5c2bba Binary files /dev/null and b/Doc/Sd1/Ref/Statements/dns-spoofing.png differ diff --git a/Doc/Sd1/Ref/Statements/sslCertificateError.png b/Doc/Sd1/Ref/Statements/sslCertificateError.png new file mode 100644 index 0000000000000000000000000000000000000000..44b3f6c1733fbbcb653018487df92036a6c62b48 Binary files /dev/null and b/Doc/Sd1/Ref/Statements/sslCertificateError.png differ diff --git a/Doc/Sd1/statements.xml b/Doc/Sd1/statements.xml index d1f07fc1626f50c00c68921a92627ad114512afc..2e6a98460d1313ff4b416059a47a0ca8c74858cc 100644 --- a/Doc/Sd1/statements.xml +++ b/Doc/Sd1/statements.xml @@ -89,7 +89,7 @@ <figure xml:id="sd1_fig_MultiStmtPerLine"> <title>Multiple statements per line</title> - <programlisting language="java">a *= 3; b = ++a - 4; </programlisting> + <programlisting language="java">a *= 3; b = ++a - 4;</programlisting> <para>Discouraged by good coding practices:</para> @@ -118,14 +118,14 @@ <title>Blocks</title> <programlisting language="java">double initialAmount = 34; -{ // first block +{ final double interestRate = 1.2; // 1.2% System.out.println("Interest:" + initialAmount * interestRate / 100); -} // End of first block -{ // second block +} +{ final double interestRate = 0.8; // 0.8% System.out.println("Interest:" + initialAmount * interestRate / 100); -} // End of second block</programlisting> +} </programlisting> <informaltable border="1"> <tr> @@ -160,12 +160,12 @@ <programlisting language="java">double initialAmount = 320000; -if (100000 <= initialAmount) { // Rich customer, higher interest rate - final double interestRate = 1.2; - System.out.println("Interest:" + initialAmount * interestRate / 100); -} else { // Joe customer, standard interest rate - final double interestRate = 0.8; // 0.8% - System.out.println("Interest:" + initialAmount * interestRate / 100); +if (100000 <= initialAmount) { + // Rich customer, 1,2% interest rate + System.out.println("Interest:" + 1.2 * initialAmount / 100); +} else { + // Joe customer, 0.8% standard interest rate + System.out.println("Interest:" + 0.8 * initialAmount / 100); }</programlisting> <informaltable border="1"> @@ -199,13 +199,11 @@ if (100000 <= initialAmount) { // Rich customer, higher interest rate <programlisting language="java">double initialAmount = 3200; if (100000 <= initialAmount) { // Rich customer, higher interest rate - final double interestRate = 1.2; - System.out.println("Interest:" + initialAmount * interestRate / 100); + System.out.println("Interest:" + 1.2 * initialAmount / 100); } else if (1000 <= initialAmount){ // Joe customer, standard interest rate - final double interestRate = 0.8; // 0.8% - System.out.println("Interest:" + initialAmount * interestRate / 100); + System.out.println("Interest:" + 0.8 * initialAmount / 100); } else { // Capitalism: Sorry, but ... - System.out.println("Interest:" + 0); + System.out.println("Interest:" + 0); }</programlisting> <informaltable border="1"> @@ -225,7 +223,103 @@ if (100000 <= initialAmount) { // Rich customer, higher interest rate </informaltable> </figure> - <qandaset defaultlabel="qanda" xml:id="sd1_qanda_GuessingResults"> + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_booleanEqual"> + <title>Comparing for equality</title> + + <qandadiv> + <qandaentry> + <question> + <para>Copy the following snippet into your IDE:</para> + + <programlisting language="java">int count = 1; + +if (count = 4) { // is count equal to 4? + System.out.println("count is o.K."); +}</programlisting> + + <para>The <xref linkend="glo_Java"/> compiler will indicate an error. Explain its cause in detail by explaining the underlying expression.</para> + </question> + + <answer> + <para>The compiler complains about incompatible types: An <code>int</code> is being found but a <code>boolean</code> to be expected.</para> + + <para>The expression <code>count = 4</code> is an assignment and <emphasis role="bold">not</emphasis> a comparison. Its type is <code>int</code> rather than <code>boolean</code>:</para> + + <programlisting language="java">int count = 1; +final int test = (count = 4); +System.out.println("test=" + test);</programlisting> + + <para>Execution yields the output <computeroutput><computeroutput>test=4</computeroutput></computeroutput>. The comment <quote>is count equal to 4?</quote> is thus misleading: The intended comparison requires using the <quote>==</quote> operator rather than an assignment operator <quote>=</quote>. Changing it the resulting expression is indeed of type <code>boolean</code>:</para> + + <programlisting language="java">int count = 4 + 3; +final boolean test = (count == 4); // Now using "==" (comparison) in favour of "=" (assignment) +System.out.println("test=" + test);</programlisting> + + <para>This time our result reads <computeroutput>test=false</computeroutput> as expected. Thus our initial code just needs a simple modification:</para> + + <programlisting language="java">int count = 1; + +if (count == 4) { // is count equal to 4? + System.out.println("count is o.K."); +}</programlisting> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <note xml:id="sd1_note_useLiteralEqualsVariable"> + <para>In contrast to <xref linkend="glo_Java"/> some programming languages like C and C++ allow using expressions like e.g. <code>if(count = 4)</code>:</para> + + <programlisting language="c">#include <stdio.h> + +int main(int argc, char **args) { + + int a = 3; + if (a = 4) { + printf("a has been changed to 4\n"); + } +}</programlisting> + + <para>The integer expression <code>count = 4</code> has got a value of 4. Integer values inside an <code>if (...)</code> statement will be evaluated as:</para> + + <glosslist> + <glossentry> + <glossterm>true</glossterm> + + <glossdef> + <para>if the expression's value differs from zero</para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>false</glossterm> + + <glossdef> + <para>if the expression's value equals zero</para> + </glossdef> + </glossentry> + </glosslist> + + <para>Thus <code>if(count = 4)</code> will always be true irrespective of the variable <code>count</code>'s initial value. Most important: The C compiler will not issue an error or warning unless non-default, more restrictive compile time directive are being activated.</para> + + <para>For this reason it is good practice using <code>if (4 == count)</code> instead: Even in C an accidentally mistyped <code>if (4 = count)</code> statement will definitively result in a compile time error most likely saving its author from tedious debugging.</para> + </note> + + <figure xml:id="sd1_fig_bestPracticeCompareEquals"> + <title><code>Best practices comparing for equality</code></title> + + <para>Always use</para> + + <programlisting language="java">if (4 == variable) ...</programlisting> + + <para>in favour of:</para> + + <programlisting language="java">if (variable == 4) ...</programlisting> + + <para>See <link xlink:href="sd1_sect_statements_if.html#sd1_note_useLiteralEqualsVariable">detailed explanation</link>.</para> + </figure> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_replaceElseIf"> <title>Replacing <code>if else (...)</code> by introducing a nested <code>if ... else</code></title> <qandadiv> @@ -259,6 +353,236 @@ if (100000 <= initialAmount) { // Rich customer, higher interest rate </qandadiv> </qandaset> + <figure xml:id="sd1_fig_IfOmitBlocks"> + <title>Single statement branches</title> + + <programlisting language="java">double initialAmount = 3200; + +if (100000 <= initialAmount) + System.out.println("Interest:" + 1.2 * initialAmount / 100); +else if (1000 <= initialAmount) + System.out.println("Interest:" + 0.8 * initialAmount / 100); +else + System.out.println("Interest:" + 0);</programlisting> + + <para>Branches containing exactly one statement don't require a block definition.</para> + </figure> + + <figure xml:id="sd1_fig_corporateSafety"> + <title>Corporate network security</title> + + <para>Would you access your online bank account using <emphasis role="bold">Stuttgart Media University's</emphasis> network?</para> + + <itemizedlist> + <listitem> + <para>Yes</para> + </listitem> + + <listitem> + <para>Only on private equipment (Smartphone, tablet, laptop, ...)</para> + </listitem> + + <listitem> + <para>Never!</para> + </listitem> + </itemizedlist> + </figure> + + <figure xml:id="sd1_fig_ipSpoofing"> + <title>IP Spoofing</title> + + <mediaobject> + <imageobject> + <imagedata fileref="Ref/Statements/dns-spoofing.png"/> + </imageobject> + </mediaobject> + </figure> + + <figure xml:id="sd1_fig_SSLCertificateError"> + <title>SSL Certificate error</title> + + <mediaobject> + <imageobject> + <imagedata fileref="Ref/Statements/sslCertificateError.png"/> + </imageobject> + </mediaobject> + </figure> + + <figure xml:id="sd1_fig_IfOmitBewareIndent"> + <title>The <link xlink:href="https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/">Apple goto fail SSL bug</link></title> + + <programlisting language="c">static OSStatus +SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, + uint8_t *signature, UInt16 signatureLen) +{ + OSStatus err; + ... + + if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) + goto fail; + if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) + goto fail; + goto fail; + if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) + goto fail; + + err = sslRawVerify(...); + ... + +fail: + SSLFreeBuffer(&signedHashes); + SSLFreeBuffer(&hashCtx); + return err; +}</programlisting> + </figure> + + <figure xml:id="sd1_fig_appleSslBugCodeReachability"> + <title>Static code analysis</title> + + <informaltable border="0"> + <tr> + <td><programlisting language="c">... + +if ((err = SSLHashSHA1.update(...)) != 0) + goto fail; + goto fail;</programlisting></td> + + <td>Reachable code</td> + </tr> + + <tr> + <td><programlisting language="c">if ((err = SSLHashSHA1.final(...)) != 0) + goto fail; + +err = sslRawVerify(...); +...</programlisting></td> + + <td>Unreachable code</td> + </tr> + + <tr> + <td><programlisting language="c">fail: + SSLFreeBuffer(&signedHashes); + SSLFreeBuffer(&hashCtx); + return err; +}</programlisting></td> + + <td>Reachable code</td> + </tr> + </informaltable> + </figure> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_staticCodeAnalysisUnreachable"> + <title>Static code analysis</title> + + <qandadiv> + <qandaentry> + <question> + <para>Consider the following snippet:</para> + + <programlisting language="java">int count = 3; +count++; + +if (count < 5) + return; + return; + +System.out.println("Failed!");</programlisting> + + <para>This <xref linkend="glo_Java"/> code mimics the <link xlink:href="https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/">Apple goto fail SSL bug</link>'s structural problem. Since <xref linkend="glo_Java"/> does not offer <code>goto</code> statements we use <code>return</code> instead for terminating the <quote>current</quote> context.</para> + + <para>Copy this code into your <xref linkend="glo_IDE"/> and:</para> + + <orderedlist> + <listitem> + <para>Explain the resulting error. What is wrong? How do you correct this error?</para> + </listitem> + + <listitem> + <para>Explain the <code>count++</code> statement's purpose.</para> + + <tip> + <para>There is no <quote>real</quote> application logic in the given code. It is an example meant to explain formal <xref linkend="glo_Java"/> language features. What happens if you correct the compile time error and in addition purge the <code>count++</code> statement?</para> + </tip> + </listitem> + + <listitem> + <para>What is the underlying idea of these warning and error messages?</para> + </listitem> + </orderedlist> + </question> + + <answer> + <orderedlist> + <listitem> + <para>Like in the original bug the code is poorly indented. Using your <xref linkend="glo_IDE"/>'s auto formatting feature (how?) you get:</para> + + <programlisting language="java">int count = 3; +count++; + +if (count < 5) + return; +return; + +System.out.println("Failed!");</programlisting> + + <para>The second <code>return</code> statement will leave the context unconditionally regardless of the preceding <code>if (count < 5)</code> and the <code>count</code> variable's value in particular. Thus the final <code>System.out.println("Failed!")</code> <emphasis role="bold">can</emphasis> never be reached.</para> + + <para>Removing the erroneous <code>return</code> resolves the error leaving us with happily compiling code:</para> + + <programlisting language="java">int count = 3; +count++; + +if (count < 5) + return; + +System.out.println("Failed!");</programlisting> + + <para>Conclusion: The <link xlink:href="https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/">Apple goto fail SSL bug</link> could not have been occurring in <xref linkend="glo_Java"/> due to language features.</para> + </listitem> + + <listitem> + <para>Removing <code>count++</code> leaves us with:</para> + + <programlisting language="java">int count = 3; + +if (count < 5) <co linkends="sd1_callout_staticIfAlwaysTrue-1" xml:id="sd1_callout_staticIfAlwaysTrue-1-co"/> + return; + +System.out.println("Failed!");</programlisting> + + <calloutlist> + <callout arearefs="sd1_callout_staticIfAlwaysTrue-1-co" xml:id="sd1_callout_staticIfAlwaysTrue-1"> + <para>Compiler warning: <emphasis role="bold">Condition 'count < 5' is always 'true'</emphasis>.</para> + </callout> + </calloutlist> + + <programlisting language="java">int count = 3; +count++; + +if (count < 5) + return; + +System.out.println("Failed!");</programlisting> + + <para>This warning is also due to static compile time code analysis: The count variable's value is not being altered throughout its scope. It could actually be declared <code>static int count = 3</code>. Thus the <code>return</code> inside <code>if (count < 5)</code> will always be executed.</para> + </listitem> + + <listitem> + <para>The underlying idea is preventing programmers from coding carelessly: Even the <code>if (count < 5)</code> statement is most likely an unintended bug.</para> + </listitem> + </orderedlist> + + <important> + <para>Conclusion: Watch out for compiler warning messages and do not ignore them!</para> + + <para>In many cases compiler warnings reveal serious flaws. Correction on average will save you lots of cumbersome time debugging your code.</para> + </important> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + <figure xml:id="sd1_fig_useScannerClass"> <title>User input by <link xlink:href="https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html">Scanner</link></title> @@ -269,88 +593,80 @@ System.out.println("You entered " + value);</programlisting> <para>See <methodname xlink:href="https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextBoolean()">nextBoolean()</methodname>, <methodname><link xlink:href="https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextByte()">nextByte()</link></methodname> and friends.</para> </figure> - </section> - <section xml:id="ex"> - <title>Exercises</title> - - <section xml:id="sw1Conditionals"> - <title>Conditional clauses</title> - - <section xml:id="sd1SectAtTheBar"> - <title>At the bar</title> + <qandaset defaultlabel="qanda" xml:id="sd1QandaAtTheBar"> + <title>At the bar</title> - <qandaset defaultlabel="qanda" xml:id="sd1QandaAtTheBar"> - <qandadiv> - <qandaentry> - <question> - <para>This example uses existing program code to be explained later. You'll implement an interactive application which implements a dialogue with a user asking for input to be entered in a terminal like window as being shown in the following video:</para> + <qandadiv> + <qandaentry> + <question> + <para>This example uses existing program code to be explained later. You'll implement an interactive application which implements a dialogue with a user asking for input to be entered in a terminal like window as being shown in the following video:</para> - <figure xml:id="sd1VideoUsingScannerClass"> - <title>Using a <classname xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html">Scanner</classname> class collecting user input.</title> + <figure xml:id="sd1VideoUsingScannerClass"> + <title>Using a <classname xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html">Scanner</classname> class collecting user input.</title> - <mediaobject> - <videoobject> - <videodata fileref="Ref/Video/scannerUsage.webm"/> - </videoobject> - </mediaobject> - </figure> + <mediaobject> + <videoobject> + <videodata fileref="Ref/Video/scannerUsage.webm"/> + </videoobject> + </mediaobject> + </figure> - <para>A bar uses a software system for picking up orders. The bar will serve just orange juice and beer. For legal reasons the latter will only be served to persons of at least 16 years of age. We show three possible user dialogues:</para> + <para>A bar uses a software system for picking up orders. The bar will serve just orange juice and beer. For legal reasons the latter will only be served to persons of at least 16 years of age. We show three possible user dialogues:</para> - <orderedlist> - <listitem> - <screen>On offer: + <orderedlist> + <listitem> + <screen>On offer: 1=Beer 2=Orange juice Your choice:>1 Tell me your age please:>15 Sorry, we are not allowed to serve beer to underage customers</screen> - </listitem> + </listitem> - <listitem> - <screen>On offer: + <listitem> + <screen>On offer: 1=Beer 2=Orange juice Your choice:>2 o.K.</screen> - </listitem> + </listitem> - <listitem> - <screen>On offer: + <listitem> + <screen>On offer: 1=Beer 2=Orange juice Your choice:>4 Sorry, invalid choice</screen> - </listitem> - </orderedlist> + </listitem> + </orderedlist> - <para>Since you may not yet know how to enable <xref linkend="glo_Java"/> applications asking for user input simply use the following recipe to get started:</para> + <para>Since you may not yet know how to enable <xref linkend="glo_Java"/> applications asking for user input simply use the following recipe to get started:</para> - <programlisting language="java">package start; + <programlisting language="java">package start; import java.util.Scanner; public class BarOrder { - public static void main(String[] args) { - - final Scanner scan = new Scanner(System.in); // Read user input - ... - final int beverageChoice = scan.nextInt(); - - //TODO: complete me! - - scan.close(); - } + public static void main(String[] args) { + + try (final Scanner scan = new Scanner(System.in)) { + System.out.print("On offer:\n 1=Beer\n 2=Orange juice\n\nYour choice:>"); + final int beverageChoice = scan.nextInt(); + //TODO: complete me! + ... + + } // Auto closing scanner + } }</programlisting> - </question> + </question> - <answer> - <programlisting language="java">package start; + <answer> + <programlisting language="java">package start; import java.util.Scanner; @@ -385,38 +701,36 @@ public class BarOrder { scan.close(); } }</programlisting> - </answer> - </qandaentry> - </qandadiv> - </qandaset> - </section> + </answer> + </qandaentry> + </qandadiv> + </qandaset> - <section xml:id="sd1SectLeapYear"> - <title>Leap years</title> + <qandaset defaultlabel="qanda" xml:id="sd1QandaLeapYear"> + <title>Leap years</title> - <qandaset defaultlabel="qanda" xml:id="sd1QandaLeapYear"> - <qandadiv> - <qandaentry> - <question> - <para>We want to write an application telling whether a given year is a leap year or not. The following dialogue may serve as an example:</para> + <qandadiv> + <qandaentry> + <question> + <para>We want to write an application telling whether a given year is a leap year or not. The following dialogue may serve as an example:</para> - <screen>Enter a year:>1980 + <screen>Enter a year:>1980 Year 1980 is a leap year</screen> - <screen>Enter a year:>1900 + <screen>Enter a year:>1900 Year 1900 is no leap year</screen> - <para>You may reuse the user input handling code from the previous example <xref linkend="sd1SectAtTheBar"/>.</para> + <para>You may reuse the user input handling code from the previous example .</para> - <tip> - <para>Read about the Gregorian Calendar which defines rules governing leap years.</para> - </tip> - </question> + <tip> + <para>Read about the Gregorian Calendar which defines rules governing leap years.</para> + </tip> + </question> - <answer> - <para>A first straightforward rule translation based solution reads:</para> + <answer> + <para>A first straightforward rule translation based solution reads:</para> - <programlisting language="java">package start; + <programlisting language="java">package start; import java.util.Scanner; @@ -441,9 +755,9 @@ public class LeapYear { } }</programlisting> - <para>This solution contains two identical print statements. Developers don't favour redundancies. Combining the first two <code>if</code> branches into one resolves the issue:</para> + <para>This solution contains two identical print statements. Developers don't favour redundancies. Combining the first two <code>if</code> branches into one resolves the issue:</para> - <programlisting language="java"> public static void main(String[] args) { + <programlisting language="java"> public static void main(String[] args) { final Scanner scan = new Scanner(System.in); // Read user input System.out.print("Enter a year:>"); @@ -458,39 +772,506 @@ public class LeapYear { System.out.println("Year " + year + " is no leap year"); } }</programlisting> - </answer> - </qandaentry> - </qandadiv> - </qandaset> - </section> + </answer> + </qandaentry> + </qandadiv> + </qandaset> - <section xml:id="sd1SectRomanNumerals"> - <title>Roman numerals</title> + <qandaset defaultlabel="qanda" xml:id="sd1QandaRomanNumeralsIf"> + <title>Roman numerals</title> - <qandaset defaultlabel="qanda" xml:id="sd1QandaRomanNumerals"> - <qandadiv> - <qandaentry> - <question> - <para>Write an application which turns a positive integer values up to and including 10 into <link xlink:href="https://en.wikipedia.org/wiki/Roman_numerals">Roman numeral</link> representation:</para> + <qandadiv> + <qandaentry> + <question> + <para>Write an application which turns a positive integer values up to and including 10 into <link xlink:href="https://en.wikipedia.org/wiki/Roman_numerals">Roman numeral</link> representation:</para> - <screen>Enter a number:>9 + <screen>Enter a number:>9 IX</screen> - <para>If the user enters a value greater than ten the following output is to be expected:</para> + <para>If the user enters a value smaller than 1 or greater than ten the following output is to be expected:</para> - <screen>Enter a number:>14 -Decimal value 14 not yet implemented</screen> - </question> + <screen>Enter a number:>11 +Decimal value 11 not yet implemented</screen> + </question> - <answer> - <para><programlisting language="java"> public static void main(String[] args) { - - final Scanner scan = new Scanner(System.in); // Read user input - System.out.print("Enter a number:>"); - final int number = scan.nextInt(); - scan.close(); + <answer> + <para><programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + + System.out.print("Enter a number:>"); + final int number = scan.nextInt(); + + if (1 == number) { + System.out.println("I"); + } else if (2 == number) { + System.out.println("II"); + } else if (3 == number) { + System.out.println("III"); + } else if (4 == number) { + System.out.println("IV"); + } else if (5 == number) { + System.out.println("V"); + } else if (6 == number) { + System.out.println("VI"); + } else if (7 == number) { + System.out.println("VII"); + } else if (8 == number) { + System.out.println("VIII"); + } else if (9 == number) { + System.out.println("IX"); + } else if (10 == number) { + System.out.println("X"); + } else { + System.out.println("Decimal value " + number + " not yet implemented"); + } +}</programlisting></para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <figure xml:id="sd1_fig_problemNumber2Dayname"> + <title>Converting numbers to day's names</title> + + <para>Task: Convert day's numbers to day's names</para> + + <informaltable border="1"> + <tr> + <td>1</td> + + <td>Monday</td> + </tr> + + <tr> + <td>2</td> + + <td>Tuesday</td> + </tr> + + <tr> + <td>3</td> + + <td>Wednesday</td> + </tr> + + <tr> + <td>4</td> + + <td>Thursday</td> + </tr> + + <tr> + <td>5</td> + + <td>Friday</td> + </tr> + + <tr> + <td>6</td> + + <td>Saturday</td> + </tr> + + <tr> + <td>7</td> + + <td>Sunday</td> + </tr> + </informaltable> + </figure> + + <figure xml:id="sd1_fig_dayNumber2NameByIfElseif"> + <title>Implementing day's number to name</title> + + <programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + System.out.print("Enter a weekday number (1=Monday, 2=Tuesday,...) :>"); + final int number = scan.nextInt(); + + if (1 == number) { + System.out.println("Monday"); + } else if (2 == number) { + System.out.println("Tuesday"); + + ... + + } else if (7 == number) { + System.out.println("Sunday"); + } else { + System.out.println("Invalid number " + number); + } +}</programlisting> + </figure> + + <figure xml:id="sd1_fig_switch"> + <title>Better: The <code>switch</code> statement</title> + + <programlisting language="java">... +switch(number) { + case 1: System.out.println("Monday"); break; + case 2: System.out.println("Tuesday"); break; + case 3: System.out.println("Wednesday"); break; + case 4: System.out.println("Thursday"); break; + case 5: System.out.println("Friday"); break; + case 6: System.out.println("Saturday"); break; + case 7: System.out.println("Sunday"); break; + default: System.out.println("Invalid number " + number); break; +} +...</programlisting> + </figure> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_whyBreak"> + <title>Why <quote>break</quote>?</title> + + <qandadiv> + <qandaentry> + <question> + <para>Do we need <code>break</code> statements in <xref linkend="sd1_fig_switch"/>? Create a complete example as in <xref linkend="sd1_fig_dayNumber2NameByIfElseif"/> but use a <code>switch</code> statement without any <code>break</code>. What do you observe on execution?</para> + </question> + + <answer> + <para>We start coding:</para> + + <programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + System.out.print("Enter a weekday number (1=Monday, 2=Tuesday,...) :>"); + final int number = scan.nextInt(); + switch(number) { + case 7: System.out.println("Sunday"); + case 1: System.out.println("Monday"); + case 2: System.out.println("Tuesday"); + case 3: System.out.println("Wednesday"); + case 4: System.out.println("Thursday"); + case 5: System.out.println("Friday"); + case 6: System.out.println("Saturday"); + default: System.out.println("Invalid number " + number); + } +}</programlisting> + + <para>Execution and entering day number 5 yields:</para> + + <screen>Enter a weekday number (1=Monday, 2=Tuesday,...) :>5 +Friday +Saturday +Sunday +Invalid number 5</screen> + + <para>So the <code>break</code> statements effectively prohibit <quote>fall-through</quote> towards subsequent <code>case</code> labels. Moving <quote>7 / Sunday</quote> to the beginning this becomes even clearer:</para> + + <programlisting language="java">... +switch(number) { + case 7: System.out.println("Sunday"); + case 1: System.out.println("Monday"); + case 2: System.out.println("Tuesday"); + case 3: System.out.println("Wednesday"); + case 4: System.out.println("Thursday"); + case 5: System.out.println("Friday"); + case 6: System.out.println("Saturday"); + default: System.out.println("Invalid number " + number); +} ...</programlisting> + + <para>This time entering number 5 again our output no longer contains <code>"Sunday"</code>:</para> + + <screen>Enter a weekday number (1=Monday, 2=Tuesday,...) :>5 +Friday +Saturday +Invalid number 5</screen> + + <para>Thus fall-through does not depend on numerical <code>case</code> label ordering but solely on their order of appearance.</para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_monthDays2Name"> + <title>Extending to month days</title> + + <qandadiv> + <qandaentry> + <question> + <para>Consider May 2017:</para> + + <informaltable border="1"> + <tr> + <th>Monday</th> + + <th>Tuesday</th> + + <th>Wednesday</th> + + <th>Thursday</th> + + <th>Friday</th> + + <th>Saturday</th> + + <th>Sunday</th> + </tr> + + <tr> + <td>1</td> + + <td>2</td> + + <td>3</td> + + <td>4</td> + + <td>5</td> + + <td>6</td> + + <td>7</td> + </tr> + + <tr> + <td>8</td> + + <td>9</td> + + <td>10</td> + + <td>11</td> + + <td>12</td> + + <td>13</td> + + <td>14</td> + </tr> + + <tr> + <td>15</td> + + <td>16</td> + + <td>17</td> + + <td>18</td> + + <td>19</td> - switch (number) { + <td>20</td> + + <td>21</td> + </tr> + + <tr> + <td>22</td> + + <td>23</td> + + <td>24</td> + + <td>25</td> + + <td>26</td> + + <td>27</td> + + <td>28</td> + </tr> + + <tr> + <td>29</td> + + <td>30</td> + + <td>31</td> + </tr> + </informaltable> + + <para>Write an application converting a given day's number within May 2017 (this may be generalized to arbitrary months) to its name e.g.:</para> + + <screen>Enter a day's number:>23 +Tuesday</screen> + + <tip> + <para>The modulo operator <quote>%</quote> is your friend.</para> + </tip> + </question> + + <answer> + <para>With respect to <xref linkend="sd1_fig_switch"/> a small modification is being required</para> + + <programlisting language="java">... +switch(day % 7) { + case 1: System.out.println("Monday"); break; + case 2: System.out.println("Tuesday"); break; +...</programlisting> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <figure xml:id="sd1_fig_switchOnString"> + <title>Switching on strings</title> + + <para>Starting from <xref linkend="glo_Java"/> 7 <code>switch</code> statements using <classname xlink:href="https://docs.oracle.com/javase/7/docs/api/java/lang/String.html">String</classname> based <code>case</code> labels are allowed:</para> + + <programlisting language="java">String month, season; +... + +switch(month) { + case "March": case "April": case "May": + season = "Spring"; break; + + case "June": case "July": case "August": + season = "Summer"; break; + + case "September": case "October": case "November": + season = "Autumn"; break; + + case "December": case "January": case "February": + season = "Winter"; break; + } +}</programlisting> + </figure> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_dayname2number"> + <title>Converting day's names to numbers.</title> + + <qandadiv> + <qandaentry> + <question> + <para>Consider the reverse problem to <xref linkend="sd1_fig_problemNumber2Dayname"/>: We want to map a given day's name to its number as in the following example:</para> + + <screen>Enter a weekday (Monday to Sunday):>Friday +5</screen> + + <para>Issue an error message in case an inappropriate text is being entered:</para> + + <screen>Enter a weekday (Monday to Sunday):>July +Unknown day name July</screen> + + <tip> + <orderedlist> + <listitem> + <para>Starting from <xref linkend="glo_Java"/> 7 switch statements using strings are allowed.</para> + </listitem> + + <listitem> + <para>You may read strings into your application using <classname xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html">Scanner</classname>.<methodname xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#next--">next()</methodname>;</para> + </listitem> + </orderedlist> + </tip> + </question> + + <answer> + <programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + System.out.print("Enter a weekday (Monday to Sunday):>"); + final String day = scan.next(); + switch(day) { + case "Monday": System.out.println(1); break; + case "Tuesday": System.out.println(2); break; + case "Wednesday": System.out.println(3); break; + case "Thursday": System.out.println(4); break; + case "Friday": System.out.println(5); break; + case "Saturday": System.out.println(6); break; + case "Sunday": System.out.println(7); break; + default: System.out.println("Unknown day name " + day); break; + } +}</programlisting> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <qandaset defaultlabel="qanda" xml:id="sd1_qanda_dayCategories"> + <title>Day categories.</title> + + <qandadiv> + <qandaentry> + <question> + <para>We want to group working days into categories:</para> + + <informaltable border="1"> + <tr> + <th>Day</th> + + <th>Category</th> + </tr> + + <tr> + <td>Monday</td> + + <td>Start of work week</td> + </tr> + + <tr> + <td>Tuesday</td> + + <td rowspan="3">Midweek</td> + </tr> + + <tr> + <td>Wednesday</td> + </tr> + + <tr> + <td>Thursday</td> + </tr> + + <tr> + <td>Friday</td> + + <td>Start of work week</td> + </tr> + + <tr> + <td>Saturday</td> + + <td rowspan="2">Weekend</td> + </tr> + + <tr> + <td>Sunday</td> + </tr> + </informaltable> + + <para>Example execution:</para> + + <screen>Enter a weekday (Monday to Sunday):>Wednesday +Midweek</screen> + + <tip> + <para>Sometimes omitting <code>break</code> statements allowing for fall-through is your friend.</para> + </tip> + </question> + + <answer> + <programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + System.out.print("Enter a weekday (Monday to Sunday):>"); + final String day = scan.next(); + switch(day) { + case "Monday": System.out.println("Start of work week"); break; + case "Tuesday": + case "Wednesday": + case "Thursday": System.out.println("Midweek"); break; + case "Friday": System.out.println("End of work week"); break; + case "Saturday": + case "Sunday": System.out.println("Weekend"); break; + default: System.out.println("Unknown day name " + day); break; + } +}</programlisting> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + + <qandaset defaultlabel="qanda" xml:id="sd1QandaRomanNumeralsSwitch"> + <title>Roman numerals, using <code>switch</code></title> + + <qandadiv> + <qandaentry> + <question> + <para>Re-implement <xref linkend="sd1QandaRomanNumeralsIf"/> using a switch statement rather then an <code>if ... else if ... else</code>.</para> + </question> + + <answer> + <para><programlisting language="java">try (final Scanner scan = new Scanner(System.in)) { + + System.out.print("Enter a number:>"); + final int number = scan.nextInt(); + + switch (number) { case 1: System.out.println("I"); break; case 2: System.out.println("II"); break; case 3: System.out.println("III"); break; @@ -501,16 +1282,19 @@ Decimal value 14 not yet implemented</screen> case 8: System.out.println("VIII"); break; case 9: System.out.println("IX"); break; case 10: System.out.println("X"); break; + default:System.out.println("Decimal value " + number + " not yet implemented"); break; - } - }</programlisting></para> - </answer> - </qandaentry> - </qandadiv> - </qandaset> - </section> - </section> + } +}</programlisting></para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + </section> + + <section xml:id="ex"> + <title>Exercises</title> <section xml:id="sd1StatementsLoops"> <title>Loops</title>