# Recursion and More! --- CS 130 // 2021-09-20 ## Administrivia - No Quiz 2 today - Quiz 1 is graded but I won't be able to return it until later tonight - Extending deadline for Assignment 2 to be 11:59 PM Thursday night - Review for exam on Wednesday (Exam on Monday) # Questions ## ...about anything? # Files ## Opening a File - To open a file in C, you use the `fopen` function: ```c FILE *fp = fopen("input.txt", "r"); ``` + The `"r"` opens the file for **reading** + Can use `"w"` for **writing** ## Reading from a File - Once a file is open, you can **read** text from it using: ```c FILE *fp = fopen("input.txt", "r"); char buffer[80]; // Reads until a newline character is found. Similar to // the readline() method in Python. // Stops after 79 characters to not overfill the buffer fgets(buffer, 80, fp); ``` - `fgets` returns `NULL` if it fails to read any characters - It **includes** the newline characters ## Looping Over a File - One common pattern is looping over a file: ```c FILE *fp = fopen("my_file.txt", "r"); char buffer[80]; while (fgets(buffer, 80, fp) != NULL) { // buffer contains the current line here } fclose(fp); ``` ## Writing to a File - To open a file for writing you use: ```c FILE *fp = fopen("input.txt", "w"); ``` + If `input.txt` already exists, it is deleted + If it doesn't exit, it is created - We use `fprintf` to print to a file: ```c fprintf(fp, "%d %d %d\n", 100, 200, 300); ``` ## Closing Files - It is important to **close** your files to inform your OS that you're done with the file - You can do this with: ```c fclose(fp); ``` ## Parsing Structured Data - When reading a file, it is common to: 1. Use `fgets` to get one line at a time 2. Then use `sscanf` to parse the line into something useful - `sscanf` is identical to `scanf` except it reads from a string buffer instead of standard input ## Exercise - Suppose we'd like to parse a table of integers into a 2D array in C - Let's assume the file format is as follows: ```text 4/4 0,1,2,3 4,5,6,7 8,9,10,11 12,13,14,15 ``` - First two numbers are the width/height of the table - How would you go about this? ## Exercise - **Discuss with those around you:** + How would you break this program down into helper functions? + Are there any functions in `string.h` and/or `stdlib.h` that might make this easier? Look up the documentation! + Consider looking through `ctype.h`, too! # Recursion ## Recursion - A **recursive** function is one that "refers to itself" - You might recall the **factorial** function can be defined recursively: $$ n! = \begin{cases} 1, &\text{ if }n=0\\\\ n\times (n-1)!, &\text{ if }n>0 \end{cases} $$ ## Recursion: Two Basic Parts - **Base Case**: + The "when to stop" case of recursion - **Recursive Case**: + Break the problem into smaller parts + Solve the parts by making recursive calls + Combine results into the answer ## Recursion in C - We can implement factorial in C as follows: ```c int factorial(int n) { if (n == 0) { return 1; } else { return n * factorial(n-1); } } ``` - [C Tutor Visualization](https://pythontutor.com/c.html#code=%23include%20%3Cstdio.h%3E%0A%0Aint%20factorial%28n%29%0A%7B%0A%20%20%20%20if%20%28n%20%3D%3D%200%29%20%7B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20n%20*%20factorial%28n-1%29%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aint%20main%28%29%0A%7B%0A%20%20%20%20int%20fact%20%3D%20factorial%285%29%3B%0A%20%20%20%20printf%28%22Factorial%20of%205%20is%3A%20%25d%22,%20fact%29%3B%0A%20%20%20%20return%200%3B%0A%7D&curInstr=0&mode=display&origin=opt-frontend.js&py=c_gcc9.3.0&rawInputLstJSON=%5B%5D) ## Alternative Factorial - Consider the following alternative implementation with a helper function: ```c int factorial(int n) { return helper(n, 1); } int helper(int n, int acc) { if (n == 0) { return acc; } else { return helper(n-1, n*acc); } } ``` # Tail Recursion ## Tail Calls - A **tail call** is when a function immediately returns the result of another function ```c int foo(int x) { int y = x + x; return bar(y); // tail call } int bar(int x) { return x + x; } ``` - A tail call can be optimized to avoid creating a new stack frame ## Tail Recursion - If a function makes tail calls to itself, it is called **tail recursive** - Was our original implementation of `factorial` tail recursive? ```c int factorial(int n) { if (n == 0) { return 1; } else { return n * factorial(n-1); } } ``` - No! It multiplies `n` before returning ## Tail Recursion - Our alternative approach **is** tail recursive! ```c int factorial(int n) { return helper(n, 1); } int helper(int n, int acc) { if (n == 0) { return acc; } else { return helper(n-1, n*acc); // tail call } } ``` ## Exercise 1. Write a **recursive** function that computes the sum of an array of integers 2. Modify it so that it is **tail recursive** --- - What would the prototype of the function be? ```c int sum(int *arr, int n) ``` - Remember to think about the **base case** and **recursive case** # Pointer Arithmetic ## Pointer Arithmetic - You can do arithmetic on pointers! ```c int arr[5] = {100, 200, 300, 400, 500}; int *p1 = arr; int *p2 = &arr[2]; int *p3 = p2 + 1; p2--; printf("%d %d %d\n", *p1, *p2, *p3); ``` - What do you guess the output will be? # Bit Masking