C++ Logo

std-proposals

Advanced search

Re: [std-proposals] !continue

From: Brian Bi <bbi5291_at_[hidden]>
Date: Sun, 5 Nov 2023 15:42:14 -0500
On Sun, Nov 5, 2023, 3: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.
>

I've encountered this before when writing parsing code. Sometimes you want
to transition to a different state and then re-process the current
character.

I dealt with it by using `goto` to jump to the beginning of the loop body.
I think this is a better option than introducing a new and obscure control
flow construct.


> 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-05 20:42:25