D (The Programming Language)/d2/Conditionals and Loops

Lesson 10: Conditionals and Loops

edit

Conditionals and loops are essential for writing D programs.

Introductory Code

edit

Palindrome Checker

edit
module palindromes;

import std.stdio;

bool isPalindrome(string s)
{
    int length = s.length;
    int limit = length / 2;
    for (int i = 0; i < limit; ++i)
    {
        if (s[i] != s[$ - 1 - i])
        {
            return false;
        }
    }
    return true;
}

void main()
{
    string[] examples = ["", "hannah", "socks", "2002", ">><<>>", "lobster"];
    foreach(e; examples)
    {
        if(!e.length) continue;  // skip that empty string

        if(isPalindrome(e))
            writeln(e, " is an example of a palindrome.");
        else
            writeln(e, " is an example of what's not a palindrome.");
    }
    while(true)
    {
        write("Type any word: ");
        string input = readln();
        if(input.length <= 1)  // length == 1 means input == "\n"
            break;  // nothing was typed
        input = input[0 .. $-1];  // strip the newline
        if(isPalindrome(input))
            writeln(input, " is a palindrome.");
        else
            writeln(input, " is not a palindrome.");
    }
}

More Conditionals and Branching

edit
import std.stdio;

string analyzeHoursOfSleep(int hours)
{
    if(!hours) return "You didn't sleep at all.";
    
    string msg = "";
    switch(hours)
    {
        case 1,2,3:
            msg ~= "You slept way too little!  ";
            goto case 7;
        case 4: .. case 6:
            msg ~= "Take a nap later to increase alertness.  ";
        case 7:
            msg ~= "Try to go back to sleep for a bit more.  ";
            break;
        default:
            msg ~= "Good morning.  Grab a cup of coffee.  ";
    }
    return msg ~ '\n';
}

void main()
{
    writeln(analyzeHoursOfSleep(3));
    writeln(analyzeHoursOfSleep(6));
    writeln(analyzeHoursOfSleep(7));
    writeln(analyzeHoursOfSleep(13));
    
    int i = 0;
L1: while(true)
    {
        while(true)
        {
            if(i == 3)
                break L1;
            i++;
            break;
        }
        writeln("Still not out of the loop!");
    }
}

/*
Output:
You slept way too little!  Try to go back to sleep for a bit more.

Take a nap later to increase alertness.  Try to go back to sleep for a bit more.

Try to go back to sleep for a bit more.

Good morning.  Grab a cup of coffee.

Still not out of the loop!
Still not out of the loop!
Still not out of the loop!
*/

Concepts

edit

The if and else Statements

edit

Using if allows you to make part of your code only execute if a certain condition is met.

    if(condition that evaluates to true or false)
    {
        // code that is executed if condition is true
    } else {
        // code that is executed if condition is false
    }

In fact, if the section of code that's inside the if or else is only one line long, you can omit the curly brackets.

    if(condition1) do_this();
    else if(condition2) do_that();  // only executed if condition1 is false, but
    // condition2 is true
    else do_the_other_thing();  // only executed if both condition1 and condition2 are false

As a result, this is often seen:

   if (condition1) {
       do_something1();
       something_more1();
   } else if(condition2) {
       do_something2();
       something_more2();
   } else if(condition3) {
       do_something3();
       something_more3();
   } else if(condition4) {
       do_something4();
       something_more4();
   } else {
       do_something_else();
   }

The Condition

edit

The condition that goes inside of the parentheses in conditional statements such as if can be anything convertible to bool. That includes integral and floating-point types (true if nonzero, false if otherwise) and pointers (null is false, and dynamic arrays (always true).

The while Loop

edit

A while loop will allow you to repeat a block of code as long as a certain condition is met. There are two forms of the while loop:

   while(condition1) {
       do_this();
   }

and

   do {
       do_this();
   } while(condition1)

The difference is, in the first example, if condition1 is false, do_this is never called, while in the second example it would be called once (the conditional check happens after the code is executed once).

The foreach Loop

edit

This loop is for iteration. Take a look at these two ways to use foreach:

foreach(i; [1,2,3,4]) {
    writeln(i);
}
foreach(i; 1 .. 5) { writeln(i); }  // equivalent to above

The for Loop

edit

This type of looping is the most complex, but it is also the one that gives a lot of control. It is defined in the same way as other C-like languages:

   for(initialization; condition; counting expression) { ... }

The initialization expression is executed only once during the beginning. Then condition is checked to be true or false. If it is true, the code inside of the conditional block (inside of the brackets) is executed. After that execution, the counting expression is executed. Then, the condition is checked, and if it is true, the loop continues. For example:

for(int i=0; i <= 5; i++)
{
    write(i);
}
// output: 012345

You can even omit parts of what goes inside the parentheses of the for. These two are equivalent:

for(int i=0; i==0; ) {
    i = do_something();
}
int i = 0;
while(i == 0) {
    i = do_something();
}

break and continue

edit

These are two statements that are used inside of loops.

The break statement breaks out of the loop. Whenever the break statement is encountered, the loop is immediately exited. This statement can go inside of while, for, foreach, and switch blocks (you will learn about those later).

The continue statement causes a loop to restart at the beginning. Let's see, through code, exactly how this works. This code example counts to 7 but skips 5.

for(int i = 0; i <= 7; i++)
{
    if(i == 5) continue;
    writeln(i);
}

Switches and More

edit

D allows absolute branching with labels and goto.

int i = 0;
looper:  // this is a label
write(i);
i++;
if(i < 10) goto looper;
writeln("Done!");
// 0123456789Done!

Do not use these unless if you have to. Code that uses labels can most often be written with more readable looping constructs, like for, while, and foreach.

There is something in D, C and C++ called the switch. D's switches are actually more powerful than C and C++'s switches.

switch(age)
{
   case 0,1:  // if(age == 0 || age == 1) { ... }
       writeln("Infant");
       break;
   case 2,3,4:  // else if (age == 2 || age == 3 || age == 4) { .. }
       writeln("Toddler");
       break;
   case 5: .. case 11:
       writeln("Kid");
       break;
   case 12:
       writeln("Almost teen");
       break;
   case 13: .. case 19:
       writeln("Teenager");
       break;
   default:  // else { .. }
       writeln("Adult");
}

Note that you must have a break in order to get out of the switch. Otherwise, fall-through occurs. Also, you can use goto.

int a = 3;
switch(a)
{
    case 1:
        writeln("Hello");
    case 2:
        writeln("Again");
        break;
    case 3:
        goto case 1;
    default:
        writeln("Bye");
}
/* output: Hello
           Again
*/

Strings can be used in case. This is a feature that's not in C or C++.

else

edit

(It doesn't seems to work in recent compilers).
You can use else for foreach, while, and for loops, too. If any of those loops have an else clause, then the else is only executed if the loop terminates normally (i.e. not with break).

int[] arr = [1,2,3,5,6];
foreach(item; arr)
{
    if(item == 4) break;
}
else
{
    writeln("No four found.");
}

//Output: No four found.