Re: c++ begginer program help
Comment at very bottom
"James Kanze" <james.kanze@gmail.com> wrote in message
news:1175897394.643713.302750@b75g2000hsg.googlegroups.com...
On Apr 6, 12:00 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote:
<sren...@yahoo.com> wrote in message
news:1175710245.893820.280900@w1g2000hsg.googlegroups.com...
On the whole, your comments are on target, and correspond to
generally accepted good programming, but in thie particular
case...
[...]
forget about char* and use std::string, then you can use find, will make
your life a LOT easier.
Whatever you do, don't use char*, that's for sure. But in this
case, I don't think that std::string is really the answer
either.
[...]
How about:
while ( std::getline( line ) )
Generally (say about 99 times out of 100), I'd recommend the
same thing. If the grammar is line oriented, it makes
resynchronizing after an error child's play, and even if the
grammar isn't line oriented, it provides as good a "chunk" as
anything else, and makes it easy to indicate line numbers in the
error messages.
In his case, however, he isn't doing any real parsing, and
there's no error handling, so these considerations don't come
into play. And one of his constructs (a block comment) can
extend across line boundaries---I think you'll find handling it
correctly no easy job if you insist on reading line by line. In
this one particular case (again: it's an exception---your
suggestions are better 99% of the time), I'd use a sliding
window in the file, implemented using std::deque<char>. It took
me less than 5 minutes to come up the following general sketch:
class Window
{
public:
explicit Window( size_t size = 2 ) ;
size_t fill( std::istream& source ) ;
void pop( size_t n = 1 ) ;
char top() const ;
size_t size() const ;
bool matchPrefix( std::string const& target )
const ;
private:
size_t myMaxSize ;
std::deque< char > myWindow ;
} ;
Window::Window(
size_t size )
: myMaxSize( size )
{
}
size_t
Window::fill(
std::istream& source )
{
while ( source && myWindow.size() != myMaxSize ) {
char ch ;
if ( source.get( ch ) ) {
myWindow.push_back( ch ) ;
}
}
return myWindow.size() ;
}
void
Window::pop(
size_t n )
{
myWindow.erase(
myWindow.begin(),
myWindow.begin() + std::min( myWindow.size(), n ) ) ;
}
char
Window::top() const
{
assert( ! myWindow.empty() ) ;
return myWindow.front() ;
}
size_t
Window::size() const
{
return myWindow.size() ;
}
bool
Window::matchPrefix(
std::string const& target ) const
{
return myWindow.size() >= target.size()
&& std::equal( target.begin(), target.end(),
myWindow.begin() ) ;
}
int
main()
{
enum State
{
start,
inBlockComment,
inLineComment
} state = start ;
Window w ;
while ( w.fill( std::cin ) != 0 ) {
switch ( state ) {
case start :
if ( w.matchPrefix( "//" ) ) {
state = inLineComment ;
w.pop( 2 ) ;
} else if ( w.matchPrefix( "/*" ) ) {
state = inBlockComment ;
w.pop( 2 ) ;
} else {
std::cout << w.top() ;
w.pop( 1 ) ;
}
break ;
case inBlockComment :
if ( w.matchPrefix( "*/" ) ) {
state = start ;
w.pop( 2 ) ;
} else {
w.pop( 1 ) ;
}
break ;
case inLineComment :
if ( w.matchPrefix( "\n" ) ) {
state = start ;
} else {
w.pop( 1 ) ;
}
break ;
}
}
return 0 ;
}
Hmm.. I dont' see where you checked for ending a block comment, or where
you
are not writing anything if you started a block comment.
Which will be non-trivial problems if he reads line by line.
==========
Actually, I could fix his program rather quickly to work using
std::getline( std::cin, line ); A comment start or end has to be in one
line. I.E.
keyword(); // comment
is legal but
keyword(); /
/ comment
isn't.
So for the end of line comment // it's easy.
Same with block comment, the start or stop has to be in one line.
I don't, at this point, want to show how I would do it because I"m quite
sure this is homework, and the OP needs to do it on their own to learn.
Basically, however, you just have to keep a flag stating if you are in the
middle of a block comment and act accordingly looking for the end of block
comment in any line.