Homework 2 Answers Due Date: Monday, April 29, 2002, at 11:59PM Points: 100 UNIX System 1. (10 points) What program is running as process #1? Type ps ax and look for the process with a PID of 1. Then look in the COMMAND field to see it is the program init [5]. 2. (15 points) Suppose I have a file called x in my current working directory. File y is a (hard) link to this file, and file z is a symbolic link to it also. I now give the command: mv x a What would the outputs of the following commands be, and why? a. cat x b. cat y c. cat z a. As there is no file named x in the current working directory, this command gives an error message (x: No such file or directory). b. When you move a file, you rename it; the contents of that file are unaffected. Further, any (hard) links to that file continue to pointo to the contents of that file, even though it is renamed. So, this command simply prints the contents of the file a. c. A symbolic link contains the name of a file. When the file x was moved, its name changed. Hence, the symbolic link z points to a non-existant file. So, the command will give an error (z: No such file or directory). C Programming 3. (25 points) Write a C program named words.c that reads a string from stdin as words, and prints each word and its line number on stdout. Loop until stdin s EOF, then terminate. A word is defined to be any contiguous sequence of alphanumeric characters. Use the fgets function to read the input a line at a time. Your program should handle lines of up to 100 characters. Don t bother to check for longer lines; you'll fix that in a later program. Your program should print one word per line. For example: Sample stdin Hello, there, my old friend! How are you today? I am very well, thank you! Goodbye... Corresponding stdout 1 Hello 1 there 1 my 1 old 1 friend 2 How 2 are 2 you 2 today 3 I 3 am 3 very 3 well 3 thank Version of April 28, 2002 10:15 pm Page 1 of 6
3 you 4 Goodbye A Word Listing Program Problem: Given input, print all the words, one per line, and put the line number in front of the word. A "word" is a maximal sequence of alphanumeric characters. Author: Matt Bishop (bishop@cs.ucdavis.edu)1/5/94 #include <stdio.h> #include <ctype.h> this is the main routine arguments: ignored return: exits with 0 function: read from stdin, break each line into words, and print them, one per line, line number in front exceptions: none void main(void) char line[101]; input line register int lineno = 0; current line number register char p; current position in line read the file a line at a time while(fgets(line, 101, stdin)!= NULL) begin at the beginning of a new line lineno++; p = line; loop until end of line while(p) skip leading non-word stuff while (p &&!isalnum(p)) p++; stopped at word; print it if (isalnum(p)) print the line number Version of April 28, 2002 10:15 pm Page 2 of 6
printf("%5d ", lineno); print the word followed by a newline while (isalnum(p)) putchar(p++); putchar('\n'); say goodbye nicely exit(0); 4. (25 points) The Fibonacci numbers play an important role in biology, mathematics, and other sciences. The first two numbers of the sequence are 0 and 1, and the numbers of the sequence are formed by adding the two previous numbers; so, the first few terms of the seuence are 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,. Please write a program which takes an integer n as a command line argument, and prints the first n numbers of the sequence. fib.c Matt Bishop This program prints out the first n Fibonacci numbers. If n is too large, you get overflow; but that's not my problem (buy a bigger machine)! Modification history: 1.0 Matt Bishop original 2.0 Matt Bishop modified to use recursion #include <stdio.h> This is the routine to print the Fibonacci numbers It just calls a function to compute each one, and prints the result. void main(int argc, char argv) int n; number of Fibonacci numbers to print register int i; counter in a for loop check the invocation if (argc!= 2) fprintf(stderr, "Usage: %s <integer>\n", argv[0]); be sure the single argument is a non-negative integer Version of April 28, 2002 10:15 pm Page 3 of 6
Debugging if (sscanf(argv[1], "%d", &n)!= 1 n < 0) fprintf(stderr, "%s: argument must be a nonnegative integer\n", argv[0]); now do the Fibonacci series. for(i = 0; i < n; i++) printf("%10d\n", fib(i)); exit nicely exit(0); fib: return the n-th Fibonacci number arguments: int n index of the Fibonacci number to return return: the n'th Fibonacci number output: none exceptions: none int fib(int n) stopping point: F0 = 0 and F1 = 1 if (n == 0 n == 1) return(n); otherwise, Fn = Fn-1 + Fn-2 return(fib(n - 1) + fib(n - 2)); 5. (25 points) What does the following program do when you run it? Comment it, expanding each argument of the printf in your comment so that anyone can understand what each argument is in simplest form. Just make one header comment, and do not clean up the program! main() printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60); It works like this: (1) unix is a macro that evaluates to 1. (2) &unix["\021%six\012\0"] == &1["\021%six\012\0"] == &"\021%six\012\0"[1] == "%six\012\0" == "%six\n" as \012 == ^J == \n and "\0" is a NUL, ending the string (3) (unix)["have"] == 1["have"] == "have"[1] == 'a' Version of April 28, 2002 10:15 pm Page 4 of 6
Extra Credit (4) 'a' + "fun" - 0x60 == 0x61 + "fun" - 0x60 == "fun" + 1 == "un" So, the program is a messy way of saying: printf("%six\n", "un"); and just prints "unix" on a line. main() printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60); 6. (10 points) If you wrote the Fibonnaci program in problem 4 using recursion, write a second version using a loop (and not using recursion). Conversely, if you wrote the Fibonnaci program using loops and not recursion, write a second version using recursion. fib.c Matt Bishop This program prints out the first n Fibonacci numbers. If n is too large, you get overflow; but that's not my problem (buy a bigger machine)! Modification history: 1.0 Matt Bishop original #include <stdio.h> This is the routine to print the Fibonacci numbers The numbers are defined as f[i+2] = f[i+1] + f[i] for all i. We use two counters, a and b. Now, note that f[i+1] + f[i] == f[i] + f[i+1], so let a correspond to f[i+2] for i even, and b to f[i+2] for i odd. Then we have: a f[i+2] = f[i+1] (b) + f[i] (a) for i even and b f[i+2] = f[i+1] (a) + f[i] (b) where (a) and (b) are the current values of a and b, and a and and b are the newly-assigned values of a and b. So, we don't need an array. void main(int argc, char argv) int n; how many Fibonacci numbers register int i; counter in a for loop register int a, b; the Fibonacci number counters check the invocation if (argc!= 2) fprintf(stderr, "Usage: %s <integer>\n", argv[0]); Version of April 28, 2002 10:15 pm Page 5 of 6
be sure the single argument is a non-negative integer if (sscanf(argv[1], "%d", &n)!= 1 n < 0) fprintf(stderr, "%s: argument must be a nonnegative integer\n", argv[0]); we do the initial conditions separately, since they cannot be computed if (n > 0) first number is 0 a = 0; printf("%10d\n", a); if (n > 1) second number is 1 b = 1; printf("%10d\n", b); now do the Fibonacci series. Note it's easier to do two at a time, as described in the header comment for(i = 2; i < n; i++) do number i a += b; printf("%10d\n", a); check that we also want number i + 1 if (++i < n) we do -- do it b += a; printf("%10d\n", b); exit nicely exit(0); Version of April 28, 2002 10:15 pm Page 6 of 6