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:
1. Names
should be chosen to reflect their interpretation. Type names begin with
uppercase letters, function, parameter, and variable names begin with lower
case letters, and macro names only use uppercase letters.
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.
Many
universities and companies have their own style guidelines, which readers are
welcome to use in place of mine, but some style guideline must be followed.
There are several proposals for standard C++ style guidelines, which readers
may also use.
util.h
/*
* File: pop\util\util.h
* Programmer: Pearce
* Copyright (c): 2000, all rights reserved.
*/
#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