The program to determine wind direction works fine. It calls out an error message when outside 0 to 360 degrees and gives the correct direction within that range.
Problem is when entering a number somewhere between 1,111,111,111 and 2,222,222,222 the result is an infinite loop that prints a fast scrolling result. This tells me there is a number limit beyond which the computer does not recognize.
My calculation for a 32 bit variable limit is 4,294,967,296. Ten 2's is less than that so why the problem?
while (inputNumber > 1111111111 && inputNumber < 2222222222)
{...
}
will cause an infinite loop as you described. If your code doesn't contain that, ignore this post; I have to guess as it's very tricky to read your code without you posting any of it.
Thanks roberts but I discovered the problem which leads to another question.
The type declared was int which accounts for + and - numbers in memory. When I divided the 32 bit number by 2 and entered that number the result crashed, BUT when I reduced that number by one it ran correctly so I exceeded a memory limit.
Question:
How do developers prevent a crash like this? The user input (cin) occurs ahead of the conditional statement of between 0 and 360. A user could enter a crazy number with undesirable results. Isn't it the job of the developer to account for all scenarios and prevent it?
Roberts: my task is not equivalent to a periodic trig function.
Moschops: I have a conditional statement that tests input within 0 - 360. All others display an error.
What I seek is what I assume a developer would create to PREVENT a crash.
Looking for code to IDIOT PROOF the program. Mine and Moschops code does NOT do this.
Stated another way, if this were a real world product design situation that must GUARANTEE no crashes, then there must be a trick to prevent possible product damage.
I would think software testers do this everyday.
Any ideas to attack the problem to prevent memory exceedence from idiots?
That was my intent. I am asking for much more. See the do while loop? Doesn't that cover all numeric cases? Expect for memory exceedence which is the reason I posted the question originally.
Thanks.
#include <iostream>
using namespace std;
void main()
{
int wdir, a, b;
do
{
cout << "Enter the wind direction in degrees." << endl << endl;
cin >> wdir;
if(wdir >= 0 && wdir <=360)
break;
else cout << "Unacceptable value. Try again." << endl;
} while (1); // the need to make while true when the value is unacceptable.
a=23, b=67;
for (int i=1; i<9; i++) // for the case number
{
if (wdir >= a && wdir <=b) // determines which case.
{ switch (i)
{
case 1: cout << "Wind direction is NE" << endl;
break;
case 2: cout << "Wind direction is E" << endl;
break;
case 3: cout << "Wind direction is SE" << endl;
break;
case 4: cout << "Wind direction is S" << endl;
break;
case 5: cout << "Wind direction is SW" << endl;
break;
case 6: cout << "Wind direction is W" << endl;
break;
case 7: cout << "Wind direction is NW" << endl;
break;
case 8: cout << "Wind direction is N" << endl;
break;
}
}
cout << "i = " << i << endl <<endl;
if (wdir >= a && wdir <=b) // to break out of the for loop immediately when the switch is satisfied
{ break;
}
a=a+45;
b=b+45;
}
if
(wdir >= 0 && wdir <= 22)
{
cout << "Wind direction is for 0-22 deg N" << endl;
}
//this program results in an infinite loop if wdir is a large number. this should not be since
// the useable range is limited. Answer is don’t enter a value > 16 bits / 2 for signed variables. Looking to idiot proof this.
#include <iostream>
#include <limits>
usingnamespace std;
int main()
{
int wdir = 16, a, b;
do
{
cout << "Enter the wind direction in degrees." << endl << endl;
if (cin >> wdir)
{
if(wdir >= 0 && wdir <=360)
break;
else cout << "Unacceptable value. Try again." << endl;
}
cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while (1); // the need to make while true when the value is unacceptable.
cout << "wdir = " << wdir << endl;
a=23, b=67;
for (int i=1; i<9; i++) // for the case number
{
if (wdir >= a && wdir <=b) // determines which case.
{ switch (i)
{
case 1: cout << "Wind direction is NE" << endl;
break;
case 2: cout << "Wind direction is E" << endl;
break;
case 3: cout << "Wind direction is SE" << endl;
break;
case 4: cout << "Wind direction is S" << endl;
break;
case 5: cout << "Wind direction is SW" << endl;
break;
case 6: cout << "Wind direction is W" << endl;
break;
case 7: cout << "Wind direction is NW" << endl;
break;
case 8: cout << "Wind direction is N" << endl;
break;
}
}
cout << "i = " << i << endl <<endl;
if (wdir >= a && wdir <=b) // to break out of the for loop immediately when the switch is satisfied
{ break; }
a=a+45;
b=b+45;
}
if (wdir >= 0 && wdir <= 22)
{
cout << "Wind direction is for 0-22 deg N" << endl;
}
}
I'll give your suggestion a try but it does not answer my question from the 7:59 a.m. post this morning which stated:
"The type declared was int which accounts for + and - numbers in memory. When I divided the 32 bit number by 2 and entered that number the result crashed, BUT when I reduced that number by one it ran correctly so I exceeded a memory limit."
You say it isn't memory exceedance but I see otherwise. My program successfully executes when within the memory limits. Until someone can explain why the program displayed in the 2:58 p.m. post runs successfully for positive numbers < 2^16 and crashes for positive numbers >= 2^16 then this post remains an open item.
It does not crash. It repeats over and over. That's very different.
It does that because there is junk left in the input line. As much of the input line is read into the int as is sensible. If you put something in the input line that is not sensible, this leaves junk on the input line. This is not cleared away unless you actively do so.
suggestion and it works. I noticed the ignore and in parenthesis' numeric limits so this is an override functionality of the numeric limits? Is that correct? If so, then I interpret the results both mine as yours as follows:
Mine crashed due to system defined limits. Yours worked due to overriding those limits.
If the intent is to avoid a crash, then I interpret these results being all programs need the cin.ignore function along with appropriate cout statements alerting of error inputs.
Unless this is incorrect, I consider my question closed.
Thanks for the new code. I'll keep an eye out for it.
Mine crashed due to system defined limits. Yours worked due to overriding those limits.
No, that is a very wrong interpretation. The program did NOT crash. It did NOT crash. It repeated endlessly because there was junk left in the input line, which was then read and NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed...
The code I added clears the input of the junk. That's it.
2^16 is out of the range of your variable.
Then the reading fails. That puts cin in an invalid state, and all subsequent readings fail too.
As you didn't initialize 'wdir' the condition is not meet, never.
The same would happen if you don't input an number. (by instance you write 'north')
cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); is to recover the stream.
How do developers prevent a crash like this? (...). A user could enter a crazy number with undesirable results. Isn't it the job of the developer to account for all scenarios and prevent it?
I like GIGO.
You can catch the error (by instance checking the state of cin), how you treat it is not obvious.
I tried your suggestion but you are incorrect that "all subsequent readings fail too."
You are correct in that entering north caused a crash. Numbers >= 2^16 require a cin.clear() for a successful run.
Any numerics within the defined memory range produces good results immediately after a crash WITHOUT the use of cin.clear(). So, why does this invalid state NOT affect numerics within limits?
Why is the initialization of wdir important when it will be input a value?
Any numerics within the defined memory range produces good results immediately after a crash WITHOUT the use of cin.clear(). So, why does this invalid state NOT affect numerics within limits?
I want to know how did you test that.
And as Moschops pointed out, it is not a crash.
A crash terminates your program. So saying 'produces good results after a crash' doesn't make sense.
Why is the initialization of wdir important when it will be input a value?
It is not. I worded it badly if(wdir >= 0 && wdir <=360) break; will cut the loop. As the reading failed 'wdir' remainds with garbage.
If that garbage value satisfies the condition, you wouldn't have an infinite loop.
Incorrect choice of words. The problem is an infinite loop. I tested the following results without cin.clear(). If an infinite loop I abort, then recompile with a value within limits and the results are fine.
Puzzled by your last sentence. Garbage value yielding normal loop operation?
The solution seems to be the use of cin.clear() before every cin statement? I have not seen this presented in any of the material I am studying but if it is a good practice to do so then I will.