Connecting Tech Pros Worldwide Forums | Help | Site Map

Exiting a loop half way through

Buster Copley
Guest
 
Posts: n/a
#1: Jul 19 '05
While playing around with my quine I was reminded
of a situation I have come across before: when
the exit-condition for a loop needs to be checked
in the middle of a loop, rather than at the
beginning (while) or the end (do ... while). It
always seems to come up when I'm hand-rolling very
simple parsers. (Doctor, it hurts when I do this ...)

Anyone want to argue for or against any of these
three alternatives, or suggest something better?

template <typename RulesFuction>
void format (const string & s, RulesFunction f)
{
// f will be applied to an iterator to a '%' character.
// Applying f should return an iterator to the character
// after the whole '%' escape sequence.
// Side-effects of f should be limited to output on cout.

iter b (s.begin ()), e (s.end ()), i;
ostream_iterator <char> out (cout);

#if defined A

copy (b, i = find (b, e, '%'), out);
while (i != e) {
b = f (i);
copy (b, i = find (b, e, '%'), out);
}

#elif defined B

while (true) {
copy (b, i = find (b, e, '%'), out);
if (i == e) break;
b = f (i);
}

#else

goto start;
while (i != e) {
b = f (i);
start: copy (b, i = find (b, e, '%'), out);
}

#endif

}


Buster Copley
Guest
 
Posts: n/a
#2: Jul 19 '05

re: Exiting a loop half way through


Buster Copley wrote:[color=blue]
> While playing around with my quine[/color]

Practice what you preach, Buster. The complete,
compilable code follows. You can see which way
I've settled on at the moment.

#include <iostream>
#include <ostream>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
typedef string::const_iterator iter;

template <typename F>
void format (const string & s, F f) {
iter b (s.begin ()), e (s.end ()), i;
ostream_iterator <char> out (cout);
goto start;
while (i != e) {
b = f (i);
start: copy (b, i = find (b, e, '%'), out);
}
}

iter p (iter i) {
cout << '%' << * ++ i;
if (* i == 'n') cout << "\"\n \"";
return ++ i;
}

struct q {
iter operator () (iter i) {
switch (* ++ i) {
case 's': format (s, p); break;
case 'n': cout << '\n'; break;
case 'q': cout << '\"'; break;
case 'b': cout << '\\'; break;
default: cout << * i;
}
return ++ i;
}
q (const string & s) : s (s) { }
const string & s;
};

int main () {
string s (
"#include <iostream>%n"
"#include <ostream>%n"
"#include <string>%n"
"#include <algorithm>%n"
"#include <iterator>%n"
"using namespace std;%n"
"typedef string::const_iterator iter;%n"
"%n"
"template <typename F>%n"
"void format (const string & s, F f) {%n"
" iter b (s.begin ()), e (s.end ()), i;%n"
" ostream_iterator <char> out (cout);%n"
" goto start;%n"
" while (i != e) {%n"
" b = f (i);%n"
" start: copy (b, i = find (b, e, '%%'), out);%n"
" }%n"
"}%n"
"%n"
"iter p (iter i) {%n"
" cout << '%%' << * ++ i;%n"
" if (* i == 'n') cout << %q%b%q%bn %b%q%q;%n"
" return ++ i;%n"
"}%n"
"%n"
"struct q {%n"
" iter operator () (iter i) {%n"
" switch (* ++ i) {%n"
" case 's': format (s, p); break;%n"
" case 'n': cout << '%bn'; break;%n"
" case 'q': cout << '%b%q'; break;%n"
" case 'b': cout << '%b%b'; break;%n"
" default: cout << * i;%n"
" }%n"
" return ++ i;%n"
" }%n"
" q (const string & s) : s (s) { }%n"
" const string & s;%n"
"};%n"
"%n"
"int main () {%n"
" string s (%n"
" %q%s%q);%n"
" format (s, q (s));%n"
"}%n"
"");
format (s, q (s));
}

White Wolf
Guest
 
Posts: n/a
#3: Jul 19 '05

re: Exiting a loop half way through


Buster Copley wrote:[color=blue]
> While playing around with my quine I was reminded
> of a situation I have come across before: when
> the exit-condition for a loop needs to be checked
> in the middle of a loop, rather than at the
> beginning (while) or the end (do ... while). It
> always seems to come up when I'm hand-rolling very
> simple parsers. (Doctor, it hurts when I do this ...)
>
> Anyone want to argue for or against any of these
> three alternatives, or suggest something better?
>
> copy (b, i = find (b, e, '%'), out);
> while (i != e) {
> b = f (i);
> copy (b, i = find (b, e, '%'), out);[/color]

Code duplication.
[color=blue]
> #elif defined B
>
> while (true) {
> copy (b, i = find (b, e, '%'), out);
> if (i == e) break;
> b = f (i);[/color]

How I used to do that (if I had to) was to add // NOTE! after the break.
So no one will miss it.
[color=blue]
> goto start;
> while (i != e) {
> b = f (i);
> start: copy (b, i = find (b, e, '%'), out);[/color]

Ahh. I looked at a goto. Now I have to go and confess. :-)

I sort of like that. It reminds me of the Duff's device and this:

http://www.cuj.com/documents/s=8890/cujexp0310dewhurst/

Since I am coming down with a fever (and it is not Saturday night here) I
might have missed important things here.

--
WW aka Attila


Buster Copley
Guest
 
Posts: n/a
#4: Jul 19 '05

re: Exiting a loop half way through


White Wolf wrote:[color=blue][color=green]
>> copy (b, i = find (b, e, '%'), out);
>> while (i != e) {
>> b = f (i);
>> copy (b, i = find (b, e, '%'), out);[/color]
>
> Code duplication.[/color]

Yeah, that's my least favourite.
[color=blue][color=green]
>>#elif defined B
>>
>> while (true) {
>> copy (b, i = find (b, e, '%'), out);
>> if (i == e) break;
>> b = f (i);[/color]
>
>
> How I used to do that (if I had to) was to add // NOTE! after the break.
> So no one will miss it.[/color]

Good call.
[color=blue][color=green]
>> goto start;
>> while (i != e) {
>> b = f (i);
>> start: copy (b, i = find (b, e, '%'), out);[/color]
>
>
> Ahh. I looked at a goto. Now I have to go and confess. :-)
>
> I sort of like that.[/color]

Me too.
[color=blue]
> It reminds me of the Duff's device and this:
>
> http://www.cuj.com/documents/s=8890/cujexp0310dewhurst/
>
> Since I am coming down with a fever (and it is not Saturday night here) I
> might have missed important things here.[/color]

Thanks a lot for your comments.

Kevin Saff
Guest
 
Posts: n/a
#5: Jul 19 '05

re: Exiting a loop half way through


"White Wolf" <wolof@freemail.hu> wrote in message
news:bkd0hj$9ah$1@phys-news1.kolumbus.fi...[color=blue][color=green]
> > #elif defined B
> >
> > while (true) {
> > copy (b, i = find (b, e, '%'), out);
> > if (i == e) break;
> > b = f (i);[/color]
>
> How I used to do that (if I had to) was to add // NOTE! after the break.
> So no one will miss it.[/color]

Hello, Wolf and Buster.

Did you ever consider:

while(true)
{
doSomethingFirst();
if (condition)
break;

doSomethingElse();
}

or possibly even (although I wouldn't do this):

while(true)
{
doSomethingFirst();

if (condition) break;

doSomethingElse();
}

To me whitespace seems the most natural way to emphasize control statements,
since most whitespace is already used for that very purpose.



Buster
Guest
 
Posts: n/a
#6: Jul 19 '05

re: Exiting a loop half way through


"Kevin Saff" <google.com@kevin.saff.net> wrote
[color=blue]
> while(true)
> {
> doSomethingFirst();
> if (condition)
> break;
>
> doSomethingElse();
> }
>
> To me whitespace seems the most natural way to emphasize control statements,
> since most whitespace is already used for that very purpose.[/color]

Thanks very much for your response.
Buster


Closed Thread


Similar C / C++ bytes