210 likes | 322 Views
CIS 112 Data Structures and Algorithms. URL encoding Revisited. Observations. Many of the solutions had a single main function that solved the entire problem. Better solutions practiced modular design with one or more functions.
E N D
CIS 112 Data Structures and Algorithms URL encoding Revisited
Observations • Many of the solutions had a single main function that solved the entire problem. • Better solutions practiced modular design with one or more functions. • The best solutions, take advantage of existing objects to free the programmer from the low level tasks.
Objects • If you can use an already existing object, by all means, use it. • If you can’t find an existing object, build the object. Then, at least, the next time you need it, it already exists. • A useful object for the URL problem might be to a numeric type “HEXNUMBER”. • An even more useful object might be a special string type “URLCodedString” .
HEXNUMBER (Simplified) • Read two characters from the input stream and stored them as an integer. • Provide member functions to return the integer equivalent of the hexadecimal number. • Return the character associated with the hexadecimal number.
hexNumber.h (version 1) class hexNumber { public: // constructor hexNumber(); // Return integer value Decimal(); // Return character value Character(); // Load data loadNumber(ch1, ch2); private: int iNum; };
hexNumber used in client code #include “hexNumber.h” int main() { hexNumber hNum; ------------------------------------------------ if (ch == ‘%’) { cin >> ch1 >> ch2; hNum.loadNumber(ch1,ch2); ch = hNum.Character(); } ------------------------------------------------ return 0; }; Create an instance of a hex number Code segment for fetching hex encoded value from input.
hexNumber.h (version 2) class hexNumber { // Same as before }; // overload the stream extract operator istream& operator(istream& in, hexNumber hNum) { cin >> ch1 >> ch2; hNum.loadNumber(ch1,ch2); } Get input directly from input stream using access function.
hexNumber.h (version 3) class hexNumber { public: // same as before friend istream& operator(istream& in, hexNumber hNum); private: int iNum; }; In this case the loadData member function is redundant and might be eliminated Create a “friend” function to access private data.
hexNumber.cpp (version 3) // original implementation code here istream& operator(istream& in, hexNumber hNum) { cin >> ch1 >> ch2; hNum.iNum = hexToint(ch1, ch2); return in; } int hexToint(char ch1, char ch2) { // any implementation that solves this problem } Access the private data member directly
hexNumber (versions 2 and 3) used in client code #include “hexNumber.h” int main() { hexNumber hNum; ------------------------------------------------ if (ch == ‘%’) cin >> hNum; ------------------------------------------------ return 0; }; Create an instance of a hex number Code segment for fetching hex encoded value directly from input.
An even more useful object might be a URL encoded • string object with the following properties. • Number of key-value pairs • Get a key name • Get a value’s content • Get a value associated with a key • Ability to load an URL encoded string directly • from a file into the object URLEncodedString class
class URLCodedString { public: // default constructor URLCodedString(); // pre - Cstring exists void LoadString(CString&); // post - number of pairs found int NumberOfKeyValuePairs() const; // post - return the ith key CString getKey(int) const; // return the ith Value CString getValue(int) const; // return the value associated the the key CString getValue(CString&) const; private: int NumberOfPairs; CString key[100]; CString value[100]; void splitString(CString&); }; URLEncodedString class specification
#include <afx.h> // for MFC CString #include <fstream.h> // for ifstream class #ifndef _URLCodedString_ #define _URLCodedString_ class URLCodedString { public: URLCodedString(); void LoadString(CString&); int NumberOfKeyValuePairs() const; CString getKey(int) const; CString getValue(int) const; CString getValue(CString&) const; private: int NumberOfPairs; CString key[100]; CString value[100]; void splitString(CString&); }; #endif URLEncodedString.h (class spec.) Macro guard
Overload file stream extraction operator using access function approach. URLEncodedString.h (cont) Return reference type inline ifstream& operator >> (ifstream & in, URLCodedString & s) { char buffer[1024]; in >> buffer; s.LoadString((CString)buffer); return in; } Type cast Implement “inline” so it can appear in the header file
#include <iostream.h> #include <fstream.h> #include "URLCodedString.h" int main() { ifstream inF; inF.open("a:/testdata.txt",ios::nocreate); URLCodedString URLcs; inF >> URLcs; for (int i=0; i<URLcs.NumberOfKeyValuePairs(); i++) { cout << "Key Value: " << URLcs.getKey(i) << endl; cout << "Value Content: " << URLcs.getValue(i) << endl; } return 0; } Using the URLEncodedString class
#include "URLCodedString.h” // Helper function char convertHextoChar(char c1, char c2) { char hexTable[22] = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','a','b','c','d','e','f'}; for (int i=0; i<22; i++) if (c1 == hexTable[i]) break; for (int j=0; j<22; j++) if (c2 == hexTable[j]) break; return (i>15?i-6:i) * 16 + (j>15?j-6:j); } URLCodedString::URLCodedString() { NumberOfPairs = 0; } URLEncodedString class
void URLCodedString::LoadString(CString& inStr) { urlstr = inStr; CString tempStr; for (int i=0; i<urlstr.GetLength();i++) if (urlstr[i] == '%') { tempStr = tempStr + convertHextoChar(urlstr[i+1],urlstr[i+2]); i++; i++; } else if (urlstr[i] == '&') { splitString(tempStr); tempStr.Empty(); } else tempStr = tempStr + (urlstr[i]=='+'?' ':urlstr[i]); splitString(tempStr); } URLEncodedString class (cont)
URLEncodedString class (cont) void URLCodedString::splitString(CString& KeyValuePair) { CString tempStr; for (int i=0; i<KeyValuePair.GetLength();i++) if (KeyValuePair[i] == '=') { key[NumberOfPairs] = tempStr; tempStr.Empty(); } else tempStr = tempStr + KeyValuePair[i]; value[NumberOfPairs] = tempStr; NumberOfPairs++; }
int URLCodedString::NumberOfKeyValuePairs() const { return NumberOfPairs; } CString URLCodedString::getKey(int index) const { return key[index]; } CString URLCodedString::getValue(int index) const { return value[index]; } URLEncodedString class (cont)
URLEncodedString class (cont) CString URLCodedString::getValue(CString& keyStr) const { bool found = false; for (int i=0; i<NumberOfPairs; i++) if (key[i] == keyStr) { found = true; break; } if (found) return value[i]; else return "No Key-Value Pair with that key found"; }
Summary • The best solutions, take advantage of existing objects to free the programmer from the low level tasks. • As we create useful objects (using the C++ class) we start to build a library of solutions which we can apply to other problems, focusing our efforts on those problems. • We are reaping some of the benefits of code reuse, a topic we will study in even more detail later in the course.