Do-while loop running twice when it should run only once (C++) - c++

friends. I have a problem.
Problem: the computer must pick randomly one string out of an array of 36 strings. If by any chance it picks strings #34 or #35 (the two last ones), it has to draw two more random strings from the same array. I tried a do-while solution, and it "almost" works (see code below).
The randomization works fine - called srand inside main(). There is a forced "x2" draw (for testing reasons), so the computer draws two more strings. These two new random picks are NOT "x2", but still the loop kicks again - but just one more time! This time the computer picks two more "chits", which aren't "x2" either, so, as expected, it returns the "The chits have been drawn" sentence and the function is terminated. Why is the same code running twice with the same results but different if/else behavior? Thank you very much in advance.
string mortalityCalc ()
{
string mortalityChits[36] = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","-","-","-","-","x2","x2"};
int mortalityResult;
// mortalityResult = rand() %36;
mortalityResult = 35; // for testing only. Delete afterwards.
string drawnChit = mortalityChits[mortalityResult];
string drawnChit1;
string drawnChit2;
if (drawnChit != "-" && drawnChit != "x2")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'.";
return returnText;
}
else if (drawnChit == "-")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'. No senators died this year.";
return returnText;
}
do
{
cout << "The computer has drawn the 'x2' chit." << endl;
cout << "Two more chits will be drawn.\n" << endl;
mortalityResult = rand() %36;
drawnChit1 = mortalityChits[mortalityResult];
cout << "The first draw is the chit '" << drawnChit1 << "'. ";
mortalityResult = rand() %36;
drawnChit2 = mortalityChits[mortalityResult];
cout << "The second draw is the chit '" << drawnChit2 << "'." << endl;
} while (drawnChit1 == "x2" || drawnChit2 == "x2");
return "The mortality chits have been drawn. The corresponding senators are dead.";
}
UPDATE: Tried running this code isolated from the rest of the program and it behave as expected. So I guess it's important to post what comes before it:
cout << "If you are a lazy bastard, the computer can pick one senator randomly for you.\nAre you a lazy bastard? [y/n]" << endl;
string lazyBastard;
cin >> lazyBastard;
cout << endl;
if (lazyBastard == "y" || lazyBastard == "Y" || lazyBastard == "yes" || lazyBastard == "YES" || lazyBastard == "Yes")
{
mortalityCalc ();
cout << mortalityCalc () << endl;
cout << "Very well. Now, imminent wars become active (Only one of each match)." << endl;
cout << "Get ready for the next phase." << endl;
My guess, from reading some other questions here, is that somehow the cin is messing with the loop behavior, even though they are not related and there's no user input whatsoever in the loop's statements or conditions. Is that possible? If so, why and how to remedy it?
Thank you again.

In the first loop you are forcing an 'x2' so your are entering the do-while loop. The result of the two calls for 'rand())%36' is always 19 and a number between 30 and 34. The point is that the random number generator generates always the same sequence of numbers, if you don't give him a seed 'srand(...)'.
do {
// ...
cout << rand()%36;
// ...
} while( /*...*/ )
See http://ideone.com/zl8ggH
You have to create random numbers and your code does what you expect.

Finally! I thought it would be a stupid thing! I just realized that I called the mortalityCalc() function twice! That's why it was looping twice!
Thanks to all who tried to help!

Related

My code and sometimes it says terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc. and then sometimes it doesnt

I can't figure out why my code works only half of the time and it seems completely random when it works this is my code for a hash simulator and when I put "bru" it puts out what I want it to put but if I want to put bruh it sometimes outputs nothing but it also sometimes puts this:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
I have no idea what is wrong with my code and it doesn't tell me because it doesn't count as an error.
p.s. I am 4 days old with c++ please be specific
Here is the code. :)
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string lor[] = {"a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9","j0","k10","l11","m12","n13","o14","p15","q16","r17","s18","t19","u20","v21","w22","x23","y24","z25"};
string password;
string passhash[10] = {"","","","","","","","","",""};
cout << "your password cant be more then 10 characters long!" << endl;
cout << "password:";
cin >> password;
bool white = true;
int justno = password.length();
justno++;
int just = -1;
int justtwo = 0;
if (password.length() >= 10){
cout << "Password too long!" << endl;
}
while (white){
just++;
if (password[justtwo] == letters[just]){
passhash[justtwo] = lor[just];
justno--;
justtwo++;
cout << justno << endl;
if (justno <= 0){
cout << "your hashed password: " << passhash[0] << passhash[1] << passhash[2] << passhash[3] << passhash[4] << passhash[5] << passhash[6] << passhash[7] << passhash[8] << passhash[9] << endl;
white = false;
}
}
}
cout << "lol";
return 0;
if (password[justtwo] == letters[just]){
There's absolutely nothing in the shown code that will enforce that, over here, just will always be less than letters.size(). just keeps getting incremented, without any apparent upper bound. Only some other tangentially related condition will stop this loop.
Therefore, at some point this expression become undefined behavior, and the shown code may or may not crash at this point.
P.S. The same thing appears to be true here, as well:
passhash[justtwo] = lor[just];
When accessing containers, of which std::strings are just a special kind, it is your responsibility to ensure that array indexes are valid, and within bounds.
P.P.S. The same thing is likely true for justtwo accesses as well, except that the logic is unclear, on that part. But if one enters a password that starts with a period, of example, this if condition will be false, so the loop will begin again, incrementing just. Still, if will be false and you are guaranteed undefined behavior, because the letters does not, obviously, contain a period, so it's guaranteed to run off the end of that array, and hillarity ensues. That much is pretty clear.

Issue Comparing strings for an Answer Key (C++)

I'm working on a midterm project for my coding class, and while I've gotten the majority of kinks worked out I'm struggling with comparing two string values and determining if they are equal or not. The strings in question are ANSWERKEYand studentAnswers. The former is a constant that the latter is compared to.
The code in question is as follows.
if (studentAnswers == ANSWERKEY)
{
percentScore = 100.0;
cout << "Score: " << percentScore << " % " << 'A' << endl;
}
else if (studentAnswers != ANSWERKEY)
{
int count = 0;
double answerCount = 0.0;
while (count < ANSWERKEY.length())
{
if (studentAnswers.substr(count, count+1) == ANSWERKEY.substr(count, count+1)
{
answerCount++;
count++;
}
else
{
cout << "Incorrect answer." << endl;
count++;
}
}
percentScore = ((answerCount) / (double)ANSWERKEY.length()) * 100.0;
cout << "Percent score is " << percentScore << "%" << endl;
}
The exact issue I'm facing is that I can't work out a better way to compare the strings. With the current method, the output is the following:
The intro to the code runs fine. Only when I get to checking the answers against the key, in this case "abcdefabcdefabcdefab", do I run into issues. Regardless of what characters are changed, the program marks roughly half of all characters as mismatching and drops the score down because of it.
I've thought of using a pair of arrays, but then I can't find a solution to setting up the array when some values of it are empty. If the student's answers are too short, e.g. only 15 characters long, I don't know how to compare the blank space, or even store it in the array.
Thank you for any help you can give.
First:
if (studentAnswers == ANSWERKEY)
{...}
else if (studentAnswers != ANSWERKEY)
{ ...}
looks like an overkill when comparing strings. And where is the else part ?
Second, this is risky. Read the IEE754 and articles about cancellation, or even SO:
double answerCount = 0.0;
...
answerCount++
Third:
You are checking character by character using substr. To me it feels like using a hammer to kill a bacteria.
studentAnswers.substr(count, count+1) == ANSWERKEY.substr(count, count+1)
Fourth:
What if studentAnswers is shorter than ANSWERKEY ?
Conclusion:
You need to clarify inputs/expected outputs and use the debugger to better understand what is happening during execution. Carefully check all your variables at each step fo your program.

2nd call of srand() in the same program with the same seed is NOT producing the same values for successive rand()

I'm working on a simple "addition questions" program for my intro to C++ class. My instructor uses a test driver to grade our code. The test driver first runs the program using his code, and then runs my function and compares the two.
In this code, we're supposed to generate random numbers to give the user simple addition problems. They enter the answer and the program keeps track of how many they got correct, and returns the number of correct answers to the main function.
As I understand it, srand() will generate the same list of numbers if the seed is the same. The problem I'm having is even though I put srand(seed) at the top of my function, the successive numbers generated by each rand() call are still different. As I understood it, if you recall srand with the same seed, it will reset the number generator and give you the same chain of numbers from rand().
Because he uses a test driver to grade, the driver is telling me almost all of my results are wrong, but it's because the driver does not actually calculate my random generated numbers, it just looks for the same answers as what he got in his version of the program. So the problem is for some reason calling srand(seed) is not using the same numbers.
This could be a problem with his driver, if it is sending a different number to my function for seed than he used, but it could also be that I put srand() in the wrong place, or I'm not using it correctly.
Can anyone confirm if the use of srand(seed) in my code would reset and use the same numbers given that seed value is the same?
Here's my function:
int correct = 0; // initialize global variable to return correct answers
// define the additionQuestions function.
int additionQuestions(int largest, int problemCount, int seed)
{
srand(seed); // initialize the random generator to the same seed used in test driver
int gen1, gen2, answer;
bool quitting = false;
// generate problems
for (int count = 0; count < problemCount && (!(quitting)); count++)
{
gen1 = rand() % largest;
gen2 = rand() % largest;
cout << "How much is " << gen1 << " plus " << gen2 << "? ";
cin >> answer;
if (answer == -1) // check for sentinel of -1
{
cout << endl << " You entered -1; exiting...";
quitting = true;
}
else // check if the user's answer is correct.
{
cout << endl << " You said " << gen1 << "+ " << gen2 << " = " << answer << ".";
if (answer == gen1 + gen2)
{
cout << " Very good!" << endl;
correct += 1;
}
else
{
cout << " No. Sorry, the correct answer is " << gen1 + gen2 << "." << endl;
}
}
} // end of for loop.
return correct; // return the number of correct answers to the main function
}
Before you write to your professor....
Your using implicit type casting from 'int seed' to 'srand(unsigned int seed)' which could cause issues when the test driver tries to test your program with a seed larger than ~2.1M.
Good luck.

C++ For Loop not Exiting

I have a for loop, a very simple one, in my program, and I want it to loop through and do something for some minimum number of times. However, the loop simply...stops. But does not move on to the next thing in the program. For instance, when min is 9, it runs for i=0 to i=8, then freezes. It should exit the for loop, but it does not execute the next print instruction, nor does it execute the loop again. It just stops. The program hangs, doing absolutely nothing as far as I can tell. I don't understand why this is.
The merged.put() function I want to execute just puts x or y in merged, depending on the condition. That part works. This is just a small part of a much larger program. sp1, sp2, and merged are all defined elsewhere.
int i;
int x;
int y;
for(i=0; i < min; i++)
{
cout << " here " + convert(i);
x = sp1.get_num(i);
y = sp2.get_num(i);
if(x >= y) {
merged.put(x);
}
else {
merged.put(y);
}
cout << " end" << endl;
}
cout << "out";
EDIT: I'm not posting the entire code, it's several hundred lines long. Type of min is int. The reply down there was helpful, when << endl was added to the last print statement, it printed. My problem now appears to be here, getting stuck on the second while, because I was not incrementing i. Shame on me...thanks for the help. (This comes directly after the above code)
if (sp_large == 2) {
cout << "1" << endl;;
while (i < sp2.get_size()) {
merged.put(sp2.get_num(i));
}
}
else {
while (i < sp1.get_size()) {
merged.put(sp1.get_num(i));
}
cout << "2" << endl;
}
EDIT: Problem solved, thanks for the help.
I'm betting that it's actually a later part of the program that is hanging.
This line:
cout << "out";
just puts "out" on the output-buffer, and won't actually print "out" until the output-buffer gets flushed. (Which could happen immediately, but is not likely to.) Change that line to this:
cout << "out" << endl;
and "out" will be printed as soon as that line is run. This will help you figure out if the program is hanging before it gets to that line, or somewhere later on.

Parse int and string

Hi I'm not sure if this is the right place to ask this question.
Anyway I have written this code to parse a molecule formula and split it into atoms and amount of each atoms.
For instance if I input "H2O" I will for the atom array get {"H", "O"} and in the amount array I will get {2, 1}. I haven't taken account for amount that is larger than 9, since I don't think there are molecule which can bind to something that is larger than 8.
Anyway I'm quite newbie, so I wonder if this piece of code can be made better?
string formula = "H2O";
int no, k = 0, a = 0;
string atom[10];
int amount[10];
bool flag = true;
stringstream ss(formula);
for(int i = 0; i < formula.size(); ++i)
{
no = atoi(&formula[i]);
if(no == 0 && (flag || islower(formula[i]) ) )
{
cout << "k = " << k << endl;
atom[k] += formula[i];
flag = false;
cout << "FOO1 " << atom[k] << endl;
amount[a] = 1;
}
else if(no != 0)
{
amount[a] = no;
cout << "FOO2 " << amount[a] << endl;
a++;
flag = true;
k++;
}
else
{
k++;
a++;
atom[k] = formula[i];
cout << "FOO3 " << atom[k] << endl;
amount[a] = 1;
flag = false;
}
cout << no << endl;
}
Have you considered an approach with regular expressions? Do you have access to Boost or TR1 regular expressions? An individual atom and its count can easily be represented as:
(after edits based on comments)
([A-Z][a-z]{0,2})([0-9]*)
Then you just need to repeatedly find this pattern in your input string and extract the different parts.
There are many potential improvements that could be made, of course. But as a newbie, I guess you only want the immediate ones. The first improvement is to change this from a program that has a hard coded formula to a program that reads a formula from the user. Then try testing yout program by inputting different formulae, and check that the output is correct.
What if you modified it to be like this algorithm? This would maybe be less code, but would definitely be more clear:
// while not at end of input
// gather an uppercase letter
// gather any lowercase letters
// gather any numbers
// set the element in your array
This could be implemented with 3 very simple loops inside of your main loop, and would make your intentions to future maintainers much more obvious.