Reference no: EM133665725
Computer Systems Principles and Programming
Introduction
The goal of this assignment is to give you practice at C programming. You will be building on this ability in the remainder of the course (and subsequent programming assignments will be more difficult than this one). You are to create a program (called ucpuiscramble) which allows users to play a word game where they try to guess as many words as possible that. can be made from a given set of letters. For example, the set of letters ACLLLOY can be used to form the words COY, CALL, LOYAL, LOLLY and LOCALLY among others. The assignment will also test your ability to code to a particular programming style guide, and to use a revision control system appropriately.
Specification
The uqunscramble game will print out a set of letters and ask the user to enter words that can be made from that set of letters and that have a certain minimum length. (The maximum length will be the number of letters in the given set of letters - each letter in the set can be used at most once.)
The program will check that the entered word can be formed from the given set of letters and that the word can be found in a specified dictionary file. If so, the program will accept the word and increase the user's score by the length of the word. If a valid word is entered that uses all of the letters then an additional 10 points is added to the user's score. The program prints the user's score and continues to read words from standard input (stdin) until it reaches end-of-file (EOF).
You can choose to play the game with a particular set of letters or the game will choose a set of letters for you. An example game play session is shown below. Lines typed by the user (i.e. the command and words entered on standard input) are shown in bold green for clarity. Other lines are output from the program to standard output. Note that the $ character is the shell prompt - tt is not entered by the user nor output by ugunscramble. Note that words entered by the user are case insensitive - they can be upper case, lower case OT a mixture of the two.
Command Line Arguments
Your program (uqunscramble) is to accept command line arguments as follows: .7u_qunscramble [--fen-min en] [--dict filename] [--chars Letters]
The square brackets ([]) indicate optional arguments (or pairs of arguments in this case). The italics indicate placeholders for user-supplied arguments. Any or all of the options can be specified (at most once each). Options can be in any order.
Some examples of how the program might be run include the following duclunscramble
duqunscramble --chars CCeiKRT
duquuscramble --len-min S
dugunscramble --dict mywords --chars aeiilnr
The meaning of the arguments is as follows:
n --chars - if specified, this option argument is followed by the set of letters to be used to play the game, The set can be any combination of letters in any order and the letters can he uppercase, lowercase or a mixture of the two.
• --dict - if specified, this option argument is followed by the name of a file that is to be used as the dictionary of valid words.
• --len-min - if specified, this option argument is followed by an integer that, specifies the minimum length of words that will be accepted as valid guesses
If the --chars option argument (and associated value argument.) is not supplied, then the program must fhoose a. random set of letters using the supplied get_random_letters 0 function - see the [provided Lihrar [section on page
If the --len-rnin option argument (and associated value argument) is not supplied, then the program must use the default value of 3.
If a dictionary filename is not specified, the default should be used (/1.0calieoursea/esse2310/etc/words). Prior to doing anything else, your program must check the command line arguments for validity. If the program receives an invalid command line then it must print the (single line) message:
Usage : uqunscramble [--len-min lea] [--dict filename] [--chars letters]
to standard error (with a following newline), and exit with an exit status of 8. Invalid command lines include (but may not be limited to) any of the following:
n A valid option argument is given (Le. --chars, --1en-min or --dict) but. it is riot followed by an associated value argument or the value argument is empty.
The --len-min argument is given but the associated -value is not a single digit.
• Any of the option arguments is listed more than once (with an associated value).
• An unexpected argument is present.
Checking whether the Letters, Zeta and/or filename arguments (if present) are themselves valid is not part of the usage checking (other than checking that the Zen value is a single digit). The validity of values is checked after command line validity as described in the sections below - and in the same order as these sections are listed, i,e. length validity is checked before letter set validity, which is checked before dictionary filename validity. This means that command line arguments like --chars --len-min would not be an invalid command line - this would be an invalid letters error - see below. (The argument --len-min is accepted as the value argument associated with --chars so is not a usage error.)
Length Validity Checking
If a minimum length is specified on the command line then your program must check that the value is between 3 and 5 inclusive. If it is not, then your program must print the message:
uqunscramble: minimum length must be between 3 and 5
to standard error (with a following newline), and exit with an exit status of 5.
Letter Set Checking
If the --chars option argument is specified with an associated value argument ( letters) then the given set of letters must be checked for validity. Valid sets of letters contain only letters (lowercase and/or uppercase)
If the letters value argument contains characters other than letters, then your program must print the message:
uquascramble: invalid letter set
to standard error (with a following newline), and exit with an exit status of 20.
If the set of letters is longer than 11 characters, then your program must print the message:
ugunscramble: too many letters - the limit is 11
to standard error (with a following newline), and exit with an exit status of 10.
If the set of letters is shorter than the specified minimum word length (the value given on the command line, or the default value (3) if no value is given on the command line), then your program must print the message:
ugunscramble: too few letters for the given minimum length (n)
to standard error (with a following newline) where n is replaced by the specified/default minimum word length. The program must then exit with an exit Status of 19. Note that the parentheses must be present in this message.
Dictionary File Name Checking
By default, your program is to use the dictionary file /localicourses/csse231Cietc/words. If the --diet argument is supplied, then your program must instead use the dictionary whose filename is given as the value associated with that option argument. If the given dictionary filename does not exist or can not be opened for reading, your program must. print the message:
uqunscramble : dictionary with name "filename" cannot be opened
to standard error (with a following newline), and exit with an exit status of 9. (The italicised filename is replaced by the actual filename, i.e. the value from the command line. The double quotes must. be present.) This check happens after all of the checks above.
The dictionary file is a text file where each line contains a "word". (Lines are terminated by a single newline character. The last line in the file may or may not have a terminating newline,) You may assume there are no blank lines and that no lines in the dictionary file are longer than 50 characters (excluding any newli-nefl although there may be entries that contain characters other than letters, e.g. "1st" or "don't". (These will never be valid words in the game.) The dictionary may contain duplicate words and may be sorted in any order. The dictionary may contain any number of words (including zero). There is no guarantee that the dictionary contains any words that can be made from the given set of letters.
Program Operation
If the checks above are successful, then your program must determine the set of letters (if this is not given on the command line). It does this by calling get_random_letters () - see details of this provided library function on page j The default number of letters to be obtained is 9. Your program must then print the following to standard output (with a newline at the end of each line):
Welcome to L.Nunscrambie!
Enter words of length minlen to mazzen made from the letters " letter-set "" where
• minien is replaced by the minimum length value from the command line (or the default value of 3 if no mininnim length is specified on the command line),
n maxlen is replaced by the number of letters in the set of letters, and •
fetter-set is replaced by the set of letters specified on the command line, or, if none was specified, then the set returned by get_random_letters(). The double quotes around this set of letters must be present. Note that. no change is made to the set of letters before printing them here - it must be exactly as specified on the command line or as returned by get_random_letters . Do not change the case of any letters.
Your program must repeatedly read lines from stdin (each terminated by a newline character or pending EOF) and check if the string entered (excluding any terminating newline) is a valid word of the right length that can be formed from the set of letters.
Your program must undertake the following checks, in the order given here. Messages printed to stdout must be terminated by a single newline. If a check fails then your program will attempt to read another line from stdin (i.e no further checks are done on an entered line once one issue is found and reported).
if the string entered contains characters other than letters (uppercase or lowercase or a mixture of both) then your program must print the following message to stdout:
Your word must contain only letters
If the string entered is shorter than the expected minimum length then your program must print the following message to stdout:
Too short! At least n characters are expected
where a is replaced by the minimum word length.
If the string entered is longer than the maximum length (the number of letters in the set of letters) then your program must print the following message to stdout:
Word must have a length of no more than n characters
where n is replaced by the maximum word length.
If the string entered is not able to be formed from letters in the set. of letters then your program must print the following message to stdout:
Word cannot be made with available letters
Note that. the case of letters is ignored when doing this check.
If the string entered is a previous valid guess then your program must print the following message to stdout: Word has already been guessed
This means your program will need to remember guesses that have been entered previously. Note that this matching must be case-insensitive - e.g., if able is a valid guess then entering aBLe will result in this message being printed.
If the string entered is not. a word found in the dictionary then your program must print the following message to stdout:
Word can't be found in dictionary
This check is case independent, e.g., if code is in the dictionary then Cade is valid.
If the checks above are passed then a valid guess has been made. Your program should increment the player's score by the length of the guessed word, and add an additional 10 points if the word is of the maximum length. Your program. must then print the following message to stdout:
OK! Your current score is n
where a is replaced by the current total score_
Exiting the Game
If end-of-file (EOF is detected on stdin when your program goes to read a line then the game is over.
If the player's score is greater than zero, then your program must print the following message to stdout (terminated by a newline);
Final score is n
where TZ is replaced by the final score. Your program must. then exit with status 0.
If the player's score is zero (i.e. no valid words have been guessed) then your program must print the following message to stdout (terminated by a newline):
No valid guesses
and then exit with status 7.
Advanced Functionality
This section describes more advanced functionality. It is recommended that you not implement this until other functionality is working.
If the player enters the string "q" on a line by itself (without the quotes) then your program will quit, but first it must print. to stdout all the valid words in the dictionary that can be formed from the set of letters. These words must be printed in uppercase, one per line. (Each line is terminated by a newline.) The words must be sorted (a) from shortest. to longest., and (b) for words of the same length, alphabetically. There must be no duplicates in this list, even if there are duplicates (possibly with different cases) in the dictionary. For example, if the dictionary contains the words game, GAME, Game and game (repeated), and this is a valid word for the given set of letters, then the word GAME will be output once.
After the words are printed, then your program must print the following message to stdout (terminated by a newline):
The maximum possible score was n
where n is replaced by the maximum score the player could have scored if they had entered ALL the valid words in the dictionary that could be formed from the set of letters,
Your program must then exit as described in the "Exiting the Game" section above (including printing a message as described in that section).
Other Requirements
Your program must open and read the dictionary file only one erl and store its contents (or a subset of its contents as you determine appropriate) in dynamically allocated memory. Your program must free all allocated memory before exiting.
Provided Library: libesse2310a1
A library has been provided to you with the following function which your program must use (when no set of letters is provided on the command line);
const char* get_random_letters(unsigned int numLetters);
The function is described in the get_random_letters (3) Mali page on moss. (Run
man. get_random_letters.)
To use the library, you will need to add #include <csse2310a1.h> to your code and use the compiler flag
- Iilocal/coursesicsse2310/include when compiling your code so that the compiler can find the include file. You will also need to link with the library containing this function. To do this, use the compiler arguments
- Lilocal/coursesicsse2310/11b -lcsse2310a1.
Style
Your program must follow version 3 of the CSSE2310/CSSE7231 C programming style guide available on the course Blackboard site. Your submission must also comply with the Documentation required for the use of Al tools if applicable,
Hints
1. The string representation of a single digit positive integer has a string length of 1.
2. You may wish to consider the use of the standard library functions isalphae , isdigit , isiower 0 , isupper , toupperO and/or tolower . Note that these functions operate on individual characters, represented as integers (ASCII values).
3. Some other functions which may be useful include: stremp() strlen , strdup(), exit (), fopen() , fprintf 0, and fgets 0 . You should consult. the man pages for these functions.
4. Remember that you don't need to store all the words from the dictionary when you read it in. Consider only storing those words that can be made from the set of letters.
5. You can check whether a word can be formed from a given set of letters by counting the ni_unber of each letter in the word and comparing that with the number of each letter in the set of letters.
6. For the advanced functionality, you should use the qsort0 function. We are not expecting students to implement their own sorting algorithm. (If you write an inefficient algorithm then you may lose marks if the marking tests time out.)
7. You may wish to consider using a function from the getopt () family to parse command line arguments. This is not a requirement and if you do so your code is unlikely to be any simpler or shorter than if you don't use such a function. You may wish to consider it because it gives you an introduction to how programs can prone ss more complicated combinations of command line arguments. See the getopt (3) man page for details_ Note that short forms of arguments are not to be supported, e.g. the arguments "-d filename" (for specifying a dictionary filename) shouldresult in a usage error. To allow for the use of a getopt 0 family function, we will not test your program's behaviour with the argument "--" (which is interpreted by getopt 0 as a special argument that. indicates the end of option arguments). We also won't test abbreviated arguments, e.g. --di, --dic, etc.
Suggested Approach
It is suggested that you write your program using the following steps. Test your program at each stage and commit to your SVN repository frequently. Note that the specification text above is the definitive description of the expected program behaviour_ The list below does not cover all required functionality.
1. Write a program that checks the number of command line arguments is even (and less than or equal to six arguments following the program name). If not, then output. the usage error message and exit. with exit status 8.
2. Write code to iterate over the command line arguments in pairs and check that the first element in each pair is one of the permitted arguments (--chars, --diet or --2.en-min). If so save the value from the second element in the pair. (If not, we have a usage error.)
3. Check that the minimum length argument (if specified) is valid. Exit with an appropriate message/exit status if not.
4. Check that the set of letters argument if specified) is valid. Exit appropriately if not. Use the get_randorn_letters library function if the argument is not specified_
5. Check that the dictionary file can be opened. Exit appropriately if not.
6. Read each line from the dictionary file and save it to an array of strings. You'll need •.0 dynamically allocate memory for a string to hold each line and dynamically allocate memory for the array (which you can grow as needed with reanoc 0 .
• You can update this code later to only save those words that can be formed from the set of letters.
• You can convert words to upper case as you go to make comparison easier later.
7. Write code that prints the welcome message and repeatedly reads a line from stdin until EOF is received.
8. Add checks for the word that is read from stdin as described in the El Print appropriate messages on failure. Trograrn Operation' section on page
• See the hint above for how you can check whether a word can be formed from a set of letters.
• You'll need to keep track of each valid word that is entered to be able to work out whether it has been entered before - you should have already written code that keeps track of a set of words (a dictionary) - hopefully you can reuse that.
9. Add code that does the scoring and prints appropriate messages. 10, Implement remaining functionality as required . .
Forbidden Functions, Statements etc.
You must not use any of the following C statements/directivesjetc, If you do so, you will get zero (0) marks for the assignment.
6 goto
• #pr agma
• gcc attributes (other than the possible use of __attribute__( (unused)) as described in the style guide)
You must not use any of the following C functions. If you do so, you will get zero (0) marks for any test case that calls the function.
• longimp 0 and equivalent functions
• system()
• popen() 6 mkfifo() car mkf ifoat ()
• fork()
• pipe()
• rewind()
• fseek()
• execs 0, execvp() or any other members of the exec family of functions
6 Functions described in the man page as non standard, e.g. strcasestr 0 . Standard functions will conform to a POSIX standard - often listed in the "CONFORMING TO" section of a man page.
The use of comments to control the behaviour of clang-'format and/or clang-tidy (e.g., to disable style checking) will result in zero marks for automatically marked style.