I am writing a C++ program that prompts the user for an input and then keeps track of how many times that input is entered. I am currently using a do-while loop and a switch statement. The part I am having trouble with is the switch statement. I can't figure out how to keep track of how many times an input is entered. For example:
Enter Value: 4
Enter Value: 4
Enter Value: 4
Enter Value: 3
Enter Value: 3
// I then want the program to be able to know and then eventually output, how many times the number '4' and '3' were entered.
I thinking possibly using some sort of increment counting form, but not 100% sure.
Thanks!
You'll probably want to use a std::map<int,int>. Here's why.
Let's look at alternatives, starting with the obvious:
int count0;
int count1;
int count2;
int count3;
int count4;
...
switch(input) {
case 0: ++count0; break;
case 1: ++count1; break;
case 2: ++count2; break;
case 3: ++count3; break
case 4: ++count4; break;
}
This does what you ask: you evaluate the input, and keep track of the number of times that specific input has been seen. This form does suffer from many problems:
It requires one line of source code for each alternative. This becomes a problem when the user can enter any value, say, from 0 to 10,000!
It has duplicate, virtually identical lines.
It has many variables, each of which has to be entered independently, but uses identically.
We can reduce the variable count by specifing an array:
int count[5];
...
switch(input) {
case 0: ++count[0]; break;
case 1: ++count[1]; break;
case 2: ++count[2]; break;
case 3: ++count[3]; break;
case 4: ++count[4]; break;
}
This still suffers from too many almost-but-not-quite identical lines of code. Let's try to get rid of the switch statement:
int count[5];
...
++count[input];
Ah, now we are getting somewhere! By eliminating the switch statement, we have one easily-maintained line of code. But what if the user (accidentally or maliciously) enters a 6? Then we will increment count[6], which does not exist. This is a Bad Thing. We could increase the size of the array:
int count[50000];
...
++count[input];
Now we are safe from the user. If he enters a 6, the Bad Thing no longer happens. Uh-oh, what about if the user enters 51000? We will increment count[51000] which does not exist. It should be obvious that we can't win this game -- for any number we choose, the user might choose that number plus 1.
Even if we could win, we'd still lose. If we are only asking the user to enter a few numbers, then we will have wasted the other 49,997 entries in the arary.
Fortunately C++ has a data structure that we can use which:
can take arbitrary numbers as its range, and
is space-efficient (compared to a large wasted array).
That data structure is called a map:
std::map<int,int> count;
...
++count[input];
A map is sort of like an array, but grows itself in a special way. Only the entries that we use are ever allocated, and every entry that we use is automatically allocated.
std::map<int, int> frequency;
int value_entered_by_user = f();
frequency[value_entered_by_user]++;
If your range of input values is limited, you can use an array. Each element of the array represents an input value. Initialize the elements to 0 at the beginning and increment the appropriate element when its corresponding input value is entered.
Related
so this is the code that im trying to get to work but it displays "duplicate case value" whenever it reaches for B
im a first year college student so i might have used a wrong format or i might be overlooking something i really dont seem to figure out the problem so i turn to you guys for help
char dep;
int exp;
cout<<"please enter your department, A, B OR C: ";
cin>>dep;
cout<<"please enter your years of experience ";
cin>>exp;
switch(dep)
{
case 'A' || 'a' :{
switch (exp) {
case 5:
cout<<"you will recieve a 5% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 5% raise";
break;
}
}
break;
case 'B' || 'b' :{
switch (exp) {
case 5:
cout<<"you will recieve a 2% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 2% raise";
break;
}
}
break;
Though it compiles (or would without the B version), and spells what you wanted if roughly translated to English, case 'A' || 'a' does not do what you think it does.
The expression after case is treated as an exact match for the selection statement — it's compared exactly to dep. You can't throw in a more complex expression and expect it to be "unrolled" into multiple comparisons. Think of switch/case as a simple lookup table, rather than an intelligent branching feature (that's what if is for!).
Perhaps confusingly, the expression 'A' || 'a' is valid in its own right, but (like any expression) it evaluates to a single value: either true or false, depending on whether either of the operands if "truthy". In this particular example, neither has ASCII value zero so both is truthy, and the expression is always true. It'll be converted to the type of dep (the rules say it becomes 1) and used for that exact lookup.
Since you did this with 'B' and 'b' too, you do then indeed have two equivalent cases.
Instead, write a separate case for each condition. Fortunately, since cases fall through, you don't need to repeat the "body" of the case: you can just put the two cases next to each other; just don't put a break between them:
case 'A':
case 'a':
// code here
break;
case 'B':
case 'b':
// code here
By the way, you misspelt default.
This is a model solution code of the following problem;
"The input consists of T test cases. The first line of the input is given a T.
Each test case consists of three rows of integers separated by a single space, each consisting of three random points of x and y coordinates. The coordinates of the top left pixel in the browser viewport are (1, 1) and the coordinates of the bottom right pixel are (1000, 1000). All coordinates are located within the viewport and the positions of each point are different."
And here is the sample of the input.
2
5 5
5 7
7 5
30 20
10 10
10 20
7 7
30 10
The last two lines are the answers of the problem.
And here is my three questions.
1) What happened when we use cin statement in initialization?? It receives how many actions it will perform from the user in the initialization of for loop. I understand that this cin statement works properly. I cannot understand how this code knows how many times this for loop has to be repeated. This is because there is no action on T after initialization with a value of T from the user. There is no actrion in 'increment/decrement' also.
2) After googling, I understand when there is cin in condition, the loop ends when there is no more inputs or the inputs' type does not match the variables' type. But in this code, the for loop ends when the repeated time (T) is over. How could this happen???
3) Finally, the outcomes should be presented after all inputs are finished not by one-by-one. Then how could this for loop memorize the outcome of each set(3 inputs)??
I'm not English speaker T.T Thank you for reading my question.
#include<iostream>
int main()
{
int T,a,b,c,A,B,C;
for(std::cin>>T; std::cin>>a>>A>>b>>B>>c>>C; printf("%d %d\n",a^b^c,A^B^C));
}
What happened when we use cin statement in initialization??
That part of for() loop can contain any simple statement, not
just initialization statement. This statement is done only once. For
loop
for ( init condition ; iteration )
statement
is actually equivalent of this code:
{
init
while ( condition )
{
statement
iteration;
}
}
But in this code, the for loop ends when the repeated time (T) is
over. How could this happen???
The operator >> overloaded for streams return stream it acted on. Class
ios_base which is common parent of all streams, contains this
operator
std::ios_base::operator bool()
This operator is an equivalent of good() method. When >> fails to read and parse values from input stream, good() returns false,
loop breaks. T is not used in the provided code.
Then how could this for loop memorize the outcome of each set(3
inputs)??
It doesn't. It prints result after reading each set.
PS. People who read\proof-check code after programmer, would tend to have murderous intent toward those who write for() loops like that.
If we use a cin statement as our initialization, we execute this once. It will receive the input and place the value in the variable T. You are completely right; there is no action on T after initialization such as incrementing or decrementing its value.
This is not true. The code does not end when the it repeated T times. As long as (valid) input is given, this for-loop will continue. This is because the condition part of your for-loop consist of a cin statement. That is, as long as your cin statement succeeds, the for-loop will continue.
It cannot. Each time the loop runs, you overwrite the variables a, A, b, B, c and C. Hence, the old values are lost.
I have an input txt file that looks like so:
3 2
ATCGATTGA
GACTATACG
I'm using fstream, and creating it as a string. I'm then able to turn 3 and 2 into their own separate ints, but want to also turn the next two lines into ints as well. I'm trying to use getline() because I am told that would be the most efficient, but can't figure out how to create the lower two as their own ints. Any help on how to get that to work?
getline isn't going to convert a string to an int. Just not what it's intended to do.
If you want to convert ATCGATTGA to an int, the obvious approach would be to treat the input as base 4. If memory serves, the "order" is usually given as A-T-C-G. Assuming that's correct, you'd treat them as A=0, T=1, C=2, G=3, and convert the sequences accordingly (but note that for our purposes, the order you choose doesn't really matter, as long as you use the same order for both encoding and decoding).
int cvt_amino(std::string const &amino) {
int result = 0;
for (char c : amino) {
result *= 4;
switch(c) {
case 'a':
case 'A':
result += 0;
break;
case 't':
case 'T':
result += 1;
break;
case 'c':
case 'C':
result += 2;
break;
case 'g':
case 'G':
result += 3;
break;
default:
throw std::runtime_error("Error: bad argument");
}
}
return result;
}
The result is a unique number for each sequence (up to the maximum that will fit in an int). Modulo bugs (I haven't tested this code) you should be able to convert a result back to the original sequence that generated it.
That does assume that the length of each original sequence is known/fixed. If lengths might vary, you won't know the number of leading 'A's to include. In such a case, you probably want to switch to base 5, and change the mapping to A=1, T=2, C=3, G=4. This removes the ambiguity with respect to variable-length inputs (but reduces the maximum length that will fit in a given variable size).
As far as reading data from the file goes, it seems pretty trivial, at least assuming we know the input format. For the format you've given above, you might use something like this:
int a, b;
your_file >> a >> b; // read the 3 and 2
// We'll assume an arbitrary number of space-separated sequences after that:
std::string input;
std:vector<int> values;
while (your_file >> input)
values.push_back(cvt_amino(input));
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I am having trouble forming the output statement for this program. The correct output should print the same input number that its numerical value holds. .
It looks like you want something similar to this:
#include <iostream>
using namespace std;
int main()
{
int standard, count1, count2, count3, count4, count5;
// Initialize your int's
standard = count1 = count2 = count3 = count4 = count5 = 0;
do {
cout<< "Enter value: ";
cin >> standard;
// Switch through your cases
switch(standard)
{
case 1:
count1++;
break;
case 2:
count2++;
break;
case 3:
count3++;
break;
case 4:
count4++;
break;
case 5:
count5++;
break;
}
} while(standard != 0);
// Do this type of loop for all your count vars
for(int i=0;i<count1;++i)
cout<< "1";
for(int i=0;i<count2;++i)
cout<< "2";
// And so on...
return 0;
}
For the for loops, note that you are going from 0 to < the total number. If you went to <= you would go passed that number. The range [0,4] = 5 (or in our case [0,5) for the set of integers) and so does [1,5] so remember to mind your offsets. Good luck!
EDIT: Also recognize that the position of the switch statement has been moved. By placing it in the loop, you actually count every time it runs through the loop. For instance, the loop "blocks" (in other words, it waits for input) at your cin line. When it receives an input (though you have no error-checking, so a non-int value may cause a segfault), it will then check it against the switch statement and increment accordingly.
By placing the switch statement outside the loop (as you initially had it), please realize that nothing happens. You have no default condition in your switch statement, nor a case for handling 0. If you check your switch after the loop, standard == 0 since that is how you exited the loop in the first place (therefore, standard's last value will be retained).
Furthermore, revisit the for loop syntax. This can be done in several ways, there are many good articles here on SO which can help you further by using the search function, but it basically works like this:
for(STARTING_POINT;SOME_CONDITION;SOME_CHANGE);
STARTING_POINT = The value where you should start your loop
SOME_CONDITION = When this condition is true, then the loop will terminate
SOME_CHANGE = how to change your variable (i.e. from starting point) until it reaches the condition
So a loop which looks like this:
for(int i=1;i<=5;++i){ ... }
means to initialize int i to value 1
Until i <= 5 run through your loop
Then, on every iteration, increment i by one (which is ++i or i++)
Finally, as you can see, I added an initialization line to my int's. What this does is it gives your variables some starting value rather than garbage value.
I hope this helps
Regards,
Dennis M.
You definitely need to move the switch statement within the while loop (Edit: this was based on the OP's initial posting of the code).
I really don't understand what you're trying to accomplish, but this part here:
for (count1=0; count1<=5; count1++)
cout << "1";
Is going to print out '1' 6 times in a row, regardless of the input. Could you explain a bit more what you're trying to do?
Here's my interpretation: You want to input a sequence of numbers (ending with zero), then output those exact same numbers, using loops.
Here's some pseudocode to give you a hint.
Declare an array of int's large enough to hold all your input numbers.
Declare a counter c = 0.
Begin loop while input is not 0
Input number from user and store it in array[c].
Increment counter c.
End loop
Begin loop i from 0 to c-1
Output number that is in array[i].
End loop
No need to use a switch statement and a counter for each possible number. Just store each input in it's own spot in an array.
In C++ want to write something like this
int Answer;
if (Answer == 1 || Answer == 8 || Answer == 10)
and so on, is it any way to make code shorter without repeating variable always?
Try:
switch (Answer) {
case 1: // fall through
case 8: // fall through
case 10:
// ... do something
break; // Only need if there are other case statements.
// Leaving to help in mainenance.
}
For readability I'd encapsulate the logic in descriptively-named functions. If, say, your answers are things with a particular color, and answers 1, 8, and 10 are green things, then you can write that logic as
bool ChoiceIsGreen(int answer)
{
return (answer == 1 || answer == 8 || answer == 10);
}
Then your function becomes
if (ChoiceIsGreen(Answer))
{
// offer some soylent green
}
If you have a lot of choices like this, I can see it getting hard to read if you have a lot of raw numbers all over the place.
If and only if you need to optimise for code size manually, and Answer is guaranteed to be positive and less than the number of bits in an int, you might use something like
if ( ( 1 << Answer ) & 0x502 )
But normally you don't want to obscure your logic like that.
You could put the values into a container and search the container.
Sounds like a std::set would be a wise choice:
if answer is in the set of (1, 8, 10) then do....
Remember that a std::set must be initialized during run-time, unlike numeric constants or an array of numeric constants. Before making any performance changes, first get the program working correctly, then profile if necessary, that is only if the program demands performance optimization.