CS 151 - Introduction to Data Structures

Lab 3

A bit of this and a bit of that

Three topics for today: copying files, more with CVS files, and recording output. (Recording is at the end of the lab.)

Copying files

Copying files (mostly review): the UNIX command to copy files is cp. For instance
	cp x y
    
would make a copy of the file named x under the name y (assuming x exists in the current directory).
	cp DIR1/x DIR2/y
makes a copy of the file named x that is in the the directory DIR1 and puts that copy into a file named y in the directory DIR2. (Assuming x, DIR1 and DIR2 exist.)
	cp DIR1/*.java DIR2/
will make a copy of every file that end with .java in DIR1 and put those copies into DIR2 (assuming DIR1 and DIR2 exist.) Recall that * is a UNIX wildcard, it allows you to say something like “all” or in this case all that ends in .java.

Further specialization is possible — for instance in the previous command replacing *java with A*.java would copy only those files that start with A and end in .java

If you want to copy everything in a directory you can use
	cp DIR1/* DIR2/

Directories in UNIX:

Everywhere above where you see either DIR1 or DIR2, you can put in a lot more that just one word. For example, your “home directory” has a name like “/home/YOURUNIXLOGIN” e.g. /home/gtowell.

Note that scp is a generalization of cp which allows you to copy from one machine to another so all of the above applies to scp as well

More about ls

ls has a short and long form and a colorful form (and a lot of other things as well). For instance
ls
shows the contents of the current directory. On the other hand,
    ls DIR1
shows the contents of the directory DIR1 assuming DIR1 exists (within the current directory). For example:
    gtstudent@comet:~$ ls /home/gtowell
    383							labstatus.txt
    aaaa						local
    Android						mail
    AndroidStudioProjects		mpub
    blah						mpublic_html
One annoyance of ls is that, in the default presentation, it is difficult to distinguish directories from files. (This is by design in Unix.) My pattern to help with this problem is to name directories with an initial capital letter and regular files with an initial lower case letter. Sadly, I do not always follow my own convention. Fortunately, ls can help
ls Site
shows all of the files the directory Site (that is within the current directory).
ls --color Site 
shows the same listing but with colors assigned to different types of things. (regular files are black, directories are blue, etc)

ls also has a long form that is very useful. To use the long form of ls, just add “-l” to your command. Ie,
ls -l DIR1 
The long form shows the names of the files and their size (in bytes) along with some other info. (Generally bytes == number of characters.) For example:
    gtstudent@comet:~$ ls -l
    total 372
    drwxr-xr-x  3 gtstudent students   4096 Jan 11  2022 383
    -rw-r--r--  1 gtstudent students     11 Mar  8  2021 aaaa
    drwxr-xr-x  3 gtstudent students   4096 Dec 11  2020 Android
    drwxr-xr-x  3 gtstudent students   4096 Dec 11  2020 AndroidStudioProjects
    drwx--x--x  2 gtstudent students   4096 Dec 11  2020 blah
    drwxr-xr-x  4 gtstudent students   4096 Dec  9  2021 charlie-crawford
    -rw-r--r--  1 gtstudent students   1272 Feb 10  2022 CLA.class
    -rw-r--r--  1 gtstudent students    589 Feb 10  2022 CLA.java
    -rw-r--r--  1 gtstudent students   1044 Dec 11  2020 config
So the file aaaa uses 11 bytes of space. In the long listing, lines that start with a "d" indicate a directory. (You can also colorize "ls -l --color")

UNIX capturing the output of programs into files

It is common to create a file to hold the output of your program. You can do this in UNIX using something called IO redirection. The simplest form of IO redirection is to cause what would have appeared on the screen to instead be written to a file. For instance, using the HelloWorld program from Lab1
    UNIX> javac HelloWorld.java	
    UNIX> java HelloWorld > hello.txt	
    UNIX> cat hello.txt
The first line compiles HelloWorld.java; the second line runs it, capturing the output into the file hello.txt. (This probably does not work in Windows) The final line just prints that file to the screen (recall the UNIX cat command from Lab 2). All of the work is done by the ">" which the operating system interprets as "take everything that is being written to standard output (in Java this is System.out) and put it in a file with the name given after the >". The name of the file is completely your choice it could be "a" or "thisistheoutfilefromhelloworld". Similarly the extension ".txt" is your choice, UNIX does not care (much).

Now make a mistake while retyping the second line and give the name of a class file that does not exist. The resulting error message still appears; it does not go into your hello.txt file. This is because the UNIX ">" directive writes standard output (i.e. System.out in Java) to a file. It handles standard error (System.err in Java) separately. To capture standard error to a file use "2>". For example
	UNIX> java HelloMistake > reader.txt 2> err.txt 
    
You can use one, either, or both of ">" and "2>".

Note that each time you use ">" it creates a new file, replacing/overwriting the file that was there. Sometimes you want to add a new run a file rather than replacing. To do so, use ">>". for example:
    UNIX> java HelloWorld > hello.txt
    UNIX> java HelloWorld >> hello.txt
The result of this is to have two runs the HelloWorld program with output in the same file.

Finally, sometimes you do not care about the output, you just do not want it on the screen or even in a file (which you would then have to delete). In this case do the following:

	UNIX> java HelloWorld > /dev/null
/dev/null is effectively a trash can; so this command say to take the stuff that the program writes to Standard.out and throw it away without every showing it to me.

Script files instead of Output redirection

A problem with the above-described redirecting the output of the program into a file is that it captures all output of the program to a file. Hence, a program with user interaction is problematic because all instructions to the user go to a file rather than to the screen. So if you want to capture to a file, AND capture the user interaction you can use the unix script command. For example:
UNIX> script aa.txt
UNIX> java HelloWorld
UNIX> exit
This will capture everything that went to the screen between "script aa.txt" and "exit" in the file aa.txt. (Both output from the program and user input.) On future assignments I will ask for sample output from your program. Any of the techniques shown here will work. (As an aside, copy and paste will also work.) On a particular assignment it may be easier to use one or the other approach.

Trivial Blackjack

The goal of the game of trivial blackjack is to get as close as possible to 21 without going over. You start by getting two numbers in the range 1..10 where the odds of getting any number are the same. You are then repeatedly asked if you want another number until you say no, or your total equals or exceed 21. (This is a simplification over the card game ... Aces are always 1, there are no face cards and there is no dealer.)

The play of the game is shown in the following trace.
    geoffreytowell@Geoff2020Mac a1 % java TrivialBlackjack
    First card: 1
    Second card: 7    Total: 8
    Another card? [y/n]:y
    Next card: 1    Total: 9
    Another card? [y/n]:y
    Next card: 4    Total: 13
    Another card? [y/n]:y
    Next card: 10    Total: 23
    BUSTED
    geoffreytowell@Geoff2020Mac a1 % java TrivialBlackjack
    First card: 9
    Second card: 1    Total: 10
    Another card? [y/n]:y
    Next card: 8    Total: 18
    Another card? [y/n]:y
    Next card: 3    Total: 21
    BLACKJACK
    geoffreytowell@Geoff2020Mac a1 % java TrivialBlackjack
    First card: 9
    Second card: 3    Total: 12
    Another card? [y/n]:y
    Next card: 8    Total: 20
    Another card? [y/n]:n
    CHICKEN!!

Recall from homework 2 that you can get user input using Scanner as follows:

    Scanner scnr = new Scanner(System.in);
    while (true) {
        System.out.print("Give me a string (q to quit):");
        String l = scnr.next();
        if (l.equals("q")) {
            break;
        }
        System.out.println("You entered " + l);
    }
You can get a random number in the range 1..10 as follows:
    Random rand = new Random();
    int card = 1+rand.nextInt(10);
Write a program with which you can play TrivialBlackjack. (You may put the entire "game" into the main method). Capture the output of several games of TrivialBlackjack into a file.

If you have time, make the game a little more realistic by adding face cards and correctly handling aces. The challenge with facecards in that you are adding 3 more card types (Jack, Queen and King), but they all have the value of 10. In TrivialBlackjack as described above, the odd of getting a 2 are 1 in 10 and the odds of getting a 10 are 1 in 10. With this modification, the odds of getting a 2 are 1 in 13; the odds of getting a card with a value of 10 is 4 in 13.

What to Hand In:

Send email to gtowell@brynmawr.edu with the following: