|
by Francis Glassborow
A Problem
A few days ago, I was working on a problem to do with a simple
menu driven graphical design process written in C++. The problem was
that I wanted to be able to offer an undo option. Unfortunately the
nature of some of the actions left only two reasonable choices; save
the prior state – about 260Kbytes of data – or redo everything
from a known point. The individual actions run fast so in an
interactive mode redoing would be acceptably fast.
Even with memory measured in gigabytes I am reluctant to store
prior states with that amount of data. Just a one level undo is, in
my opinion, unreasonable with the resources the average user has
available.
However, storing the actions for a redo from scratch has a major
advantage, it means that in addition to a simple multi-level undo,
we can also provide facilities for editing an action without having
to undo back to it.
My immediate thought was that the individual menu choices formed
a sequence and could be stored in an STL type container. The trouble
with that idea is that I want a simple design without going down the
route of smart pointers or proxy objects. I needed a single type
that could be stored in a container, and I needed a simple way to
create instances of that type.
An Idea
I fairly soon realised that the C++ string
type could act as a place to store the data. But was there some
quick, uniform way to create such a string for each menu option?
Once I phrased the question that way, an answer sprang to mind,
use a stringstream object to do the
conversions. The data being input from the keyboard would be easily
inserted into such an object. Furthermore, we could use a stringstream
as a source as well as a sink for data so redoing an action would,
with a few tweaks, be the same as the original with cin
replaced by a stringstream object.
Confused? Perhaps some code snippets will help:
int
main(){
playpen pic;
vector<string> acts;
bool finished(false);
do {
display_choices();
int choice=get_choice();
finished = do_choice(choice, acts, pic);
} while(!finished)
} |
Inside do_choice() we will find
something like:
if
(recordable(choice))
{
stringstream act_data;
act_data << char(choice) << "
";
// code to handle individual
// choices, passing them
// act_data by reference.
acts.push_back(act_data.str());
}
else
{
// code for cases which
// are not recordable,
// e.g. save, load, quit,
// undo, etc.
} |
The key feature is that stringstream
objects support two member functions called str().
Here we are using the version that has no parameters, which returns,
by value, the string being used as a
buffer. We can simply push that string
onto the end of our vector of string.
The result is that we create a sequence of actions stored as string
objects in a vector. We can write
that data back to a file and we can process it by removing entries
or by editing them (probably with another menu driven process to
which we could apply a similar strategy to allow us to undo edits.)
We can write a do_all() function
that takes a vector<string>
containing the actions and repeats them. The top level of such a
function will be purpose written but most of the implementation can
build on our existing functions that execute the different actions.
The primary difference being that they will use a stringstream
object as their data source.
The key to that last process comes from using the second form of
the str() member function. If you
provide a string argument it replaces the current buffer with that
one. Again, a small code snippet:
void
do_all_actions(vector<string>& acts)
{
stringstream next_act;
for(int i=0;i!=acts.size(); ++i)
{
process_act(next_act.str(acts[i]));
}
} |
This is no more than the rudiments of a mechanism and you will
have to do quite a bit more to flesh it out into high quality,
possibly OO, source code.
A Second Idea
While I was working out my idea for using stringstream
objects as sources and sinks for data I remembered one of the
questions that newcomers to C++ frequently ask: How do I covert a
number into a string?
An expert will quite likely say “Use Boost's
lexical_cast.” I am unconvinced that that is a particularly
helpful response. Boost's (see www.boost.org)
lexical_cast is an all singing, all
dancing template which may, or may not, meet your needs, but is
certainly going to consume valuable time while you read the
documentation and learn to use it.
Most programmers just want a quick way to convert data to a
string the following little template probably does all they want and
a bit more as a bonus:
template<typename
strable>
string to_str(strable data)
{
stringstream converter;
converter << data;
return convertible.str();
} |
This code converts any type that supports an operator <<
into a string. Thus, it will work for all the built-in types and
also for many user-defined types. It does not try to do anything
clever, but could, with a extra work, be extended to take a format
string. I am not convinced that it would be worth the effort.
I advocate of simple code that meets most needs, leaving the generalizations
for those that need them.
Summary
Those working on GUI event driven applications often ignore the
C++ stream facilities because they use OS specific mechanisms for
data capture and display. Others working in environments where the
C++ console objects and fstream
types make sense focus entirely on those. I think that the C++ stringstream
class has much to offer both groups in that it provides mechanisms
for handling data in a single homogeneous form. Like much of C++,
the benefit comes from the synergy of combining the different
resources the language provides.
by Francis Glassborow
WG21 & J16 (C++) and WG14 & J11 (C) are currently in
maintenance mode with respect to the relevant Standard. Both are
preparing to start work on the next release of their Standard
(scheduled for some time at the end of this decade). There are many
issues that have to be tackled but to understand the constraints, we
need to understand how we got to where we are today.
In this series I intend to tackle various issues that I find
important, particularly those that are often not fully understood. I
hope that many readers will feel the desire to chip in and do so by
emailing either the editor of ACCent or directly to me (francis_at_robinton.demon.co.uk).
The committee members of the above names committees are often
accused of not listening to the C and C++ communities. The putative
evidence for this is that they do not make the changes an individual
wants and believes to be self evidently a ‘good thing.’
Putting aside for one moment that they are all unpaid (indeed,
not a few pay serious money from their own pockets to be involved)
volunteers, there is a serious issue of how they should know what
you want if you do not clearly tell them and listen to the answer.
As the saying goes, it takes two to tango.
When thinking about a proposal for extension or change it is
important to understand the impact such a change would have on
existing code. Every change has a cost, and almost every change will
constrain potential future changes. Let me deal with a very simple
cost in the remainder of this column before moving on to other costs
in future columns.
Breaks Existing Code
It has long been a contention of mine that one of the weaknesses
of K&R is that the authors do not mention tools such as lint
that were designed to ensure consistency between files. The
consequence was that several major companies implemented C for their
platform of choice without providing those tools. That left C open
to criticism because of its potential for dangerous linkage
practices.
It was only very recently that I discovered why lint is a
distinct tool rather than an implicit part of C implementations.
When Ritchie proposed to add the underpinning for stronger linkage
requirements he hit upon the legacy
code problem. Adding those features would have broken just about
every piece of C code that had been written. That was unacceptable,
the cost was considered to be too high.
The fix was to move that responsibility to another tool whose use
was entirely optional. That decision reinforced the 'Trust the
Programmer' paradigm for code development.
All would have been well had the then future generations of C
programmers been taught that lint was an essential tool. It would
have been even better if a lint like tool had been bound into the
compiler-linker chain by default. It wasn't with the result that
most programmers have to go and get a third party tool such as
PCLint in order to do a professional job with C development.
A decision made more than two decades ago continues to haunt us
today. Yet I am sure that the original decision to not break
existing code was the right one, it is just that the consequences
might have been better managed.
Will we learn from that experience? Or are we doomed to repeat it
again and again?
Over to you, because my space has run out.
By Reg. Charney
I am pleased to announce that we have some exciting changes in
this newsletter. First, we are in transition to a new editor – DS
Moen; and second, we have a new and exceedingly knowledgeable
regular columnist – Francis Glassborow.
Our New Editor
While I have guided ACCent since its inception, I felt it needed
to be made more exciting, relevant, and interesting. To that end,
some else needed to lead the effort. That someone needed to be more
intimately involved with the nuts and bolts of the Valley and its
currents and moods. I believe that I found her.
I am pleased to welcome Deirdre Saorise Moen as our new editor.
She has been a software engineer for more than twenty years and has
worked on scientific, shrink-wrap, and general applications. She
became interested in open source while working at an ISP where she
was introduced to many forms of UNIX as well as Linux. She is also a
science fiction enthusiast and author.
After moving to the Bay area, She helped found BayPIGgies, an
interest group for the Python language, now led by Wesley Chun and
Danny Yoo.
Francis Glassborow
Causes are often only real when they have a human face. Francis
Glassborow is that person for me and why I am an ACCU member and
founded ACCent.
Francis is English, a retired school master, a life-time member
of the ACCU, former editor of the ACCU's C Vu magazine, and
prodigious book reviewer. He is one of the main contributors to the
3000+ book reviews on the main ACCU site. He helped organized one of
the world's best annual programming conferences in Oxford, England.
Obviously, he cares deeply about our profession. Welcome to
ACCent.
I was contact early this month by Luby Aczel, a Volunteer
Coordinator for the non-profit Northern California studio of
Recording for the Blind and Dyslexic. They create and lend
educational material on CD or four track cassette to individuals
with learning or visual disabilities. They need volunteers to read
the many technical and computer manuals for which they get requests.
Please visit their web site at www.rfbd.org
to find out more about them. You can also contact Luby Aczel, at
650-493-3717, ext. 13
The C++ Standard Library,
A Tutorial and Reference by Nicolai M. Josuttis,
Addison-Wesley, 1999, ISBN 0-201-37926-0, 799pp
Rating: Highly Recommended
Reading Level: Easy.
This book is for C++ programmers at all experience levels.
The stated goal of this book is to “describe the C++ standard
library so that all (or almost all) your programming questions are
answered before you think of the question”, and it succeeds at
this. It provides a conceptual overview of the components of the
library, describes the details needed to use the components (with
many useful source examples), and points out traps and pitfalls and
ways of avoiding these.
Space does not permit an extensive list of the topics covered,
but as an example, auto_ptr is
covered for 21 pages, including a good discussion of when not to use
auto_ptr.
The technical writing is excellent, being both precise and easy
to read. It achieves the difficult goal of being simultaneously
readable as a tutorial and usable as a reference.
I was only able to find two minor errors (although a few more are
listed on the author's web site), which is very impressive for a
book of this size and complexity.
There is an extensive index. In practice, it was fairly easy to
use the index to locate any topics of interest.
I am not aware of any other book that covers the subject with
nearly this much breadth and depth.
I think that some of the most important changes during the C++
standardization process were to the standard library. This book is a
great way for programmers to catch up on any of these changes that
they may have missed.
Essential for any programmer serious about writing modern C++
code
— Wayne Vucenic
By Reg Charney and Ali
Çehreli
Generally, looking at all the data we have, we have yet to see a
turnaround in the employment picture in the Valley. Normally, the
newer technologies spurt ahead after their introduction. This has
not really been the case, as far as the Valley goes. We are
currently tracking UML, .NET, Security, and Multimedia openings. In
Figure #1, you can see that even with the money Microsoft is pouring
into .NET, its adoption is slowing. In the Valley, there were only 5
openings for Windows XP device drivers. For Windows overall, there
were only 39 openings while there were 7 Linux openings. Security,
last year’s poster child for “hot” technologies is not doing
as well as most of us would hope—this while we are getting
inundated with SPAM and viruses, worms, Trojan horses, etc.

|