Today in class I showed a nice way to do a bottlecap code generator/evaluator using the object oriented methodology.
First, in bcap.h, we have the specification for a BottleCap class:
#include <iostream> #include <vector> using namespace std; class BottleCap { public: BottleCap(int codelength, int nchars, vector <int> rewards); int Evaluate(string code); string Generate(int value); private: int EvalFxn(string code); int length; int numchars; vector <int> rewards; }; |
Note, there are three public methods -- the constructor, Evaluate() and Generate(). The constructor takes three arguments:
The Evaluate() method takes a string as its argument. This is the code. If the code is illegal (wrong number of characters or wrong characters), Evaluate() returns -1. Otherwise, it returns rewards[c], where c is the value of the function applied to the code.
The Generate() method returns a random code whose function is equal to the value argument.
The BottleCap class has three private variables, which are copied from the constructor arguments when the constructor is called. It also has a private method called EvalFxn(). This takes a code as its argument and returns the value of the function applied to the code. This method is private because it is used in the implementations of Evaluate() and Generate(), but we do not wish to allow users of the BottleCap class to use it.
The only subtle code is in Generate() -- note that I use new to create a C-style string of the correct size. When I return, I create a C++ string from the C string and call delete to deallocate the memory that I created with the new call. This is because otherwise, that memory will become "dead" -- no one will ever use it. So as not to waste memory, I call delete.
#include <iostream> #include <vector> #include "bcap.h" using namespace std; #define L 15 #define M 17 int main(int argc, char *argv[]) { BottleCap *bc; vector <int> rewards(M); int i, val, ncodes; string code; if (argc != 3) { cout << "usage: bcap-gen number-of-codes value\n"; exit(1); } ncodes = atoi(argv[1]); val = atoi(argv[2]); for (i = 0; i < M; i++) rewards[i] = 0; rewards[3] = 3; rewards[10] = 10; bc = new BottleCap(L, M, rewards); srand(time(0)); for (i = 0; i < ncodes; i++) { cout << bc->Generate(val) << endl; } } |
It first checks argc to make sure that it has been called with the correct number of arguments. Then it initializes the integers ncodes and val from the command-line arguments. It does this with atoi(), which converts a C-style string to an integer.
Next, it creates an instance of the bottlecap class using new and the constructor. Before doing that, it creates its rewards vector, which is all zeros, except for a 3 in index 3 and a 10 in index 10. Finally, it generates ncodes codes whose values are equal to val.
Let's see it compiling and running:
UNIX> g++ -o bcap-gen bcap-gen.cpp bcap.cpp UNIX> bcap-gen usage: bcap-gen number-of-codes value UNIX> bcap-gen 5 10 ICNHAAFDPGQEKKJ INCNJQHEAGLNLCP MBEFPFLJDONLJQB IPINMGBQKKJKMLA KLCLEJHHCLBEPBJ UNIX> bcap-gen 5 3 QMFQFCBJHDGCKBQ GCPMEJEBKPAAFDP QAGCMFDCCGMNPDC HFMFNLKPMHBABCN HMBNAIIHEGIJFKN UNIX>
#include <iostream> #include <vector> #include "bcap.h" using namespace std; #define L 15 #define M 17 int main(int argc, char *argv[]) { BottleCap *bc; vector <int> rewards(M); int i; string code; int val; for (i = 0; i < M; i++) rewards[i] = 0; rewards[3] = 3; rewards[10] = 10; bc = new BottleCap(L, M, rewards); if (argc == 1) { while (!cin.fail()) { cin >> code; if (!cin.fail()) { val = bc->Evaluate(code); cout << "Code " << code << " is worth " << val << " points.\n"; } } } else { for (i = 1; i < argc; i++) { code = argv[i]; val = bc->Evaluate(code); cout << "Code " << code << " is worth " << val << " points.\n"; } } } |
Note first how it creates the same instance of the BottleCap class as bcap-gen.cpp. Then it evaluates input dependingo on its command line arguments. If there are none, then it reads from standard input using cin. If however there are command line arguments, then it assumes that they are codes and evaluates them. Note how this is neat because you can test it by piping the output of bcap-gen into it to test:
UNIX> g++ -o bcap-eval bcap-eval.cpp bcap.cpp UNIX> bcap-eval QMFQFCBJHDGCKBQ MIPBCOAHGHGACLN AAAAAAAAAAAAAAA Thor Code QMFQFCBJHDGCKBQ is worth 3 points. Code MIPBCOAHGHGACLN is worth 10 points. Code AAAAAAAAAAAAAAA is worth 0 points. Code Thor is worth -1 points. UNIX> bcap-gen 5 10 | bcap-eval Code JMIKQGOADOCQIPF is worth 10 points. Code LNNFKDPANGJCLOH is worth 10 points. Code GQIMJFQJGNENGCI is worth 10 points. Code FEDNHBPCQDPNJPO is worth 10 points. Code GBGADEQBLOBHIED is worth 10 points. UNIX> bcap-gen 5 3 | bcap-eval Code BJEEBDNQPQHQFDL is worth 3 points. Code CBJIPAJLCBPDLJB is worth 3 points. Code PCCHQGOKHQHFLBO is worth 3 points. Code KQPQOBOAPCDOLNA is worth 3 points. Code FIBCHFAHCBJLBIM is worth 3 points. UNIX> bcap-gen 5 12 | bcap-eval Code NKADIFJHDIONPFK is worth 0 points. Code IOOGBMOBBOQDJOG is worth 0 points. Code AFOPAMLQCKKAOQE is worth 0 points. Code ACOHFBBGIEHDKQP is worth 0 points. Code LGENNCEKNIBNQBP is worth 0 points. UNIX>