CLS hitting on performance - c++

This code prints the desired no(4 here) of perfect numbers. It's an old code of mine and checks up every number whether it's perfect or not. It runs normally and finishes in 6-ish seconds, but if I put a cls before checking every number it takes a big hit(about 100 secs). Please tell me the theory behind it(why multiple cls takes a hit on performance).
No normie answers like "Dude obviously it takes a hit, it's refreshing the screen every time."
PS- I know the better way is not to check perfect numbers but to generate them.(By Euclid-Euler theorem)
IDE- DevC++
#include <iostream>
#include <string>
using namespace std;
int choice, quan, i, a[50], number;
string schoice;
void startgame()
{
choice = 3;
quan = 4;
system("cls");
cout << "Hey guys, today we are gonna print different types of numbers\n";
cout << "\nFollowing are some of the special numbers found in the known observable little universe of ours:- \n";
cout << "\n1. Prime numbers\n2. Square numbers\n3. Perfect Numbers\n\n";
cout << "Which ones do you wanna see?\n";
//cin >> choice;
cout << "\nCool! How many of them do you wanna see?\n";
//cin >> quan;
}
void perfect()
{
if (choice == 3)
{
int j = 0, y = 0, f = 0, number = 2;
do
{
//This is the cls in question
//system("cls");
cout << "The number under inspection: " << number << "\n";
f = 0;
for (i = (number - 1); i >= 1; i--)
{
if (number % i == 0)
{
f = f + i;
}
}
if (f == number)
{
//cout<<number<<", ";
a[j] = number;
j = j + 1;
y = y + 1;
}
number++;
}
while (y < quan);
system("cls");
cout << "\nHere are your " << quan << " perfect numbers starting from 1:-\n";
j = 1;
for (i = 0; i < quan; i++)
{
cout << a[i];
if (j != quan)
{
cout << ", ";
}
j++;
}
}
}
int main()
{
do
{
startgame();
perfect();
cout << "\n\nReturn to Main menu?(Y/N)\n";
schoice = "N";
//cin >> schoice;
}
while (schoice == "Y");
return 0;
}

When you run system("cls"), you create a new process, and you do that every time you pick a new number for inspection.
Creating a process is an expensive operation, and more importantly you don't need it, if all you want is to update current number on screen.
It is sufficient to write
cout << "The number under inspection: " << number << "\r";
cout.flush();
The first line will output text and return cursor to the beginning of the same line.
The second line will make sure all the above does show up on the display.
Note: this is also slow operation, so you would probably want to rate limit it.
I suggest you output this for every 1 number in 1000 or so.

Windows CreateProcess() is quite expensive, much more expensive than Unix fork(). Moreover, system("cls") is an inefficient, non-portable hack. You can't use it in non-windows systems. You can use ncurses library that supports console manipulation.
For Windows, via Console API:
void clear() {
COORD topLeft = { 0, 0 };
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO screen;
DWORD written;
GetConsoleScreenBufferInfo(console, &screen);
FillConsoleOutputCharacterA(
console, ' ', screen.dwSize.X * screen.dwSize.Y, topLeft, &written
);
FillConsoleOutputAttribute(
console, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
screen.dwSize.X * screen.dwSize.Y, topLeft, &written
);
SetConsoleCursorPosition(console, topLeft);
}

Related

Parallel Arrays in C++

Trying to create a program that takes a coffee flavor add-in and checks if it's valid using an array.
If valid it uses the array index to gather price information.
I managed to write the code below, but it only works for 1 iteration.
How can alter it so a user can enter: Cream and cinnamon and output the total of each add-in as well as the total price of the cup of coffee? The cup of coffee starts with a base price of $2.00
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Declare variables.
string addIn; // Add-in ordered
const int NUM_ITEMS = 5; // Named constant
// Initialized array of add-ins
string addIns[] = { "Cream", "Cinnamon", "Chocolate", "Amaretto", "Whiskey" };
// Initialized array of add-in prices
double addInPrices[] = { .89, .25, .59, 1.50, 1.75 };
bool foundIt = false; // Flag variable
int x; // Loop control variable
double orderTotal = 2.00; // All orders start with a 2.00 charge
string QUIT = "XXX";
// Get user input
cout << "Enter coffee add-in or XXX to quit: ";
cin >> addIn;
// Write the rest of the program here.
for (x = 0; x < NUM_ITEMS && foundIt == false && addIn != QUIT; x++) {
if (addIn == addIns[x]) {
foundIt = true;
x--;
}
}
if (foundIt == true) {
cout << addIns[x] << " $" << addInPrices[x] <<endl;
cout << "$" << orderTotal + addInPrices[x] <<endl;
}
else {
cout << "Sorry, we do not carry that." <<endl;
cout << "Order total is $ " << orderTotal <<endl;
}
return 0;
}
Don't use parallel arrays - you will mess up maintaining them.
Better options:
Create a struct for your add-ins:
struct Addin {
std::string name;
double price;
}
and use an array (or better yet an std::vector) of those structs.
Another option is to use a map:
std::map<std::string, double> addIns = {
{"Cream", .89},
{"Cinnamon", .25},
// etc.
};
Then you won't need a loop, just a lookup
auto item = addIns.find(addIn);
if(item != addIns.end() {
// do your math here
}
Your program is written to get a single output. For multiple outputs there have to be loops and the not found condition also has to be re-written.
try this
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Declare variables.
const int NUM_ITEMS = 5; // Named constant
string addIn[NUM_ITEMS]; // Add-in ordered
// Initialized array of add-ins
string addIns[] = { "Cream", "Cinnamon", "Chocolate", "Amaretto", "Whiskey" };
// Initialized array of add-in prices
double addInPrices[] = { .89, .25, .59, 1.50, 1.75 };
//bool foundIt = false; // Flag variable
int x, i, j; // Loop control variable
double orderTotal = 2.00; // All orders start with a 2.00 charge
string QUIT = "XXX";
// Get user input
cout << "Enter coffee add-ins followed by XXX to quit: ";
for(i=0; i<NUM_ITEMS; i++) {
cin >> addIn[i];
if(addIn[i] == QUIT) {
i++;
break;
}
}
int foundIt[i];
// Write the rest of the program here.
for(j=0; j<i; j++) {
foundIt[j] = -1;
for(x = 0; x<NUM_ITEMS && foundIt[j] == -1 && addIn[j] != QUIT; x++) {
if (addIn[j] == addIns[x]) {
foundIt[j] = x;
}
}
}
for(j=0; j<i-1; j++) {
cout << addIn[j];
if(foundIt[j] != -1) {
cout << " $" << addInPrices[foundIt[j]] << endl;
orderTotal = orderTotal + addInPrices[foundIt[j]];
}
else {
cout << " - Sorry, we do not carry that." <<endl;
}
}
cout << "$" << orderTotal <<endl;
return 0;
}
Sample Outputs
Enter coffee add-ins followed by XXX to quit: Cream Cinnamon XXX
Cream $0.89
Cinnamon $0.25
$3.14
Enter coffee add-ins followed by XXX to quit: Cream Onion XXX
Cream $0.89
Onion - Sorry, we do not carry that.
$2.89
What I did was made addIn array of srings with NUM_ITEMS size instead of variable. Also, foundIt was made an integer array to keep track of indexes where the items are found in addIns array and -1 if not found.
To only access the items that user has entered in addIn, your QUIT has been made the termination condition in that array.
The structure you are looking for is a while or do/while loop.
To be able to enter "empty" lines use std::getline from.
The structure of your program will then look something like this :
As you can see I have a habit of changing my boolean expressions into functions (predicates). This makes code more readable and predicates reusable in other bits of code.
#include <iostream>
#include <string>
bool is_quit(const std::string& input)
{
return input.length() > 0;
}
bool is_valid_input(const std::string& input)
{
return true; // your own check
}
int main()
{
bool quit = false;
std::string input;
do
{
std::cout << "give input : ";
std::getline(std::cin, input);
quit = is_quit(input);
if (is_valid_input(input) && !quit)
{
std::cout << "ok" << std::endl;
}
} while (!quit);
return 0;
}

The Print statements don't show up in the C++ game

So I am trying to code a game using C++. I am using this online compiler so I can also work on it at school. This program was just a simple clicker game that I starting making. When I tested it to see if the code worked so far, nothing showed up, which is strange considering I have print statements in the code that give the directions for the player.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int SCORE = 0;
int LEVEL = 1;
int COST = 50;
int ADDSCORE = 10;
char KEYINPUT;
bool GAMEON = true;
printf("Press space bar to gain points to your score.\n");
printf("Press z key to upgrade your score multiplyer.\n");
printf("Press the escape key (esc) to quit.\n");
printf("Upgrade score multiplyer = %d.\n", COST);
printf("Score multiplyer = LV%d.\n", LEVEL);
printf("Score = %d.\n", SCORE);
while (GAMEON == true) {
if (KEYINPUT == 32) {
SCORE += ADDSCORE;
}
if (KEYINPUT == 122) {
ADDSCORE += 10;
SCORE -= COST;
COST *= 2;
LEVEL += 1;
}
if (KEYINPUT == 27) {
GAMEON = false;
}
}
printf("Game has ended. You may now close out of the game");
return 0;
}
I am not sure if it is my code or if it is the online compiler, but I executed on a different compiler and got the same result. Nothing. Not exactly sure why this is happening, but if someone can spot what is wrong can you let me know.
I tried a bit around and on my system with a local compiler the text also does not print. Now in the first place if you want to code in C++ you need to use C++. printf is actually a C function. You are not using any C++ specific code in your example. If you want to use C in your C++ application though, use the C++ equivalents of the C libraries which wourld be <cstdio> in your case. Now to the problem itself: i am using MSYS shell on windows and i assume you use something similar. There seems to be a problem with the output buffer when you use printf. Normally the output buffer is flushed with the \n newline character at the end of the input. Apparently this does not seem to work in some cases. Adding an fflush(stdout) at the end of the output worked in my case and the text was printed from the buffer and also calling it directly from windows command line, without flushing the buffer, did the trick. So i think it is a problem how your shell handles the buffers. Now to the solutions. Either you flush the output buffer everytime you want to print or you start to use C++ IO. Also as mentioned you need to initialize and change the value from KEYINPUT while your program is running.
#include <iostream>
using namespace std;
int main()
{
int SCORE = 0;
int LEVEL = 1;
int COST = 50;
int ADDSCORE = 10;
char KEYINPUT;
bool GAMEON = true;
/* Use cout instead of printf for output operations */
cout << "Press space bar to gain points to your score." << endl
<< "Press z key to upgrade your score multiplyer." << endl
<< "Press the escape key (esc) to quit" << endl
<< "Upgrade score multiplyer = " << COST << endl
<< "Score multiplyer = LV" << LEVEL << endl
<< "Score = " << SCORE << endl;
while (GAMEON == true) {
KEYINPUT = cin.get(); /* You need to initialize the value before using and change it in the loop */
if (KEYINPUT == 32) {
SCORE += ADDSCORE;
}
if (KEYINPUT == 122) {
ADDSCORE += 10;
SCORE -= COST;
COST *= 2;
LEVEL += 1;
}
if (KEYINPUT == 27) {
GAMEON = false;
}
}
cout << "Game has ended. You may now close out of the game" << endl;
return 0;
}
A little note at the end: Since i tried to do similar little games as i started, you will need to use a platform dependent library to capture those keystrokes like ESC or other keys which not directly get put into the input buffer. i know conio for windows and otherwise the winapi is well documented and relatively easy to use. There are also many examples of how to use the winapi to capture keystrokes from the command line window which can easily be found on google.

How do I make a real-time updating grid in c++

So I'm making a sudoku solver to kind of test myself, and I have seem to hit a wall.
I'm trying to get the user to input values into a grid, and it'll automatically update every couple of seconds to see the next value they put in the grid.
I don't know how to get the user input into the grid itself.
Here is my code for the grid itself.
void draw()
{
int given;
cout << endl;
for (int i = 0; i < 13; i++)
{
for (int j = 0; j <= 9; j++)
{
if (j == 0)
{
cout << "|";
}
if (j == 3 || j == 6 || j == 9 )
{
cout << "|";
}
if (i == 0 || i == 4 || i == 8 || i == 12)
{
cout << "#";
}
else
{
cout << " ";
}
}
cout << endl;
}
}
To get this to refresh, I have this loop.
while (gameOver != TRUE)
{
system("cls");
draw();
cout << "\nEnter the next given number, or 0 for a blank space: ";
Sleep(600);
}
So I need help getting the user input value to both
Display on the grid
Save in any way (I think an array might work best?)
Thanks.
I personally think that the easiest way to visualize (and store) the values would be in a two-dimensional array.
You can declare and n * m array like this :
int x[n][m];
Then access elements (i,j) like this in your for loop to display it :
x[i][j]
By this line I guess you're programming on Windows:
system("cls");
So my answer will be based on that and utilize a lot of WinAPI.
Normally, you can stick to cin and update the grid after user presses Enter. But since you want a real-time display refresh, this doesn't seem optimal. You have conio.h on Windows so go for it:
#include <conio.h>
...
char ch;
while (true) {
while (!kbhit()); // Wait for user input
ch = getch();
switch (ch) {
// Process input here.
}
}

Why are my if statements not working consistently?

I'm making a coin toss program for my c++ class and we are required to make a function that flips a coin and prints out if it is heads or tails, and print 10 per line. When I ran the program though the if statements I used to detect if the coin was heads or tails weren't enough to pick from the two.
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main()
{
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times)
{
int toss = 0, count = 0;
for(int i = 0; i < times;i++)
{
toss = rand()%2;
if(toss == 1)//Detects if coin is heads.
{
cout << "H";
}
if(toss == 0)//Detects if coin is tails.
{
cout << "T";
}
else //I had to include this for the program to run, further explanation below the code.
{
cout << "Ya done goofed.";
}
count++; //Counts to ten
if(count == 10) //Skips to the next line if the coin has been tossed ten times.
{
cout << endl;
count = 0;
}
}
}
At one point I replaced the heads or tails with "cout << toss;" and the only numbers returned were 1 and 0. I don't understand how if I'm getting only the two numbers I'm checking for some of them aren't being caught by my if statements.
To complete the assignment I've changed the second if statement into an else statement and everything seems peachy, but I'd really like to understand what's going on here.
What happens with your code is:
Is the result 1 ? Then print H. Keep going. Is the result 0 ? Then print T. Else, if it's not 0, print "Ya done goofed.".
You need to keep your if statements linked together:
if (toss == 1) {
cout << "H";
} else if (toss == 0) {
cout << "T";
} else {
cout << "Ya done goofed.";
}
You won't fall in the else case anymore and will be able to remove it.
As a sidenote, regarding your overall program structure: your coinToss function shouldn't do everything. Your code should be more splitted: a function which returns H or T, a function which calls this function X times as requested by the user and formatting the output would be a good start.
Another small note: your count variable, allowing you to add a new line every 10 flips, could be removed. i % 10 will give you the same result: every ten increments, i % 10 would be equal to 0.
You're probably printing the output properly, then terminating without writing a newline on the last line, and your shell prompts clearing back to the left margin and overwriting your output (clearing the rest of the line to boot). If you have less than 10 tosses, your only line of output may appear lost, otherwise it'll be the last line.
Try adding an extra std::cout << '\n'; before main returns.
(Separately, you can say std::cout << "HT"[rand() % 2];, or std::cout << (rand() % 2 ? 'H' : 'T'); and do away with the ifs, but it's no big deal... whatever's clearest for you at this stage)
Well, rand()%2 will produce only two numbers: 1 and 0, this seems to be in line with your task as a coin is a boolean number generator, isn't it? :)
Therefore this seems to do the job you are looking for:
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main()
{
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times)
{
int toss = 0, Count = 0;
for(int i = 0; i < times;i++)
{
toss = rand() % 2;
// Choose:
cout << ((toss) ? "H" : "T"); // if you want a character
// or
cout << toss; // if you want the number
Count++; //Counts to ten
if(Count == 10) //Skips to the next line if the coin has been tossed ten times.
{
cout << endl;
Count = 0;
}
}
}
if(toss == 1)//Detects if coin is heads.
{
cout << "H";
}
else if(toss == 0)//Detects if coin is tails.
{
cout << "T";
}
You need to use else-if statement. You also need not use else after the toss==0 because rand()%2 will either be 0 or 1. There is no third option.
rand() returns a pseudo-random integral number in the range between 0 and RAND_MAX. And, rand() % 2 will be 0 or 1. So, there would be:
if(toss == 1)//Detects if head
{
cout << "H";
}
else // tail
{
cout << "T";
}
I don't think there is anything wrong with this. Well not that I can see... If I add some debug then I see what I think you're expecting...
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main() {
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times) {
int toss = 0, count = 0;
for(int i = 0; i < times;i++) {
toss = rand() % 2;
cout << "Toss: " << toss << endl;
if(toss == 1)//Detects if coin is heads.
{
cout << "H (" << toss << ")" << endl;
}
if(toss == 0)//Detects if coin is tails.
{
cout << "T (" << toss << ")" << endl;
}
count++; //Counts to ten
if(count == 10) //Skips to the next line if the coin has been tossed ten times.
{
//cout << endl; count = 0;
}
}
}
And compile it
g++ coin_toss.cc
And run it
./a.out
How many times would you like to toss the coin?
4
Toss: 1
H (1)
Toss: 0
T (0)
Toss: 0
T (0)
Toss: 0
T (0)
Then this is exactly what I expect or am I missing something?
You don't need an "if else if" statement.
You can also use a switch:
switch( rand() % 2 )
{
case 0:
cout << "T";
break;
case 1:
cout << "H";
break;
default:
cout << "oops you goofed!;
}
// continue within for loop
If you "forgot" the break after case 1 you would again get the "oops you goofed!" message after each head toss.

I'm getting a weird error for a program that seems like it should "just work."

I present to you all a program I'm working on for my college programming course. I still have a little ways to go before it completely meets my assignment's requirements, but I've gotten a basic draft of the program error-free (supposedly) and it appears to run… but then it suddenly kicks me into Xcode's debugger and gives me:
Thread 1: EXC_BAD_ACCESS(code=2, address=0x7fff95c1e5f5)
Here's the command line output, up until it kicks me out:
-----------------------
Quarterly_sales_taxator
-----------------------
How many company divisions will we be dealing with? 2
Am I correct in assuming that there are 4 sales quarters? yes
Please enter the sales Company Division #1 brought in for Sales Quarter #1 20
(lldb)
Here's my code:
//
// quarterly_sales_taxator.cpp
// Ch. 7 program #7
//
// Created by John Doe on 11/27/12.
//
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cctype>
using namespace std;
void read_company_divisions_and_sales_quarters(double **, int, int);
//void write_company_divisions_and_sales_quarters_to_array(double **, int, int); // This will be used later on to read data from a file.
void display_quarterly_sales_array(double **, int, int);
string temp; // A global temporary placeholder variable; I use this several times.
int main()
{
int COMPANY_DIVISIONS,
SALES_QUARTERS = 4;
double **quarterly_sales_form;
cout << "\n\n-----------------------\nQuarterly_sales_taxator\n-----------------------\n\n";
cout << "\nHow many company divisions will we be dealing with? ";
getline(cin, temp);
stringstream(temp)>>COMPANY_DIVISIONS;
while (COMPANY_DIVISIONS < 1 || isdigit(COMPANY_DIVISIONS == false))
{
cout << "\n\n------"
<< "\nError:"
<< "\n------"
<< "\n\nYou have entered an invalid choice."
<< "\nPlease type a number greater than zero. ";
getline(cin, temp);
stringstream(temp)>>COMPANY_DIVISIONS;
}
cout << "\n\nAm I correct in assuming that there are 4 sales quarters? ";
getline(cin, temp);
// Convert to uppercase.
for (int count = 0; count < temp.length(); count ++)
{
temp[count] = toupper(temp[count]);
}
if (temp == "NO" || temp == "NOPE" || temp == "INCORRECT" || temp == "YOU ARE NOT" || temp == "YOU ARE INCORRECT" || temp == "NEGATIVE" || temp == "NEGATORY")
{
cout << "\nOk, then how many sales quarters are we dealing with? ";
getline(cin, temp);
stringstream(temp)>>SALES_QUARTERS;
}
cout << endl << endl;
// This sets up the 2d array.
quarterly_sales_form = new double *[COMPANY_DIVISIONS];
for (int count = 0; count < COMPANY_DIVISIONS; count ++)
{ quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS]; }
read_company_divisions_and_sales_quarters(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);
// write_company_divisions_and_sales_quarters_to_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS); // I'll add this feature later.
cout << "\n\nHere's what you entered:\n\n";
display_quarterly_sales_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);
// Since we used a series of pointers, we need to free the allocated space back up.
for (int count = 0; count < COMPANY_DIVISIONS; count ++)
{ delete[] quarterly_sales_form[COMPANY_DIVISIONS]; }
delete[] quarterly_sales_form;
return 0;
}
/*############################################
# read_company_divisions_and_sales_quarters #
############################################*/
void read_company_divisions_and_sales_quarters(double **array, int DIVISIONS, int QUARTERS)
{
for (int count = 0; count < QUARTERS; count++)
{
for (int index = 0; index < DIVISIONS; index++)
{
cout << "\nPlease enter the sales Company Division #" << count+1 << " brought in for Sales Quarter #" << index+1 << " ";
getline(cin, temp);
stringstream(temp) >> array[count][index];
}
}
}
/*################################
# display_quarterly_sales_array #
#################################*/
void display_quarterly_sales_array(double **array, int DIVISIONS, int QUARTERS)
{
for (int count = 0; count < DIVISIONS; count++)
{
cout << "\nCompany division #" << count+1 << ":\n";
for (int index = 0; index < QUARTERS; index++)
{ cout << array[count][index] << ", "; }
}
}
Can some kind soul please tell me what I'm doing wrong?
{ quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS]; }
In this line, COMPANY_DIVISIONS should be count.
In addition to what Dan Hulme said, it seems this line
stringstream(temp) >> array[count][index];
should really be
std::istringstream(temp) >> std::skipws >> array[index][count];
In addition to using std::istringstream rather than std::stringstream and making sure that an lvalue is at hand, which isn't strictly needed until the type read becomes more interesting, this also reverses the indices: index runs over COMPANY_DIVISIONS and count over SALES_QUARTERS.
The real question is, of course: Who hands out assignments like this? Pointer manipulations and allocations are best left to low-level library writers. This is C++ not C: we can and should use abstractions. Getting this code exception safe is a major challenge and there is no point in teaching people how to write broken (e.g. exception unsafe) code.