R. Clayton (rclayton@monmouth.edu)
(no date)
I have two programs in a file
mov r0 12
mov r1 13
+ r1 r2
mov r4 12
mov r6 19
- r4 r6
I tried using istream_iterator and std::copy to copy the instructions into a
list. I tried another version using an overloaded << operator to read this
program into a list of Instructions (I have a class called
Instruction). When I ran the program in windows it read the blank line as an
empty string and called the default constructor of the class Instruction to
push_back the Instruction into the list. But on Solaris using both STL and
SaferSTL, the blank line never gets read as a blank line. Instead the
previous instruction read (+ r1 r2) gets copied into the list. I tried
several different versions of code and added checks for cin.fail() but to no
avail.
This didn't work -
std::list<Instruction>
tmp(std::istream_iterator<Instruction>(cin),
std::istream_iterator<Instruction>());
This didn't work either
Instruction i;
while (cin >> i)
if (cin.fail())
tmp.push_back(Instruction());
cin.clear();
else tmp.push_back(i);
Is there something I'm doing wrong? All versions work correctly on windows.
To be able to answer your question, I'd need to see how you implemented
instruction extraction. Let's assume you did the obvious:
struct instruction
string op, first_arg, second_arg
istream & operator >> (istream & is, instruction & i)
return is >> i.op >> i.first_arg >> i.second_arg
As you noticed, this implementation doesn't respect blank lines. Extraction
will chew through all leading space characters until if finds a non-space
character, which it takes as the first character of the string giving the
op-code name; this is the standard default behavior. (I don't understand why
you got the previous instruction back, I'll guess that it has something to do
with your code.)
But that's not the only problem. Instruction extraction as given will accept
move
r1
a move
as legal input because it also chews through all the other space characters
too.
These problems can be fixed by changing instruction extraction, but that's
not a particularly easy course to take. As an alternative, reconsider your
solution.
By going from input stream to a pair of programs, you are, in my opinion,
taking too big a step. My solution handles this in two steps: reading two
blocks of text from the input stream, and then translating each block of text
into a program consisting of a sequence of instructions:
text_block tb1, tb2, tb3
if not std::cin >> tb1
error missing program
if not std::cin >> tb2
error missing program
if std::cin >> tb3
error extra junk on input
string emsg
program p1(tb1, emsg)
if not emsg.empty()
error emsg
program p2(tb2, emsg)
if not emsg.empty()
error emsg
Reading blocks of text from input is something I do often, so extraction for
that's already done:
istream operator >> (istream & is, text_block & tb)
tb.clear()
string str
do
if not getline(is, str)
return is
while is_blank_line(str)
do tb.push_back(str)
while getline(is, str) and not is_blank_line(str)
return is
By using getline() I avoid two problems: assembling input into lines
(getline() does that for me) and run-away space skipping (getline() doesn't
skip space characters).
This archive was generated by hypermail 2.0b3 on Mon May 03 2004 - 17:00:06 EDT