Functional Problem Solving (CSC 151 2014S) : Labs

# Laboratory: Files

Summary: In this laboratory, we explore file creation, input, and output in Scheme.

## Preparation

a. Scan through this lab to determine what kinds of tasks you'll need to complete.

b. You should also scan through the reading on files in Scheme.

c. Open the reference on files in Scheme in a separate window.

d. Start the GIMP and MediaScript.

e. Make a copy of `files-lab.rkt`, the code for this lab.

## Exercises

As you may recall from the reading, we have prepared two simple files for simple exploration of input and output, `/home/rebelsky/glimmer/samples/hi.txt` and `/home/rebelsky/glimmer/samples/sample.txt`.

a. Using a sequence of commands in the interaction window, read all the characters from `hi.txt`. For example,

````>` ```(define source
(open-input-file "/home/rebelsky/glimmer/samples/hi.txt"))```
`>` `(read-char source)`
`#\H`
...
`>` `(read-char source)`
`#<eof>`
`>` `(close-input-port source)`
```

b. Using a sequence of commands in the interaction window, read all the characters from `sample.txt`.

c. Using a sequence of commands in the interaction window, read all the values from `sample.txt` (use `read` rather than `read-char`).

d. Using a sequence of commands in the interaction window, read all the values from `hi.txt`.

### Exercise 2: Reading from Files, Revisited

The file `/home/rebelsky/glimmer/samples/scheme-values.txt` contains the following:

```23
A
"A"
#\A
(1 2 3)
```

a. Use `read-char` to confirm that it has that form.

````>` `(define inport (open-input-file "/home/rebelsky/glimmer/samples/scheme-values.txt"))`
`>` `(read-char inport)`
`#\2`
`>` `(read-char inport)`
`#\3`
`>` `(read-char inport)`
`#\newline`
`>` `(read-char inport)`
`#\A`
...
`>` `(close-input-port inport)`
```

b. What values do you expect repeated calls to `read` to extract from that file?

````>` `(define inport (open-input-file "/home/rebelsky/glimmer/samples/scheme-values.txt"))`
`>` `(read inport)`
...
`>` `(close-input-port inport)`
```

d. What type (e.g., number, list, string, etc.) does each value extracted from that file have?

### Exercise 3: Summing Values

The file `/home/rebelsky/glimmer/samples/numbers.txt` contains five hundred and twenty-eight natural numbers.

a. Use `sum-of-file` from the reading to determine their sum.

b. How would you quickly determine if your attempt to sum those numbers was correct?

Citation: That file was copied from a similar file produced by Mr. Stone.

### Exercise 4: File Length

Using `sum-of-file` (and its helpers) as a pattern, write a Scheme procedure, ```(file-size "file-name")``` that takes as argument a string that names a file and returns the number of characters in that file (that is, the number of times that `read-char` can be called to read a character from the file without returning the end-of-file object).

### Exercise 5: Missing Files

Find out what happens if `sum-of-file` or `file-size` is given a string that does not name any existing file.

### Exercise 6: Creating Files

In the interactions pane, write a series of expressions that will create a file, `my-info`, with the following lines (substituting your own name and major).

```Name: _last_, _first_
Major: _major-or-undeclared_
```

### Exercise 7: Reusing Output Files

The Scheme standard says that if you try to open an output port to a file that already exists, “the effect is unspecified”, i.e., anything might happen. Hence, designers of a particular implementation of Scheme are free to do what they choose.

a. Find out through experimentation what Racket does in this situation.

b. Search the Web for the Racket documentation on `open-output-file` and find out how to overwrite an existing file.

### Exercise 8: Writing to Files, Revisited

Write a Scheme procedure, ```(dump-info file-name last-name first-name major)``` that, given four strings as parameters, writes the following to the file named by `file-name`,

```Name: last-name, first-name
Major: major
```

## For Those With Extra Time

### Extra 1: Reading All Lines

Write a procedure, ```(read-lines filename)```, that takes the name of a file as a parameter and returns a list of all the lines of the file (with each line represented as a string). You can certainly use the `read-line` procedure from the reading as a helper for `read-lines`. You might use `sum-of-file` as a pattern for `read-lines`.

### Extra 2: Displaying Files

Write a procedure, ```(display-file filename)```, that takes the name of a file as a parameter and displays the contents of the file with each line preceded by its line number. You may find it useful to call upon the previous procedure to do the reading.

### Extra 3: Finding Divisors

Use the `store-divisors` procedure from the reading to draw up a list of the divisors of 120, storing them in a file named `divisors-of-120`. Examine the file afterwards and confirm that the answer is correct.

By the way, don't give this procedure an extremely large number as argument -- it's much too slow. There are more efficient ways to find divisors!

### Extra 4: Counting Characters

Write a Scheme procedure that takes as arguments two file names (an input file and an output file), counts the number of occurrences of each vowel in the input file, and writes the result to the output file. Note that the output file should have the following form (with numbers in place of the number signs):

```a: ###
e: ###
i: ###
o: ###
u: ###
```

If you have time or inclination, extend your procedure to deal with all 127 ASCII characters.

Samuel A. Rebelsky, rebelsky@grinnell.edu

Copyright (c) 2007-2014 Janet Davis, Samuel A. Rebelsky, and Jerod Weinman. (Selected materials are copyright by John David Stone or Henry Walker and are used with permission.)

This work is licensed under a Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit `http://creativecommons.org/licenses/by-nc/3.0/` or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.