C++ Logo

std-proposals

Advanced search

Re: [std-proposals] !continue

From: Chris Gary <cgary512_at_[hidden]>
Date: Mon, 6 Nov 2023 09:25:34 -0700
I'm not sure if someone's already mentioned this, but is there anything
wrong with making this into a "while"?
To increment, or not to increment? That is the question.
Every text processing loop I've ever written has been a "while" loop for
this reason.
Sometimes you just need to check the next character without consuming it,
and sometimes you need to take a step larger than one character.

Try something like making a LineInput class with a PushBack( c ) that
returns "true" if it detected an EOL condition.

Then your loop might be:

while( Serial.available() )
{
  if( line.PushBack( Serial.read() ) )
  {
    // We have a complete line, parse it.
    if( ! ProcessCommand( line.GetPtr() ) ){ break; }// Break if the
command met a terminal condition
  }
}

I'm aware of the limitations of embedded environments like an Arduino, and
so understandably there should really be more error handling to do with the
buffer filling up and other things.
However, this is just one challenge in dealing with unconstrained serial
communications; QoS issues being the much more difficult set of problems.
It pays to have layered code that can separate QoS issues from actual
behavioral implementation, and something like a LineInput can help with
that.

I've often found myself in need of some way to break out of nested loops,
or break from a loop within a switch statement, but then later found it
could be refactored into something more readable.

On Sun, Nov 5, 2023 at 1:39 PM Frederick Virchanza Gotham via Std-Proposals
<std-proposals_at_[hidden]> wrote:

> Today I was programming an Arduino microcontroller and I wrote the
> following loop:
>
> for ( ; Serial.available(); ++p )
> {
> if ( p >= &buf[sizeof(buf) - 1u] ) break;
> p[0u] = Serial.read();
> p[1u] = '\0';
> unsigned const len = std::strlen(buf);
> char *ending = nullptr;
> if ( nullptr != (ending = std::strstr(buf, "\r\n")) )
> {
> ending[0u] = '\0';
> ending[1u] = '\0'; // Overwrite the "\r\n" with "\0\0"
> if ( ending != buf ) this->ProcessInput();
> buf[0u] = '\0';
> p = buf - 1u; // subtract 1 because it will be
> incremented upon continuing
> }
> }
>
> On the third last line, you'll see that I wrote:
>
> p = buf - 1u; // subtract 1 because it will be incremented upon
> continuing
>
> instead of just:
>
> p = buf;
>
> and that's because 'p' will get incremented upon the next iteration of
> the loop, i.e. the 'for' loop has '++p' as the post-iterative step.
>
> This code I've written today will work fine on a microcontroller, but
> on a desktop PC that has extreme debugging enabled (for example
> 'mudflap' or 'address santiser'), the debugger will stop the program
> when it sees that 'p' has become less than 'buf'.
>
> So I was thinking . . . what if we could easily express that we want
> to continue on to the next iteration of the loop, but that we don't
> want to execute the post-iterative step. Maybe we could write
> "!continue" for this, something like:
>
> for ( ; SerialSimGsm.available(); ++p )
> {
> if ( p >= &buf[sizeof(buf) - 1u] ) break;
> p[0u] = SerialSimGsm.read();
> p[1u] = '\0';
> unsigned const len = std::strlen(buf);
> char *ending = nullptr;
> if ( nullptr != (ending = std::strstr(buf, "\r\n")) )
> {
> ending[0u] = '\0';
> ending[1u] = '\0'; // Overwrite the "\r\n" with "\0\0"
> if ( ending != buf ) this->ProcessInput();
> buf[0u] = '\0';
> p = buf;
> !continue; // Don't allow 'p' to be incremented
> }
> }
>
> In this example, the post-iterative step is quite simple, but there
> are other times when I write loops like:
>
> for ( ; Serial.available(); delayMicroseconds(750u), ++p )
> or:
>
> for ( ; Serial.available(); Serial2.write(Serial.read()) )
> DoSomethingInBetween();
>
> and so the statement "!continue" could be quite versatile in these
> more complex loops.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-11-06 16:25:46