In response to the emergence of the novel coronavirus, grocery stores have become very creative in enabling their customers to acquire groceries in many different ways that reduce potential virus exposure. For example, the Ralphs where I shop supports the following ways to fulfill grocery store orders:
For this assignment, suppose that a sensor is recording grocery store order fulfillments at the sliding doors as they leave the store. For example,
1P1D
would indicate that a single pickup and a single delivery order had been fulfilled. From this information, note that the character P is being used to represent a pickup order, the character D is being used to represent a delivery order. Similarly, the character S and I would represent shipped order and in-store order. Additionally, lowercase letters p, d, s and i could also be used. For example,
5s10i
would indicate that five shipped orders and ten in-store orders had been fulfilled. Additionally, no more than 20 pickup orders, no more than 10 delivery orders and no more than 99 total orders can be processed in one grocery store string. For example,
20p10d99i
would not be valid because more than 99 total orders are represented in this one grocery store string.
Precisely, to be a valid grocery store order string,
digit(s) must be followed by an order type (p,d,s,i or P,D,S, I) leading extra zeros in the digit portion is not allowed only digit characters and the order type character are allowed. No spaces or any other characters allowed no more than 20 pickup type orders are allowed in a single grocery order string no more than 10 delivery type orders are allowed in a single grocery order string no more than 99 total orders are allowed in a single grocery order string
All of the following are examples of valid grocery store order strings:
- 1p1d1s1i (a single pickup, single delivery, single shipped and single in-store order)
- 5d5p (five delivery and five pickup orders)
- 1D1P4d4p (five delivery and five pickup orders)
All of the following are examples of invalid grocery order strings:
- happyDays10 (no characters allowed besides digits, p, P, d, D, s, S, i or I)
- 000001p (no leading zeros in the digit portion allowed)
- +1p (no + allowed)
- 1p1d XYZ (string must be fully consumed to be valid)
- 50i50i50s (no more than 99 orders total)
- 10p10p10p1d1s1i (no more than 20 pickup orders allowed)
- 5d5d5d1p1s1i (no more than 10 delivery orders allowed)
Your task
For this project, you will implement the following five functions, using the exact function names, parameter types, and return types shown in this specification. (The parameter names may be different if you wish).
bool isWellFormedGroceryOrderString(string grocerystring)
-
This function returns true if its parameter is a well-formed grocery order string as described above, or false otherwise.
-
int pickupCount(string grocerystring)
-
If the parameter is a well-formed grocery order string, this function should return the number of pickup type grocery orders after the string is fully processed. If the parameter is not a valid grocery order string, return -1.
-
int deliveryCount(string grocerystring)
-
If the parameter is a well-formed
animal parkgrocery order string, this function should return the number of delivery type grocery orders after the string is fully processed. If the parameter is not a valid grocery order string, return -1. -
int shipCount(string grocerystring)
-
If the parameter is a well-formed
animal parkgrocery order string, this function should return the number of shipped type grocery orders after the string is fully processed. If the parameter is not a valid grocery order string, return -1. -
int inpersonCount(string grocerystring)
-
If the parameter is a well-formed
animal parkgrocery order string, this function should return the number of in-person type grocery orders after the string is fully processed. If the parameter is not a valid grocery order string, return -1.
-
These are the only five functions you are required to write. Your solution may use functions in addition to these five if you wish. While we wont test those additional functions separately, using them may help you structure your program more readably. Of course, to test them, youll want to write a main routine that calls your functions. During the course of developing your solution, you might change that main routine many times. As long as your main routine compiles correctly when you turn in your solution, it doesnt matter what it does, since we will rename it to something harmless and never call it (because we will supply our own main routine to thoroughly test your functions).
-
-
Clearly, I am expecting the last four functions to invoke the first function as they complete their assigned task. This code reuse is one of the major benefits of having functions. So please do that.
-
-
Before you ask a question about this specification, see if it has already been addressed by the Project 3 FAQ. And read the FAQ before you turn in this project, to be sure you didnt misinterpret anything. Be sure you also do the warmup exercises accompanying this project.
-
-
Additionally, I have created a testing tool called CodeBoard to help you check your code. CodeBoard enables you to be sure you are naming things correctly by running a small number of tests against your code. Passing CodeBoard tests is not sufficient testing so please do additional testing yourself. To access CodeBoard for Project 3, please click the link you see in this week named CodeBoard for Project 3. Inside the file named user_functions.cpp, copy and paste your implementation of the assigned functions. CodeBoard uses its own main( ) to run tests against your code. Click Compile and Run. However please be aware that no editing changes can be saved inside CodeBoard. In this anonymous user configuration, CodeBoard is read-only and does not allow for saving changes.
Programming Guidelines
The functions you write must not use any global variables whose values may be changed during execution (so global constants are allowed).
When you turn in your solution, neither of the four five required functions, nor any functions they call, may read any input from cin
or write any output to cout
. (Of course, during development, you may have them write whatever you like to help you debug.) If you want to print things out for debugging purposes, write to cerr
instead of cout
. cerr
is the standard error destination; items written to it by default go to the screen. When we test your program, we will cause everything written to cerr
to be discarded instead we will never see that output, so you may leave those debugging output statements in your program if you wish.
The correctness of your program must not depend on undefined program behavior. For example, you can assume nothing about c
s value at the point indicated, nor even whether or not the program crashes:
int main() { string s = "Hello"; char c = s[5]; // c's value is undefined
Be sure that your program builds successfully, and try to ensure that your functions do something reasonable for at least a few test cases. That way, you can get some partial credit for a solution that does not meet the entire specification.
There are a number of ways you might write your main routine to test your functions. One way is to interactively accept test strings:
int main() { string s;
cout.setf( ios::boolalpha ); // prints bool values as "true" or "false"
for(;;) { cout << "Enter a possible grocery store string: "; getline(cin, s); if (s == "quit") break; cout << "isWellFormedGroceryOrderString returns "; cout << isWellFormedGroceryOrderString(s) << endl; cout << "pickupCount(s) returns "; cout << pickupCount(s) << endl; cout << "deliveryCount(s) returns "; cout << deliveryCount(s) << endl; cout << "shipCount(s) returns "; cout << shipCount(s) << endl; cout << "inpersonCount(s) returns "; cout << inpersonCount(s) << endl; }
return 0; }
While this is flexible, you run the risk of not being able to reproduce all your test cases if you make a change to your code and want to test that you didnt break anything that used to work.
Another way is to hard-code various tests and report which ones the program passes:
int main() { if (!isWellFormedGroceryOrderString("")) cout << "Passed test 1: !isValidGroceryOrderString("")" << endl; if (!isWellFormedGroceryOrderString(" ")) cout << "Passed test 2: !isWellFormedGroceryOrderString(" ")" << endl;
This can get rather tedious. Fortunately, the library has a facility to make this easier: assert
. If you #include the header <cassert>
, you can call assert
in the following manner:
assert(some boolean expression);
During execution, if the expression is true, nothing happens and execution continues normally; if it is false, a diagnostic message is written to cerr
telling you the text and location of the failed assertion, and the program is terminated. As an example, heres a very incomplete set of tests:
#include <cassert> #include <iostream> #include <string> using namespace std; int main() { assert( isWelLFormedGroceryOrderString("") == false ); assert( isWellFormedGroceryOrderString(" ") == false ); assert( shipCount( " " ) == -1 ); assert( deliveryCount( " " ) == -1 ); assert( inpersonCount( " " ) == -1 ); assert( pickupCount( " " ) == -1 );
assert( isWellFormedGroceryOrderString( "1s1d1i1p1S1D1I1P" ) == true ); assert( shipCount( "1s1d1i1p1S1D1I1P" ) == 2 ); assert( deliveryCount( "1s1d1i1p1S1D1I1P" ) == 2 ); assert( inpersonCount( "1s1d1i1p1S1D1I1P" ) == 2 ); assert( pickupCount( "1s1d1i1p1S1D1I1P" ) == 2 ); cerr << "All tests succeeded" << endl; return 0; }
The reason for writing one line of output at the end is to ensure that you can distinguish the situation of all tests succeeding from the case where one function youre testing silently crashes the program.
Reviews
There are no reviews yet.