-
Tri-Nested for loop
I can't get this to work right. I have been workiing on it for a long time now but to no avail. It is a 3 section nested loop (if there is such a thing). It is supposed to print out a graph for each score but when it runs it just prints out
*
*
*
*
*
and I don't know what it prints out before that because it moves so fast and then it ends.
Am I doing something wrong?
Code:
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(13)<< "GRAPH"<< endl;
// Score output loop
for (int score=1; score < 10001; score++){
for (;(frequency[score]>1) && (frequency[score]< 10001);)
cout<< setw(5) << score << setw(5) << frequency[score] << setw(5);
// Print bar
for (int i=1; i <= frequency[i]; i++)
cout <<"*";
cout << endl;
}
I did have
if (!(frequency[i]==0)) cout << "*";
cout << endl;
after
cout<< setw(5) << score << setw(5) << frequency[score] << setw(5);
instead of the 2nd for loop.
But the problem was that if reads any other statements as else. But I wanted it to go back up to for to increment the number again.
One of my biggest goals is to stop it from printing 0's.
-
This one does the same thing. I used break and continue before instead of goto but they didn't work either.
Code:
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(13)<< "GRAPH"<< endl;
// Score output loop
for (int score=1; score < 10001; score++){
if (frequency[score]>0)
cout<< setw(5) << score << setw(5) << frequency[score] << setw(5);
else goto graph;
// Print graph
graph:
for (int i=1; i <= frequency[i]; i++){
if (frequency[i]==0) goto graph;
else cout <<"*"; goto graph;
}
cout << endl;
}
-
for (;(frequency[score]>1) && (frequency[score]< 10001);)
This is an endless loop.
-
Here is what I came up with. It has one minor problem. It does not put the space between the numbers and the graph.
This line: cout<< setw(5) << i << setw(10) << frequency[i] << setw(9);
All of it works except the last setw.
And I could not figure out a way to not use goto.
Code:
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int d; // Score entering finish letter
int main(int argc, char *argv[])
{
int score[1000001] ={0}; // initialize all memory locations to 0.
int frequency[1000001] ={0};
cout << "\nEnter scores (Limit: 1000000):\n" << endl;
// Score entering loop
for (int i=0; i< 1000001; i++){
cout << "Enter d when finished. Next score: "; cin >> score[i];
if (score[i]==d || !(score[i]<1000001)) break;
}
// Score counting loop
for (int i=0; i< 1000001; i++)
++frequency [score[i]]; // This is the key to it all!!!
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(14)<< "GRAPH"<< endl;
// Score output loop
for (int i=1; i < 1000001; i++){
if (frequency[i]>0)
cout<< setw(5) << i << setw(10) << frequency[i] << setw(9);
else goto graph;
// Print graph
graph:
for(int j=0; j< frequency[i];j++){
if (!(frequency[i]==0)) cout << '*';
else continue;
}
if (frequency[i]==0) continue;
cout << endl;
}
system("PAUSE");
return 0;
}
-
You can always avoid using Goto.
In this case you can just put a break in the loop, put the code from the graph flag just outside the loop and you're done?
-
Ok. I will try it. Here is what I changed to space out the graph. It does not make sence to me why I had to do this but I am hoping you guys know a way out of it.
cout<< setw(5) << i << setw(10) << frequency[i]<< setw(6)<< "-";
-
It always breaks out of the big loop and not the small one.
Code:
for (int i=1; i < 1000001; i++){{
if (frequency[i]>0)
cout<< setw(5) << i << setw(10) << frequency[i]<< setw(6)<< "-";
else break;
// Print graph
}
for(int j=0; j< frequency[i];j++){
if (!(frequency[i]==0)) cout << '*';
else continue;
}
if (frequency[i]==0) continue;
else {cout << endl; continue;
}}
-
I think you're confusing yourself. Insert newlines after EVERY statement.
You can make if-conditions execute more than one statements by defining a block:
Code:
if(condition)
{
statement;
statement;
}
else
{
statement;
statement;
}
And the indentation is still inconsistent. It would be easier for you if the code was properly formatted.
-
Shouldn't else break break out of the first loop and the continues at the bottom go back to the top of the first for loop?
Code:
// Score output loop
for (int i=1; i < 1000001; i++){
{
if (frequency[i]>0)
cout<< setw(5) << i << setw(10) << frequency[i]<< setw(6)<< "-";
else break;
// Print graph
}
for(int j=0; j< frequency[i];j++)
{
if (!(frequency[i]==0)) cout << '*';
else continue;
}
if (frequency[i]==0) continue;
else {cout << endl; continue;}
}
This never prints anything but the single digit lines for some reason.
-
You have one redundant and irritating pair of braces.
-
Hmm some of the else's aren't necessary here:
PHP Code:
// Score output loop
for (int i=1; i < 1000001; i++){
{
if (frequency[i]>0)
cout<< setw(5) << i << setw(10) << frequency[i]<< setw(6)<< "-";
else break;
// Print graph
}
for(int j=0; j< frequency[i];j++)
{
if (!(frequency[i]==0)) cout << '*';
// else continue; --- Not needed, it will continue by itself
}
/*
if (frequency[i]==0) continue;
else {cout << endl; continue;}
This block above can be replaced by:
*/
if (frequency[i]) cout << endl;
}
-
I don't think you are seeing the whole picture. Run this program:
Code:
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
char d; // Score entering finish letter
int main(int argc, char *argv[])
{
int score[1000001] ={0}; // initialize all memory locations to 0.
int frequency[1000001] ={0};
cout << "\nEnter scores (Limit: 1000000):\n" << endl;
// Score entering loop
for (int i=0; i< 1000001; i++){
cout << "Enter d when finished. Next score: "; cin >> score[i];
if (score[i]==d ||!(score[i]<1000001)) break;
}
// Score counting loop
for (int i=0; i< 1000001; i++)
++frequency [score[i]]; // This is the key to it all!!!
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(8)<< "GRAPH"<< endl;
// Score output loop
for (int i=1; i < 1000001; i++){{
if (frequency[i]>0)
cout<< setw(7) << i << setw(8) << frequency[i]<< setw(6)<< " ";
else break;
// Print graph
}
for(int j=0; j< frequency[i];j++){
if (!(frequency[i]==0)) cout << '*';
}
if (frequency[i]==0) continue;
cout << endl;
}
system("PAUSE");
return 0;
}
Now run this one:
The 1st one breaks when it encounters a 0 and breaks out of the entire nested loop. Is there any way to make it break out of only the loop it is in and work just like the bottom one here?
Code:
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
char d; // Score entering finish letter
int main(int argc, char *argv[])
{
int score[1000001] ={0}; // initialize all memory locations to 0.
int frequency[1000001] ={0};
cout << "\nEnter scores (Limit: 1000000):\n" << endl;
// Score entering loop
for (int i=0; i< 1000001; i++){
cout << "Enter d when finished. Next score: "; cin >> score[i];
if (score[i]==d ||!(score[i]<1000001)) break;
}
// Score counting loop
for (int i=0; i< 1000001; i++)
++frequency [score[i]]; // This is the key to it all!!!
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(8)<< "GRAPH"<< endl;
// Score output loop
for (int i=1; i < 1000001; i++){
if (frequency[i]>0)
cout<< setw(7) << i << setw(8) << frequency[i]<< setw(6)<< " ";
else goto graph;
// Print graph
graph:
for(int j=0; j< frequency[i];j++){
if (!(frequency[i]==0)) cout << '*';
}
if (frequency[i]==0) continue;
cout << endl;
}
system("PAUSE");
return 0;
}
-
Both source codes crash when compiled with VC++ in debug mode.
-
I missed the end brace on the second one. I will fix it. Ok, now try.
-
I fixed that myself. I'm not that dumb.
No, they compile ok but crash when running. I even know why. I'll tell you in a second.
But first, where is the difference between the two?
The only difference I see is
Code:
else goto graph;
// Print graph
graph:
which does exactly NOTHING.
Ok, now for the crash. Your arrays are each ~1 million elements large, each consisting of 4 bytes. This means you're allocating 8 MB on the stack. Windows imposes a limit of 1 MB on the stack, applications that do not heed this crash.
Here's working and properly formatted code that does what you want. You can compare it to yours and figure out what you've done wrong.
Oh, btw, I cleaned up both of your codes, removing redundant code and such. The outcome is the same, letter by letter.
Code:
#include <iostream>
#include <iomanip>
using namespace std;
// Those may not be inside main as the two arrays together need 8MB of stack space!
// But windows systems don't allow apps to allocate more than 1MB on the stack.
int score[1000000] ={0}; // initialize all memory locations to 0.
int frequency[1000001] ={0};
int main(int argc, char *argv[])
{
int temp, entered=0;
cout << "Enter scores (Limit: 1000000):" << endl;
// Score entering loop
for (int i=0; i < 1000000; i++) {
cout << "Enter -1 when finished. Next score: ";
cin >> temp;
while(temp > 1000000) {
cout << "Score out of range. Enter again: ";
cin >> temp;
}
if (temp < 0)
break;
score[i] = temp;
entered++;
}
// Score counting loop
for (int i=0; i < entered; i++)
++frequency[score[i]]; // This is the key to it all!!!
cout << "SCORE" << setw(13) << "FREQUENCY" << setw(8)<< "GRAPH"<< endl;
// Score output loop
for (int i=0; i < 1000001; i++) {
if (frequency[i]>0) {
cout<< setw(7) << i << setw(8) << frequency[i]<< setw(6)<< " ";
// Print graph
for(int j=0; j < frequency[i]; j++) {
cout << '*';
}
cout << endl;
}
}
system("PAUSE");
return 0;
}
-
Putting those outside main makes the program a lot slower but that is ok if it is the right way to do it.
Why does it slow down like that?
(and just to let you know, with the dev c++ compiler I needed #include <cstdlib> to compile. The error was with the system("PAUSE");)
I just noticed the the program is now 7 megabites instead of 70 kilobites. That is a problem!!! Can it be fixed?
-
I had none of those problems. The app is just as fast and only 470 k in debug compile. gcc doesn't seem to be very efficient there.
Right, forgot about the system call. It seems that somewhere deep inside the iostream header of VC++ includes cstdlib.
The problem is that the large arrays are now written to disk and therefore have to be loaded from there. It's probably faster if you do:
Code:
int score[1000000];
int frequency[1000001];
int main(int, char**)
{
memset(score, 0, 1000000*sizeof(int));
memset(frequency, 0, 1000001*sizeof(int));
//...
}
I think memset is declared in cstdlib.
-
Must not be in cstdlib because it gives erros about memset.
-