Appendix 3: Utilities
Every C++ programmer has files of useful functions that he or she uses in almost every project. Many of the examples in the book include a file called util.h, which is listed in this appendix.
Coding Style Guidelines
util.h follows a simple coding style with only a few basic rules:
2. Format should reflect program structure. Indentation levels should reflect nesting levels, blank lines should separate logical tasks, and opening and closing curly braces should be aligned.
3. Comments shouldn't be overdone or underdone. Comments should be literate. Each file begins with a comment that at least contains the file's and author's names. Each function begins with a comment that tells the function's purpose. Non-obvious entry, exit, and exception conditions should also be mentioned. Remarks about algorithm can be included if they're helpful.
util.h
#ifndef UTIL_H
#define UTIL_H
// include just about everything:
#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <strstream>
#include <typeinfo>
#include <fstream>
using namespace std;
#include <cmath>
#include <cctype>
#include <cstring>
#include <cerrno>
/*
* Generic error handling for
small programs.
*
* EXIT: terminates program if
DEBUG_MODE true.
* Throws exception, otherwise.
*/
#define DEBUG_MODE true
inline void error(const string&
gripe)
{
if (DEBUG_MODE)
{
cerr << "Error, " << gripe << "!\n";
exit(1); // terminate program
}
else // release
mode
throw runtime_error(gripe);
}
/*
* ostream insertion templates
for STL containers
*
* ENTRY: operator<<()
must be defined for Data
* EXIT: characters inserted
into os
*/
template <typename Data>
ostream& operator<<(ostream&
os, const vector<Data>& v)
{
os << "<
";
vector<Data>::const_iterator
p;
for( p = v.begin();
p != v.end(); p++)
os << *p << ' ';
os << '>';
return os;
}
template <typename Data>
ostream& operator<<(ostream&
os, const list<Data>& v)
{
os << "(
";
list<Data>::const_iterator
p;
for( p = v.begin();
p != v.end(); p++)
os << *p << ' ';
os << ")";
return os;
}
template <typename Data>
ostream& operator<<(ostream&
os, const set<Data>& v)
{
os << "{
";
set<Data>::const_iterator
p;
for( p = v.begin();
p != v.end(); p++)
os << *p << ' ';
os << "}";
return os;
}
template <typename Key, typename
Data>
ostream& operator<<(ostream&
os, const pair<Key, Data>& v)
{
os << '('
<< v.first << ", " << v.second << ')';
return os;
}
template <typename Key, typename
Data>
ostream& operator<<(ostream&
os, const map<Key, Data>& m)
{
map<Key, Data>::const_iterator
p;
cout << "{\n";
for( p = m.begin();
p != m.end(); p++) os << *p << endl;
cout << "}\n";
return os;
}
/*
* Searching maps.
*
* ENTRY: k = search key, m =
map to
* search, v = a place to store
the value
* associated with k in m.
*
* EXIT: Returns true if search
was
* successful, and places associated
value in v.
* Otherwise, false is returned
and v is unchaned.
*/
template <typename Key, typename
Data>
bool find(Key k, Data& v,
const map<Key, Data>& m)
{
map<Key, Data>::const_iterator
p;
p = m.find(k);
if (p == m.end())
return false;
else
{
v = (*p).second;
return true;
}
}
/*
* Binary to string conversion.
*
* ENTRY: operator<<()
defined for Data
*/
template <typename Data>
string toString(const Data&
val)
{
ostrstream os;
os << val
<< ends;
return os.str();
}
/*
* String to binary conversion
*
* ENTRY: operator>>() defined
for Data
* EXIT: val holds binary value
of str
*/
template <typename Data>
void fromString(Data& val,
const string& str)
{
istrstream is(str);
is >> val;
}
/*
* Generic data entry with error
checking.
*
* ENTRY: operator>>() defined
for Data
* EXIT: val holds extracted
data
*/
template <typename Data>
void getData(Data& var,
const string& prompt)
{
Data response;
cout << prompt
+ " -> ";
while (!(cin >>
response))
{
cerr << "Invalid entry, ";
cerr << "please try again or type <Ctrl>c to quit\n";
cin.clear(); // clear failure flag
cin.sync(); // flush buffer
cout << prompt + " -> ";
}
cout << "You
entered " << response << endl;
var = response;
}
/*
* Non-blocking way to find out
if
* characters are waiting to
be read.
*/
inline int moreChars(istream&
is = cin)
{
return is.rdbuf()->in_avail();
}
#endif