Topic objectives: Pointers and dynamic memory space allocation
Strings and string functions
Arrays of pointers
More control structures
Functions, parameter passing, side effects
Well, now our novice cooks have found the spice rack program that checks blends to be useful but now they want more flexibility. They want to be able to enter their own spice names, to sort the spices in certain ways and to make shopping lists for the seasoning blends. So we will be modifying and expanding the first program to accommodate these functions. We will also be making some changes to take advantage of different language elements available to us as software designers. We would like to use any parts of the first program that are still useful in the second program but things can be totally rewritten if needed.
The first major change will be to allow the user to enter the names of spices and to record these names as strings using an array of pointers and dynamic allocation to create the strings. This will change the beginning of the program from having the novice cook pick from a list of spices to having the novice cook enter a set of spices by name. The cook should be allowed to type in between ten and twenty spices. The program should declare arrays of size twenty (20) for the pointers and the costs. The program should ask how many spices there will be in the cook’s spice rack and then read in that number of strings, one spice per line. The program should read the user’s string into a buffer and then copy the string in a dynamically allocated space whose address (pointer) is stored in the array of pointers.
After the spices are read in, then the program will ask the use for quantities and costs just as in the previous program. The quantities and costs will be stored differently in this program in a two-dimensional array instead of in separate one-dimensional arrays. The index value in the list of pointers should correspond to the index value in the array of amounts and costs. Ex: If the user entered “garlic” for the fourth spice name (spice_name) then the values in the quantity and cost array elements with index 3 will correspond to garlic – spice_valuemight be quantity in units of garlic and spice_valuemight be cost of one unit of garlic. You can declare preprocessor constants to use for the quantity and cost index if you want, i.e. #define COST 1 would allow you to write spice_value[COST] to reference the cost. If you want to record and store the total cost (and/or other numeric data e.g. amount needed or cost for a particular amount of a spice) for a spice you may include total cost (and/or the other data) as additional elements of your two dimensional array.
After the user has entered their data, the program should print a list of the spices in the spice rack by name, the quantity (in appropriate units), the cost per one unit of spice and the total cost for the available amount for each of the spices in the ‘rack’.
Once the cook’s data is all recorded, the program should ask the cook if they would like to sort the spices. The program should allow the cook to sort the spices by name, by amount, or by unit cost. The name sort will use string comparisons and selection sort while the amount and cost sorts will use numeric comparisons and bubble sort. You should be able to use the same swapping function for all sorts. Remember that you must sort the array of pointers AND each associated element of the array of numeric values when you are swapping the data around regardless of whether you are sorting by name, amount or cost. (This means that if you are swapping “garlic“ and “basil“ - spice_name and spice_name for example - that you must also swap the costs of garlic and basil – e.g. spice_value[COST] and spice_value[COST] -, the quantities of both and any other info you have stored about them.) Print all the contents of both arrays after you have sorted it. Allow the user to sort the arrays as many times in as many ways as they want and print the arrays after every sort. When the user has finished the sorts, let them continue on to check the blends.
At this point, the program will now offer the user to opportunity to determine what types of seasoning blends can be made, to make a shopping list of missing spices for a blend, or to sort the spices with their associated quantities and costs (and any other data).
The first task of determining if a blend can be made will simply be the same task from the first lab modified to work on the new data structures. You should use the three blends from the first program along with at least three more blends for a total of six blend choices. This task will differ in two ways: how the spice name info is compared and what happens if a blend cannot be made. If the first program, the novice cook was just informed that spices were missing and the blend could not be made. Now the novice cook will have the option of creating a shopping list of the missing spices and amounts in order to complete one mixture of the seasoning blend.
The process should be to display the seasoning blends to the novice cook and let the cook choose a blend. Your program must do the following steps for the chosen blend of seasoning:
a) Determine if the blend can be made from the available spices by the steps below:
i) (Modified from first program) Determine if all the required spices are in the spice ‘rack’. Since the spices are now strings, you will need to record the spices in the blends as strings and then use string comparison functions to check if a spice is available. If not go to step b2.
ii) If all spices are available determine if the required amount of each spice is available by:
1) Find the ingredient requiring the smallest number of units (ex: for Italian blend this is rosemary)
2) Determine if the amount available in the spice rack is sufficient for the blend. If not go to step b2.
3) Repeat steps 1 and 2 for each ingredient in the seasoning blend
4) If sufficient amounts of all spices are available to make the blend go to step b1.
b1) Since at least one mixture of the blend can be made your program should do two things. First, calculate the cost of one mixture of the seasoning blend and print this. Second, repeat the steps 1 -4 above for double the amount (two mixtures of the blend). If two can be made, check for triple the amount (three mixtures) and continue checking in this fashion. When your program finds an amount that is too large, stop checking and print a message indicating how many mixtures of the required blend can be made.
b2) (Modified from first program) If your program has reached this step, then either some required spices are missing for the blend or the required amounts are not available. At this point print a message indicating which spice was found first to be missing or insufficient for the blend and then give the user three options.
1) Create a shopping list of the missing spices and amounts so that one mixture of the seasoning blend could be created
2) Choose another blend to check and start over at step a) above or
3) End the program
If the user chooses b2 1), then perform the same checking that was being done for the seasoning blend but this time check everything in one mixture of the blend and record missing spices and amounts needed. You should use an array of string pointers with dynamically allocated space for the names of the spices and another array to hold the needed quantities. This shopping list should record only the amounts needed beyond what the spice rack already has. This means if the blend needs 5 units of basil and the spice rack has three units of basil then the shopping list should list TWO units of basil since that is all that is needed. Your array of pointers and your array of amounts should be large enough to hold the maximum number of ingredients for any blend (if the most complicated blend has 8 ingredients then your arrays must be able to hold up to 8 ingredients.)
If the user chooses b2 2), then just let the cook choose another blend and start over at step a) just as in the previous program.
If the user is finished and chooses b2 3), print a concluding message and then end the program.
The program should use the following data structures:
One-dimensional array of pointer to char (strings) for recording spice names typed in by the cook and dynamic space allocation to store each string
Multi-dimensional floating point array for recording corresponding amounts in units of spice and price of ONE unit of spice
One and multi dimensional character string and floating point arrays to hold data for each seasoning blend: spice names and amounts in units. You can also store cost if desired.
One and multi dimensional character string and floating point arrays to hold data for shopping list for one seasoning blend: spice names and amounts in units
The program should NOT use the following data structures:
The program should use the following control structures:
Function calls to perform tasks
A loop to perform testing for the spice blends
Selection statements as needed
Function calls to string library functions for comparing and copying strings
Function calls to malloc or calloc to allocate space for strings
Bubble sorting algorithm for numeric values
Selection sorting algorithm and string comparisons for string values
The program should NOT use the following control structures:
breaks outside of switch structures
any topic not covered in class before the lab DUE date unless approved by the instructor
The program should be implemented as a set of functions with at least one function for getting input from the user, one for the selection sort, one for the bubble sort, one for the swap function, one for printing the data, and one for checking blends. You may use more functions than this but you must use at least this many.
The program should perform the following actions in the given order:
Declare and initialize the variables
Print a welcome screen for the user that introduces the system
Get the needed input value from the keyboard
Perform appropriate calculations and print the appropriate outputs
Let the user enter additional values until the user indicates that they are finished.
The program should have a program header which gives, at least, your name, the number of the lab assignment, your class and section, the assignment date, the due date, and a description of the program. If multiple files are used, each file should contain a similar header.
Each programmer-defined function, i.e. each function you write, should have a function header similar to those used in the examples in the textbook. This header should include at least the function name, the purpose of the function, and its inputs and outputs.
This program must be run with three different sets of data for the spice rack contents. The first data set (dataset 1) should use the values given below. You must also create two additional data sets and run your program with them as well. You may run it three times within a single execution or you may execute the program three different times so that you have a total of three different data sets. The sample datasets that you create must meet the guidelines given in the problem definition.
The program output must be recorded in a script file from OMEGA using the gcc compiler. If you do not know how to create a script file, it is your responsibility to ask the TA or OIT how to use this function.
Sample input values for data set 1:
Spice Amount in units Total cost
Garlic 100 10.00
Oregano 25 1.25
Onion 40 2.15
Sweet paprika 5.5 5.50
Dry mustard seeds 10 0.10
Black pepper 108 2.16
Rosemary 10 2.40
Salt 200 1.00
Cayenne 50 0.55
Basil 22 3.30
Marjoram 10 4.00
Thyme 33.3 6.00
Fennel 5 5.55
Sage 1 3.85
Coriander 10 2.39