C++ Questions

Pages: 1... 34567... 10
Let me try to be clearer, it makes absolute no sense to have the program declare and initialize WITHIN the loop, since it will be reset to zero in this case, with each iteration. I believe that to be correct and the reason why they chose to do this.

If there was a way to distinguish an initial variable set versus a change to the variable, then it would be possible to allow the bool test variable to be instantiated WITHIN, but since there is no way, then this is not possible...even though the while() test is outside the block...because in reality they can do ANYTHING they want, even have the while() test be "considered" within the block.

In a for() loop one can declare and initialize variables inside the parenthesis, which happens before the {} blocked code and therefore is allowed. And you can distinguish an initial test variable set versus variable iteration.
jonnin, thanks. I was referring to the do/while() loop specifically. I was just trying to get at the root of why it was done this way.

Why do I get a feeling that the do/while() loop might be due for a change or might benefit from a change. Maybe at the very least have the do/while(){} have its own scope and execute it only if it passes the first test and only after the first default iteration/pass-through. Ideally, maybe like the structure of a for loop with it's own body scope like a Lambda:

do
{
}while(;;){cout << "NOT FOUND TRY AGAIN...";};

That is a great idea for variable and object termination within a block code, I will keep it in mind with future needs, thanks!

Last edited on
Hi SubZeroWins,

While there are valid uses of a do loop, I am not a fan of them, or rather don't seem to need them at all. With the 3 types of loop, it is always possible to convert from one to another.

Notice in your do loop, you have the same boolean condition twice, once inside the loop and again as the loop condition.

Wanting a loop to run at least once is not a reason to use a do loop IMO, because it can always be written as a while or for loop.

One example where a do loop might be used, is from K&R "C Programming" book, when copying a null terminated C style string, the null must be written even if the string is zero length. In this case one can't have a for or while loop, because it runs zero times and stuff still needs to be done regardless.

SubZeroWins wrote:
Why do I get a feeling that the do/while() loop might be due for a change or might benefit from a change. Maybe at the very least have the do/while(){} have its own scope and execute it only if it passes the first test and only after the first default iteration/pass-through. Ideally, maybe like the structure of a for loop with it's own body scope like a Lambda:

1
2
3
do
{
}while(;;){cout << "NOT FOUND TRY AGAIN...";};


None of that make any sense to me, at all. If one wants to output "NOT FOUND TRY AGAIN..." , put it at the end of the loop body. The do loop does have it's own scope, it's in the body of the loop. A while loop can be used to interactively get a correct value for a variable.

I don't think do-while can be scoped easily. I mean you can define it in the language, but it would become something really screwy like
do (int x = 0) { .. } while(!x);

maybe just not used to that, but it looks like an ugly bandaid to me.
The for loop can "be" a while loop or even a do-while with careful hand waving of its flexible parameterized design. It covers all the edge cases by itself. Making the while loops do more ... you could... seems like a hammer in search of a nail.

Thanks George!

TheIdeasMan, no I understand that it can be done with other iterators/loops. I need that printout each time it goes through the loop and not only at the end of the loop, which means user inputs a number that is not in the multiset. I can get it to work fine with the do loop and it is not about getting things to work.

This is no big deal, I was just wondering why they did it this way and what this groups thoughts were and if you ever thought the do/while can be improved upon. I thought there might even be a way already but that I have not seen yet with a do loop.

Here is the way my theoretical do/while loop would work; sorta like a a for() loop with an additional {} block body (like the way the Lambda has). The latter of which happens only if it goes through the loop the second time and thereafter.

Of course in this theory the "i" gets declared and initialized once before loops starts automatically, similar to a for() loop. Wouldn't this be a convenient way to have the do loop work?

1
2
3
4
5
6
7
8
9
10
11
12
	
	//int i = 0;
	do
	{
		cout << "Num to find: ";
		//int i =0;		//NOT WORK INSIDE OF LOOP!!!!!!!
		cin >> i;

		//if (ms1.count(i) == 0)
		//	cout << i << " NOT FOUND TRY AGAIN..." << endl;

	} while (int i = 0;  ms1.count(i) == 0; ) { cout << i << " NOT FOUND TRY AGAIN..." << endl; };
Last edited on
SubZeroWins wrote:
TheIdeasMan, no I understand that it can be done with other iterators/loops. I need that printout each time it goes through the loop and not only at the end of the loop, which means user inputs a number that is not in the multiset. I can get it to work fine with the do loop and it is not about getting things to work.


I was commenting about how it is bad form to use a do loop like this.

With this question there are several things: The code is about a guessing game; your reply doesn't make sense*; having a discussion about inventing a new type of do loop isn't really going to go anywhere, because the proposal isn't necessary.

* You want it at the end of the loop, and not only there, but it only appears once.

The range based for loop is rather flexible, one can have init statements, structured bindings, braced init lists or any container like thing that has defined begin and end iterators.

https://en.cppreference.com/w/cpp/language/range-for
In my experience, complicated loops are typically easier and faster to write if while (true) is used as a first try.

During this first try, use break and continue and goto however is needed to arrive at a working product. Once the code is working, you'll be able to tell if a do-loop or for-loop would be better:
1
2
3
4
5
6
7
8
9
10
while (true)
{
  cout << "Num to find: ";
  int i = 0;
  cin >> i; // TODO: handle failure properly to avoid potential infinite loop
 
  if (ms1.count(i) > 0) break;
  
  cout << i << " NOT FOUND TRY AGAIN...\n";
}

In this case I think that do-loops or for-loops don't suit very well and I would leave this unchanged.

To summarize, try using while (true) as a "default" choice if you're ever unsure which loop variant would be best for a particular problem.
Last edited on
SubZeroWins wrote:
The while() bool check, although is part of the loop, is considered to be outside the block code...and there is no inference the compiler has to include it as part to the block...that part is understood!

The compiler doesn't have a choice. The rules are specified by the C++ standard.

It would indeed have been convenient if the variables inside the loop body were still alive and accessible inside the loop condition of the do-while loop but the way that it currently works makes more sense technically and is more consistent with the rest of the language.

Note that the body of loops and if statements is technically just a single statement.

do statement while ( condition ) ;

Usually we use { and } and put multiple statements inside but that is another construct that is not part of the loop/if syntax itself.

{ ... } is a so called compound statement (a statement that contains a list of statements).
https://en.cppreference.com/w/cpp/language/statements#Compound_statements

The way compound statements works is that they introduce a new scope. If you declare variables inside there they will go out of scope (and get destroyed) at the end of the compound statement (when the } is reached). That's why these variables are not accessible outside the compound statement.

SubZeroWins wrote:
They could have programmed this alternatively though, ...

Yes, they could have. It would have been slightly inconsistent but maybe worth it. It's too late now though. They cannot change the rules now because that could change the meaning of existing programs. This is not a big deal because a workaround is simple.

SubZeroWins wrote:
... but there is no logical reason to reset a declared variable inside the loop and so it was forced to be declared outside.

There is nothing nonsensical about declaring variables inside loops. You just need to know the lifetime rules of local variable and realize it will get created and destroyed on each iteration. If that is not what you want then you need to write it some other way.
Last edited on
Without checking that input is a number, then as a 'simple' one-liner consider something like:

1
2
3
4
5
#include <iostream>

int main() {
	for (int i {}; (std::cout << "Enter even number: "), (std::cin >> i), (i % 2); std::cout << "Not even\n");
}


I used even test just for ease. For the previous given example, this would be ms1.count(i) == 0
Last edited on
I am surprised at your responses fellas. First I thought there might be some hidden or less seen syntax that I was unaware of, but that is not the case. Then I thought at the very least you would agree with me.

You can say the same thing about the for loop, it is not REALLY needed because there are alternative ways and yes having it makes it more convenient. Ditto for the range-based-for loop.

I know there are multiple ways of doing this and I could have even used the less recommended start: goto start.

Forget the other ways of doing this, it wouldn't tickle your fancy to have such a do loop? Here, I will make this new theoretical syntax a bit easier and exactly like the for loop then.

The benefit of this is:
1) You can include such things as a cout that you did not want to include on the very FIRST default loop through, only the 2nd time and thereafter.
2) Variable declaration & initialization can take place as part of the syntax (done before loop starts), just like a for loop.

You honestly would not prefer to have this sucker around? REALLY?

1
2
3
4
5
6
	do
	{
		cout << "Num to find: ";
		cin >> i;

	} while (int i = 0;  ms1.count(i) == 0; cout << i << " NOT FOUND TRY AGAIN..." << endl);
Oh and Happy Easter guys!

1
2
3
4
	if (yourEggCracked == true)
		cout << "Sorry, you lost man!" << endl;
	else
		cout << "Your on top of the Easter Bunny world!!!" << endl;
I wouldn't say no to some of your ideas but the above do while where you use a variable BEFORE it is created is nothing I would want to see at all.

that may seem reasonable to you, but try it in a 3-4 deep nested loop or a large loop body and all of a sudden 'where did i come from' becomes difficult to read or understand and violates rules that everything else follows religiously. Now your inner loop could be processing i, j, k, x and z each declared after the code that uses in different places as tags on the 'end' of different loop wrappers...
Last edited on
Learning to program has little to do with syntax and a LOT to do with being able to cleanly organize levels of abstraction into a step-by-step process.

For some people it is an extraordinarily easy thing to do. For others the opposite is true.

That says nothing for your intelligence or anything like that. It is a skill to be learned, and for those of us for whom it comes easier it is still often a very frustrating struggle to get right.

But it is a skill, and there are right and wrong ways to think about it. Which translates to right and wrong ways of doing things. The key is to recognize that there is a proscribed way to do every thing, and our task is simply to learn each thing properly.

("Simply" being the tongue-in-cheek word here. Simple varies concept by concept and person to person.)

And, honestly, beginner-level instructional stuff like you find all over the internet is not a substitute for more advanced instruction.
NO, this is a theoretical example and does not work as the do loop works now obviously. So, what your saying is it is not possible to ask the compiler to do this? Not possible to ask the compiler to create the variable before the loop starts?

The variable WILL BE and MUST BE created before the loop starts. That is why I said...
Of course in this theory the "i" gets declared and initialized once before loops starts automatically

Compiler sees the "do" and goes directly to the left side of the first ";" semicolon and creates the variable(s) ready to be consumed before the loop starts (and the variable ends upon loop exit). But if you like the compiler can also MOVE the variable(s) in code automatically so that it appears at the top of the do body like this:
do{int i = 0;} //And have the compiler recognize that var declaration is now allowed within!

So this will happen behind the scenes AUTOMATICALLY and the variable will be created.

So this will not violate anything. The compiler can already do much more complicated things, such as creating variadic overloaded functions, so this is an easy task for a future C++ upgrade I would gather.

Why, will the compiler not be able to create the variable or move the variable declaration/initialization before the loop starts like this?
@SubZeroWins
There are long and technical reasons why what you are asking is no where near as simple as you think it is. You are far, far removed from the first person to ever want to do something like that.

The “much more complicated things” that the compiler can do are actually very simple things in comparison.

While it seems like you want to apply a simple heuristic, you are ultimately asking to solve the Halting Problem. Short of that, you’ve got an inconsistent and buggy compiler.


But, all that aside — and, honestly, more to the point — you are trying to shoehorn the computer language into how you want it to work. And not to be overly reductionist, but... That’s Not How It Works™.

Remember, Occam’s razor always applies. You are asking for a very complicated piece of logic to do something humans can handle (and have been handling since the ’40s) with ease. It’s why humans program computers, and not computers.

’Cause computers are dumb.
Last edited on
Duthomhas wrote:
There are long and technical reasons why what you are asking is no where near as simple as you think it is. You are far, far removed from the first person to ever want to do something like that.

To my understanding, the proposed loop looks like
do loop-body-1; while (init; condition; increment) loop-body-2;
And is supposed to be roughly equivalent to
1
2
3
4
5
6
7
8
9
10
{
  init; 
  while (true) 
  {
    { loop-body-1; }
    if (! condition) break;
    { loop-body-2; }
    increment; 
  }
}

We could debate whether we need to add or remove braces and what the consequences are, but as you know, this is simple to implement.

It seems this new loop is conceptually the same as an infinite loop with at least one conditional break anywhere inside it. Contrast this with while (condition) loop-body;, which is equivalent to an infinite loop with a conditional break at the top:
while (true) { if (! condition) break; loop-body; }
And again with do loop-body; while (condition);, which is equivalent to an infinite loop with a conditional break at the end:
while (true) { loop-body; if (! condition) break(); }
So the proposal does, in a way, fill a gap in the loop variants.

That being said, I would vote strongly against it for a few reasons. Primarily because init runs before it is written in the code. That implies a surprising exception to the rules for object lifetime.

This is a big deal because C++ programmers manage system resources by controlling object lifetime (that is Resource Acquisition Is Initialization), so exceptions to the lifetime rules impact the viability of C++ for resource management.

Another reason is that this offers marginal benefit. I think it has no performance effects, wouldn't really speed up development (since we can just make a while loop), and could be a source of confusion and mistakes. I'd have to say "no" to this one.

BTW, In early C, all local variables were required to be declared at the start of the function (why?). Because of that restriction, this inconvenience:
do { int success = frob(foo); /*...*/ } while(success); // doesn't compile
did not exist. Note it doesn't compile even with modern C++, because the second mention of success is not in scope. I suspect that this inconvenience might have motivated your idea.
Last edited on
The same "inconvenience" also exists in other statically typed languages such as Java and C#.
IMO C/C++ should allow for a do-construct like this:

1
2
3
4
5
do int i {}; {
    cout << "Num to find: ";
    cin >> i;

} while ((ms1.count(i) == 0) && (cout << i << " NOT FOUND TRY AGAIN...\n"));


ie an optional variable definition statement following do with these variable(s) scope extending until the end of the while statement.
Pages: 1... 34567... 10