Homework 3
Caution
  • You are expected to work individually.
  • Due: Friday, February 23th Monday 2/26 at 11pm EST (Baltimore time) is the HARD DEADLINE. No late days will be counted or can be used beyond this dealine.
  • This assignment is worth 60 points.

Learning Objectives

Objectives

To practice with:

  • arrays
  • strings
  • file I/O
  • command-line arguments
  • Makefiles
  • program organization
  • testing with assert
Individual Assignment
This is an individual assignment. This means you must NOT show your working code to another student, and should discuss with each other only the assignment requirements and expectations. See course staff for coding help.

Project Scaffolding (“Starter Code”)

In the class public git repository, the folder cs220-sp24-public/homework/hw3/ contains several files you should use as a starting point for this assignment. From within the public repo, type git status to confirm your local copy is in good shape, then type git pull to copy this folder. Then copy these files to your personal cs220 repository to begin your work. If you compile the files as posted, you’ll see a number of unused parameter errors reported, because the files contain incomplete function definitions. As you work on filling in the function definitions, you’ll eventually eliminate these warnings. By the time you submit your code for grading, none of these warnings (or any others) should be reported.

Write a program to solve a word search puzzle. Your program will accept a single command-line argument which is the name of a text file containing the word-grid. After reading the grid of letters from that file, you will read from stdin words for which to search. For each given word, you will print to stdout the location of all copies of that word in the grid.

Required Program Functionality

Unless otherwise noted, your program should exit with return value 0. The program expects a filename as a command-line argument. If none is supplied, the program should output “Please enter a command line argument.” and exit with return value 1. If a filename is supplied but cannot be opened successfully, output “Grid file failed to open.” and exit with return value -1. A proper grid file contains an N x N grid of characters where N is at most 10 and all characters in the grid are alphabet letters. That is, there should be N lines containing N letters (any mix of upper or lower case), followed by an empty line, with no spaces between the letters. Anything in the grid file after the empty line can be ignored. There are only 3 types of invalid grids that your program must detect and report. In any of the following cases, your program should output “Invalid grid.” and exit with return value -2:

Search words read from stdin are separated by whitespace (any amount). The program should continue processing search words until it reaches the end-of-input (ctrl-d if stdin is not redirected).

Words may appear in the grid forwards or backwards, horizontally or vertically, with the characters in order in adjacent cells. Different words might share characters. The program must search for each word in all 4 directions: right, left, down, up.

Note
The program should be case insensitive in its search.

For each appearance of a search word found in the grid, your program should output to stdout a line of text containing the matched word, the row number of the start of the word, the column number of the start of the word, and the direction of the match: R for right, L for left, D for down, U for up (as shown in the examples below). Rows and columns shown in the output are to be numbered starting with 0.

If multiple copies of a single search word are present in the grid, the program must locate and report each of them. The required order of the output lines for multiple appearances of a single search word w is as follows:

Multiple appearances within each directional category (R, L, D, U) should be reported in order of occurrence of the first letter in the search word, when the grid is read row-by-row from left to right, starting with row 0. For example, if word w appears in the grid directed leftwards starting at row 4, column 3 and again directed leftwards starting at row 1, column 6, then the appearance starting at row 1, column 6 should be listed before the other leftward appearance, and both leftward appearances should be after any rightward appearances are reported, but before any downward or upward directions are reported.

Further Assumptions
  • If no matches for a word are found, print the search word followed by " - Not Found" , as shown below.
  • You may assume the input word is never longer than MAX_SIZE characters.
  • You may assume there are no intervening whitespace among characters in grid.txt.
  • You may assume there are NO null terminators anywhere in grid.txt.

Sample Runs

grid.txt, example input file with empty line at the end

pitk
olpe
pkey
tope
  1. Sample run #1, interactive user input
./word_search grid.txt
tip pop key
tip 0 2 L
pop 0 0 D
pop 2 0 U
key 2 1 R
key 0 3 D
  1. Sample run #2, interactive user input shown interleaved with program output
./word_search grid.txt
tip
tip 0 2 L
pop key
pop 0 0 D
pop 2 0 U
key 2 1 R
key 0 3 D
  1. Sample run #3, redirected input using Unix echo and pipe
echo "tip pop key nope" | ./word_search grid.txt
tip 0 2 L
pop 0 0 D
pop 2 0 U
key 2 1 R
key 0 3 D
nope - Not Found

Implementation Requirements

/* Given a filename and a MAX_SIZExMAX_SIZE grid to fill, this function populates the grid and returns n, 
the actual grid dimension. If filename_to_read_from can't be opened, this function returns -1. If 
the file contains an invalid grid, this function returns -2.
*/
int populate_grid(char grid[][MAX_SIZE], char filename_to_read_from[]); 

/* Each of these 4 functions returns the number of times the given word string was found in the 
grid facing the direction indicated in the function name. Parameter n indicates the actual size 
of the grid. The function sends corresponding output to the specified file pointer, which 
already points to an open stream. Output lines must appear in order of the first character's 
appearance in a left-to-right scan of each row beginning with row 0.
*/
int find_right(char grid[][MAX_SIZE], int n, char word[], FILE *write_to); 
int find_left (char grid[][MAX_SIZE], int n, char word[], FILE *write_to); 
int find_down (char grid[][MAX_SIZE], int n, char word[], FILE *write_to); 
int find_up   (char grid[][MAX_SIZE], int n, char word[], FILE *write_to); 

/* This function is similar to the 4 functions above, but reports ALL appearances of the given 
word, in the required R,L,D,U order.
*/
int find_all  (char grid[][MAX_SIZE], int n, char word[], FILE *write_to); 

Testing

In addition to the source files listed above, you must write and submit a C file named test_search_functions.c that will contain a tester main function and #include search_functions.h. The file will also contain at least one helper test function per each of the functions declared in search_functions.h. For example, if the declaration for a function named fun1 appears in search_functions.h, then test_search_functions.c should include a corresponding function named test_fun1. The job of each of the helper functions in test_search_functions.c is to test, using assert statements, that the corresponding function declared in search_functions.h works properly. The main function in test_search_functions.c will call each helper function in turn, and, if all of the tests pass, should output All search_functions tests passed! to indicate success.

Makefile

You must submit a working Makefile with at least a word_search target that builds your program to create an executable named word_search and a test target that builds and runs your testing executable. To be considered fully functional, your Makefile should correctly build the executables with the appropriate flags when (and only when) one of the relevant source files has changed. The Makefile should be named Makefile (spelling and case are important).

Git Log

You are expected to use git to backup your progress on this project. Include in your submission a copy of the output of git log showing at least five commits to the repository of code from this assignment, with meaningful commit messages. (You should commit early and often, likely every time you have a version that compiles, so you should probably have many more than five of these). Just before submitting your work, save the output into a file called gitlog.txt by executing:

git log > gitlog.txt.

Submission Checklist

Your Gradescope submission should contain at least the following files:

* word_search.c
* search_functions.h
* search_functions.c
* test_search_functions.c
* test1.txt, test2.txt, and any additional data files created by you which your tester functions require
* Makefile
* gitlog.txt

Hints, Tips, and a Challenge

Here are some further hints and tips

Tips & Hints
  • To implement a case-insensitive search, consider converting to lowercase all characters read in as part of the grid or as search words.
  • Make the horizontal search as clean and efficient as possible before attempting to write searches in other directions.
  • Instead of writing a new search function to search in reverse for a word, reverse the word itself and apply your original searches (horizontal, vertical) to it.
  • Make use of gdb to help debug your program.
  • Write your function tester functions early, rather than waiting until the last minute. Their purpose is to help you catch bugs in the functions early on, so the bugs don't cause problems when used by main. Using this approach as intended will help you track down bugs more easily.
  • If in testing your program's output, you want to determine whether two files are identical (e.g. when one file contains your program's actual output and the other contains the expected output), the completed function named file_eq provided for you in the test_search_functions.c file will be useful!
  • In addition to writing tests for individual helper functions that are included in your submission, you'll need to create and utilize "end-to-end" tests for your complete word search as well. By "end-to-end" testing, we simply mean running the entire program and checking if it behaves as desired on a number of different inputs. Your end-to-end tests do not need to be handed in.

Extra Challenge (not for credit)

Find words directed diagonally as well, by searching in 8 directions, rather than 4. This is a good way to improve your grasp of the language and concepts.

Submission

Create a .zip file named hw3.zip which contains all the requested files mentioned above. (Do not zip your entire hw3 folder - only the files.) Copy the hw3.zip file to your local machine and submit it as Homework 3 on Gradescope.

Multiple Submissions
You may re-submit any number of times prior to the deadline; only your latest submission will be graded.
Late Submissions
Review the course syllabus for late submission policies (grace period and late days). You will want to save your late days for the future assignments as they will be more involved.
Style Matters!
You should also make sure that your code has good style. You can look at the [coding style guidelines here](https://jhucsf.github.io/spring2021/assign/style.html) from a course you will take later that also applies to this course. In brief, you should make sure that your submission is well formed: - it is not overcommented or undercommented - there are no ambiguous variable names - proper/consistent bracket placements and indentation - no global variables

Two notes regarding automatic checks for programming assignments:

Danger

Remember that if your final submitted code does not compile, you will earn a zero score for the assignment.

Info

Two notes regarding automatic checks for programming assignments:

  • Passing an automatic check is not itself worth points. (There might be a nominal, low point value like 0.01 associated with a check, but that won’t count in the end.) The checks exist to help you and the graders find obvious errors.
  • The automatic checks cover some of the requirements set out in the assignment, but not all. It is up to you to test your own work and ensure your programs satisfy all stated requirements. Passing all the automatic checks does not mean you have earned all the points.