Tutorial 2) Part 3: For-loops, Nested if-else statements

In programming, a for loop is a control flow statement specifying iteration over a list of objects that executes a block of code repeatedly. In the Unix C shell, the foreach routine is useful for operating on a set of data files. The loop iterates for each argument in parentheses, setting the variable equal to each filename found in parenthesis. The * wildcard can iterate over each file in your current directory:

touch list # initialize file named list

foreach file (*)

echo $file >> list

end

cat list

Here a character string is being stored in the variable file during each iteration of the loop. The syntax for manually storing a string variable in C shell would be:

set file=filename

echo $file

set str = fo g

echo $str

set str="fo g" overwrite the str variable with a longer string

echo $str

Q3: Experiment with interchanging set and @ with successive addition operations as shown in the examples below. What happens and why?

set i=3+4

echo $i

set i=$i+1

echo $i

@ i= $i + 1 because i is a string, we can't do integer arithmetic

@: Badly formed number.

@ j = 10

set j=$j+3

echo $j

set text=100

@ text++ smart shells convert characters to an integer if possible

echo $text

In the old days of programming, there were GOTO control statements, allowing one to jump arbitrarily from one part of the program to another. This branching is confusing and is in contrast to good "structured" programming, which has now become a best practice in coding. Like the foreach and while loops, structures should have one entry point at the top and one exit point at the bottom (not be multi-branched).


In addition to for and while loops, if-then-else conditional statements allow you to write any program without GOTO statements. An if-then construct evaluates a statement to be TRUE (Boolean stored as '1') or FALSE (stored as '0'). The statements within the if-then block are only performed if TRUE, otherwise the subsequent else block (optional) is performed when the statement evaluated as False.


Download the class executable script: Files: class.csh

In your terminal we will move it from where your Internet Browser default downloads files to (Downloads/) and into your Unix home directory so we can use it..

Find class.csh on your hard drive:

PC: cd /cygdrive/c/Users/username/Downloads

Mac: cd ~/Downloads

PC/Mac: ls -lrt confirm file was downloaded

cp class.csh ~/day2 copy and rename file inside day2

cd ~/day2

ls -lrt confirm the file was copied

cat class


--- ### If the download didn't work.. you can always copy the code below into a Vi terminal..

vim class

Tap the letter i to enter insert mode.

Select the text below, ^c to copy it, click on your Terminal and hit ^v to paste (copy-and-paste may not work in your Vim).

class.csh code:

#!/bin/csh -f

if ($#argv == 0) then

echo "No number to classify"

else if ($#argv > 0) then

@ number = $argv[1]

if ($number < 0) then

@ class = 0

else if (0 <= $number && $number < 100) then

@ class = 1

else if (100 <= $number && $number < 200) then

@ class = 2

else

@ class = 3

endif

echo The number $number is in class $class

endif

Hit escape to exit Vi insert mode and return to command mode. In command mode, write and quit the file (only write it if you're modifying a file):

:wq

--- ### ---

Note in the code above how multiple if-then and/or else-if (elif in python) statements can be nested inside of each other. Consistent spacing between columns is crucial for determining the logic structure.

We downloaded class as an ordinary text file. To run it as a shell script, you need to give yourself, the user, execute permissions (x) using the change mode command.


chmod u+x class the user is added execute permissions

ls -lrt

-rwxr--r-- 1 rhills 438738691 405 Jun 16 2015 class


ls -lrtFG

-rwxr--r-- 1 rhills 405 Jun 16 2015 class*

If you don't see the x in the 4th character (execute privileges), try:

sudo chmod u+x class sudo executes a command as superuser (Administrator)

Let's execute our program and test different integers as input to the program. The program expects us to pass an integer variable (-5 etc.) on the command line at the time of execution. A single dot (.) is needed in front of the class filename so that Unix will look in the current directory to run this program (this is a safety feature to prevent you from running non-system code).

./class

./class -1

./class 99

./class 199

./class 200000

./class 20000000000000000000

./class 200000000000000000000

./class 2.5

Q4: Looking at the source code in class.csh and rationalizing the above, explain why the last three outputs are incorrect for the integer variable. What's the largest positive or negative number the program can accept?


Some programs can accept (or require) two or more command arguments separated by spaces:

ls ../day1 . (space before single dot)

For unix programs, the list of arguments specified on the command line is stored as a vector array (argv in class.csh, argument vector). For example in C shell:

set array = ("arg1" arg2 3)

echo $array

echo $array[2] # the brackets are calling (referencing) the second element of the array

arg2

echo $#array #the pound sign returns the length (number of elements) in the array. This is useful for error checking, as in when class.csh complains if it doesn't see an input number (line 2 of code: if-then statement).

3

Arrays are useful when you have a large number of data and don't want to create extra variables.


Q5a. Looking at the nested if-then statements in the CLASS program, which lines of code are executed before the program terminates if you don't specify an argument when calling the program? What happens if you give CLASS two arguments?


The else statements allow us to treat each possible input case specified to prevent the program from terminating due to an error. Copy the program to a separate program:

cp class class2

vim class2 Edit class2 to make a new program...


Q5b. Change the function of some statements in class2 to create a new result obtained by the program. Don't just change the category cutoffs. For example, you could add in a fifth category or enable the program to test two numbers on the same command line. The final program should not crash (terminate without completely executing) or give a Unix shell error, but may give a misleading result. Explain in which situations your modified program arrives at a different result than the original program.

./class2 <input numbers> show how your output is different

diff class class2

The diff command will show lines that you've changed. With syntax highlighting on, you could even try:

vim -d class class2

You've now opened two Vi instances (switch between them using Control-W-W). Try scrolling the cursor in one using the hjkl keys. When you're done, type :q enter followed by :q enter to quit both windows.


If-then statements can employ logical operators. For example AND: '&&' means only if both conditions are true, and OR: '||' which evaluates successfully if either or both conditions are true. There is also negation (!), identity (==), etc. (>=, <=).

Logical operators in C shell:

@ j = 1

echo $j

if ( $j == 1 ) echo true

if ( $j != 2 ) echo true


@ k = 4

if ( $j == 1 && $k == 4 ) echo true

if ( $j == 1 && $k == 2 ) echo true

if ( $j == 0 || $k == 4 ) echo true


Download and view the grade program: Files: grade.err


Q6a. Which lines of code are executed in the grade program for a score of 80?

Q6b. Debug and test the grade.err program in your terminal.

Q6c. Write the Unix commands to give it execute access and run the program.

So that concludes are basic discussion of C shell, because it's a pretty basic shell. The real power of C shell is using it to automate and interface with other programs. One of these is the Unix command awk (or gawk, GNU awk), which will allow us to do floating point calculations.

Proceed to: Part 4