I am in need of assistance to create an vertical bar graph with required limitations of learning experience. Such as, using only the fundamental basics listed: if statement, boolean, loop, string, arithmetic and comparison operators. Basically giving an idea of how limited my experience is in the language for clarification. Now, I have completed this problem already but the output does not seem to look like a desirable graph in my opinion so this is why posting. I will provide the problem and valid code I used to complete this problem.
Write a program that provides the option of tallying up the results of a poll with 3 possible
values. The first input to the program is the poll question; the next three inputs are the possible
answers. The first answer is indicated by 1, the second by 2, the third by 3. The answers are
tallied until a 0 is entered. The program should then show the results of the poll—try making a
bar graph that shows the results properly scaled to fit on your screen no matter how many
results were entered.
#include<iostream>
int main()
{
bool poll = false;
int Tech = 0, Edu = 0, Agri = 0;
std::cout << "VOTING POLL" << std::endl;
std::cout << "----------------------------" << std::endl;
std::cout << "----------------------------" << std::endl;
while(!poll)
{
std::cout << "Of the year 2022, in the United States of America, what should be the top priority of our concerns?" << std::endl;
std::cout << " 1.Technology\n 2.Education\n 3.Agriculture" << std::endl;
std::cout << "\n";
int pollAnswer;
std::cin >> pollAnswer;
if(pollAnswer == 1)
{
Tech++;
}
else if(pollAnswer == 2)
{
Edu++;
}
else if(pollAnswer == 3)
{
Agri++;
}
else if(pollAnswer == 0)
{
poll = true;
}
else
{
std::cout << "\n" << "Invalid. Please choose an answer from the above listing." << std::endl;
}
}
std::cout << "Technology: ";
while(Tech > 0)
{
std::cout << "* ";
Tech--;
}
std::cout << std::endl;
std::cout << "Education: ";
while(Edu > 0)
{
std::cout << "# ";
Edu--;
}
std::cout << std::endl;
std::cout << "Agriculture: ";
while(Agri > 0)
{
std::cout << "| ";
Agri--;
}
}
using only the fundamental basics listed: if statement, boolean, loop, string, arithmetic and comparison operators.
Those are enough to write a sort of scanline algorithm:
Establish a maximum height for the bars and scale all the (three) values accordingly. This isn't mentioned in your requirements, but it seems better to avoid too high (or too low) bars.
for each line of output (you may initialize a loop variable row at max_height and decrease it down to 0):
print some spaces, so that you can add the labels after this loop.
if the value of the first scaled variable (say, Tech) is less than or equal to row, print a ' ' (a space) otherwise print the character chosen to represent that bar ('*', I think).
repeat for all the other bars and then add a '\n' (newline) to end this row.
Print the labels, like "Technology" and the likes, correctly spaced.
I'll leave all the details of the implementation to the reader.
I think the first thing to do would be to make sure all the labels take up the same amount of space, so the bars in the graph all start from the same location on the left.
The text suggests scaling the graph to fit the screen. To do that we probably want to take the largest of the three counts, and figure out what to multiply that by so it'll be close to (but not greater than) the screen width (e.g., 80 columns), then multiply all three values by that scale factor.
I wouldn't use spaces in the bars, so each bar would look more "solid".
Possible result:
Technology: ****************************************
Education: ##########################
Agriculture: ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
If you want vertical bars instead of horizontal, you'd typically do that by storing the characters into (for one possibility) a 2D array. Then when you're done creating the graph in that 2D array, you scan across the array "sideways" to print out its contents, and scan through the other direction "backwards", so your labels end up at the bottom of the screen. I'd start by filling the array with space characters, then write out the contents of the bars into the array. Then after that's one, you print it out to the screen.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I did not write this code.
i'm on my 3rd day of coding in C++ and i'm having a hard time understanding how incremnent works in general.
int main()
{
int antal_ord {};
double medellangd {};
string kort_ord;
string langt_ord;
int min_length {100};
int max_length {};
string S;
cout << "Mata in en text:\n" << endl;
while (cin >> S)
{
if (S.length() > max_length)
{
max_length = S.length();
langt_ord = S;
}
if (S.length() < min_length)
{
min_length = S.length();
kort_ord = S;
}
medellangd+=S.length();
antal_ord++;
}
if (antal_ord == 0)
{
cout << "Inga ord matades in." << endl;
}
else {
medellangd = (medellangd / antal_ord);
round(medellangd);
cout << "Texten innehöll " << antal_ord << " ord." << endl;
cout << "Det kortaste ordet var " << '"' << kort_ord << '"' << " med "
<< kort_ord.length() << " tecken." << endl;
cout << "Det längsta ordet var " << '"' << langt_ord << '"' << " med "
<< langt_ord.length() << " tecken." << endl;
cout << "Medelordlängden var "<< fixed << setprecision(1) << medellangd << " tecken.";
}
return 0;
}
antal_ord is the variable for the amount of words written in this scenario.
In the line where it says "cout << "Texten innehöll " << antal_ord << " ord." << endl;" how does it know how many words have been written? The only time this variable is used before this line is when the variable gets incremented, but how does that let the variable know how many words have been written in total?
and also the .length command, does it basically just count the amount of letters written?
There's really nothing special going on here. Every time you read one word with cin >> S, you increment antal_ord by one. Since you started with zero words written and antal_ord==0, at the end antal_ord will equal the number of words read from cin.
Similarly, S.length() returns the number of letters currently in S. In your case, that is exactly the number of letters read from cin since you didn't chance S after reading. But if you did S += " some extra letters, then S.length() will of course change.
When you'll learn about most programming languages, you'll start off with basics: syntax, data types, declarations (vars + funcs as well as other possible concepts), loops, calls, math operations and other code-control techniques relevant to each programming language.
What you'll see about most (and I;ll try to "rewind" from the generalization I started with and back down to C/C++) is that you have the following type of math operation variations when it comes to addition (let's focus on this, as it's more on point with the question).
result in a separate variable, in our case b: b = a + 1;
result in the same variable: a += 1;
incrementing the value of the variable: a++;
Expanding on it:
In the first case, b will have its value overwritten and is dependent on a different values (in this case the value of a and 1). What you need to focus on here is that a is NOT changed.
In this case, a receives a new value and is incremented by the right-side-value, in our case 1. a is changed by adding one (not incrementing)
In our case, similar to #2, the value of 8a* is updated, but the incrementation is done by 1.
Apart from syntactic sugar or code style preference, the difference between each is also in the way the variables are assigned their values (more formally said, in the assembly code "underneath"). This topic is a lot more complicated for someone that started programming, but focusing on the question, the answer is simply that ++ increments the value by 1.
Also note that there is a difference in certain coding flows between ++a and a++. Mainly in loops. For ++a the value is set before executing the code, using the already incremented value in the code, while a++ uses the current value of a first, then increments it.
Try it like this:
int i = 0;
while (++i < 100)
{
std::cout << i << std::endl;
}
... versus...
int i = 0;
while (i++ < 100)
{
std::cout << i << std::endl;
}
Then count how many lines each case wrote.
There is also a small caveat you should be aware of, it's a bit more advanced, so it's just a little "FYI" for you. There are two C++ techniques called "function overloading" and "operator (re)definition". Let's focus on the second one. You could build your own data type (for example a struct or class) and implement your own operators that do something other than what their arithmetic counterparts do. You'll see this in iterator definitions. In that case ++ is not "actual value incrementation" (so it's not a math calculation), but rather switching to the next item in a list. Once you reach std::vector lessons you'll encounter that.
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.
I'm trying to figure out a way to print out a list of memory addresses stored in a file, where there will be 4 or so columns. So it'd print out 4 addresses, each one separated by a '\t', and then do a new line.
I wrote this and it works, except the problem is that once the addresses become 8 long, the tab just gets even wider so it looks bad.
cout << hex;
for (int i = 0; i < getSizeA(); i++) {
fread(&buffer, sizeof(uint32_t), 1, in);
if (i % 4) {
cout << "\t";
}
else {
cout << "\n";
}
cout << buffer;
}
cout << endl << dec;
It looks like this when it's 7 or less
and then the tabs get wider after they're 8 long:
I could probably just add another if statement for that, but it'd probably make my code even more ugly.
Is there a better way to do this than what I'm doing? Namely, a way to separate them using '\t'?
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!
I am having a lot of trouble aligning my output to the terminal. I want to print a vector of vectors viz vector< vector<double> > myvec; to the output where myvec[i] occupies the ith row on the terminal. The vectors composing myvec have size 3
This is the way I am trying to print it.
for(unsigned int i=0; i<myvec.size() ; ++i )
{
cout<<myvec[i][0]<<" "
<<myvec[i][1]<<" "
<<myvec[i][2]<<'\n';
}
When I print this to output only the myvec[i][0] column of numbers is aligned properly. The rest of the numbers look messy. Is there a good way to align this output?
(Ignore the 0.7 printed to the right on line 5 of image)
You can use setw() to set the minimum number of characters you want to be written and left to output the data to the left. Like this:
cout << setw(8) << left << myvec[i][0];
This should fill the empty space with spaces but if not, then you can do:
cout << setw(8) << left << setfill(' ') << myvec[i][0];
You will need to #include <iomanip> for this.
Just a couple notes about your code:
Alignment types
quasiverse's answer gives you left justification, i.e. every number starts in the first character position. Drop the left to make it right-justify, i.e. every number starts in the last character position.
Aligning the decimal points is a bit harder. If you want to set a fixed number of digits past the decimal point, then replace the left with fixed and add setprecision(), giving it the number of digits you want past the decimal. For example, to show two digits past the decimal:
cout << setw(8) << fixed << setprecision(2) << myvec[i][0];
2-D Vectors
You're declaring vector< vector<double> > myvec;, but the minor (second) dimension appears hardcoded to 3. This means that you are creating a vector of vectors, where each row is an entire vector object with storage for three doubles.
vectors don't store their data internally; the actual vector object just stores the number of elements, a pointer to the actual data storage, and maybe a couple other things. The actual data is stored in a separate block. This will create a lot of overhead and memory fragmentation (every row allocates a block to store the data).
For example, for a 1000x3 vector, there is the top-level vector object on the stack, an array of 1000 vector objects (one per row) on the heap, and each of those points to a block of three doubles, so you have 1001 objects on the heap and every access has to go through two pointers. Slow and inefficient.
vector is overkill if the length is fixed. So I'd recommend having a vector of structures, with each structure having three doubles:
struct point {
double x, y, z;
};
vector<point> myvec;
This stores all the data in one block, since point is completely self-contained. Then your code is:
for(unsigned int i = 0; i < myvec.size() ; ++i)
{
cout << setw(8) << left << myvec[i].x << ' ' << setw(8) << left << myvec[i].y
<< ' ' << setw(8) << left << myvec[i].z << endl;
}
Or, the C++ iterator way to do it:
for(vector<point>::const_iterator elem = myvec.begin(); elem != myvec.end() ; ++elem)
{
cout << setw(8) << left << elem.x << ' ' << setw(8) << left << elem.y
<< ' ' << setw(8) << left << elem.z << endl;
}
This saves a bunch of calls to operator[]. If your compiler supports the new C++11 standard, you can change the for() line to:
for(auto elem = myvec.begin(); elem != myvec.end() ; ++elem)
where auto tells the compiler to make elem the same type as what myvec.begin() returns. Another C++11 way, less likely to be supported, is the range-based for loop:
for(auto elem: myvec)