In this particular case I think you could do one of the following (ignoring the "while (true)" + "break" combination):
1:
while (printOneStr(s[i]), ++i < n)
printOneStr(", ");
2: goto start;
do {
printOneStr(", ");
start:
printOneStr(s[i]);
++i;
} while (i < n);
But for this kind of code in general, I have thought that the "do while" statement should be extended to take an extra statement after the "while (cond)" part. It could still be an empty statement, with just a semicolon, like "do ... while (cond);", exactly like it's already used; but in cases like yours, you would be able to write this: do {
printOneStr(s[i]);
++i;
} while (i < n) {
printOneStr(", ");
}
As a bonus, the current mandatory semicolon after do-while statements would stop being a special case for the grammar of C.
- Somehow cram it into the loop expression with the comma operator. This is very limited because it is an expression. For example, what if 'printOneString' can err?
- Somehow use 'while(1)' with 'break'. It may even compile to the same code as with 'goto'. But why, then, we have to use an unbounded loop syntax with a clearly bounded sequence?
- Somehow add additional variables and tests and either lose efficiency or trust the compiler to lead us out.
With 'goto' the code does only what is necessary. What 'goto' does not do is that it does not immediately convey a clear idea that the code repeats certain steps.