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));
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.
First bear with me,I am a noob.
I was trying to write a program that outputs days of the week. Say for example if one enters day1 it outputs Sunday, day2 Monday and so on. I used a switch statement with an int mapped onto an enum for the switch cases. The problem I seem to be having is that it does no seem to work, at least not when I input day1. It works as expected when I use int values 1 through 7. I have tried to find solutions to this and so far am only hitting walls kindly help.
Here's my code:
enum days{day1,day2,day3,day4,day5,day6,day7};
int day;
cout<<"Enter the day of the week in format day1 through day7 ";
cin>>day;
switch(day)
{
case day1:
cout<<"Sunday";
break;
case day2 :
cout<<"Monday";
break;`
}
If you want to take input like day1, day2 etc, then why did you declared the input variable as int, it should be char array..
If you want to take input like 1, 2 then it's kinda okk...
If you want to input string and then compare it with enum values then first you have to convert it into an integer value.
you can do this,
char day[4];
cin>>day;
int d=day[3]-49;
then use it in the switch as you did..
switch(d)
{
case days::day1:
cout<<"Sunday";
break;
case days::day2 :
cout<<"Monday";
break;
If you want your users to enter day1 and to map it to your enum, you need to parse integer value from input yourself. You can either read it as string and then do parsing yourself or use slightly non C++ solution with scanf:
int dayNum = 0;
char buff[16];
scanf("%[^0-9]%d", buff, &dayNum);
also remember that enums start from value 0, if you want them to start from 1 then you must change enum to:
enum days{day1=1,day2,day3,day4,day5,day6,day7};
^^
day2, day3 etc. will have values 2,3,...
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.
I am trying to understand the switch statement better. I don't need the code but kinda a walkthrough on how it would be done.
If someone enters a 7 digit phone number EG. 555-3333 but enters it as "jkl-deff" as it would correspodnd to the letters on the dial pad, how would I change the output back to numbers?
Would this work:
switch (Digit[num1])
case 'j,k,l':
num1 = 5;
break;
case 'd,e,f':
num1 = 3;
break;
To do that with a switch statement, you'd have to walk through the char array, switching on each character. Group all the chars that have the same number together.
Something like
switch (phoneChar[i])
case 'a':
case 'b':
case 'c':
newChar[i] = '2';
break;
That said, I'm not sure that switch case is the best way to do that. I don't know what would be the best off the top of my head, but something feels wrong about this :)
Edit
The i would be the index of the current character under consideration. You'll have a 7 (or 8 or 10 or 12 character string depending on formatting) for a phone number. You'd have to take each character at a time.. so phone[0] = 'j' in the above example.
I would not use a switch!
// A,B,C => 2; D,E,F => 3 etc.
static int convert[] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
for(int loop =0 ;loop < Digit.size(); ++loop)
{
num = convert[Digit[loop] - 'a'];
// Thus the character 'a' gets mapped to position 0
// the character 'b' gets mapped to position 1 etc.
// num is then the character mapped into the covert[] array above.
}
You could probably do it like this:
if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
to convert a character to a phone pad digit. The num==8 part at the end handles the exra digit on the 9 key.
Altogether it would look like this:
char c = getNextCharacterSomehow();
int num = -1;
if (isdigit(c)) num = c-'0';
else if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
else if (isupper(c)) { num=(c-'A')/3; num = 2 + (num==8) ? 7 : num; }
Also, a note about the switch statement: The item that comes between the "case" and the ":" has to have the same type as the thing specified by the "switch()" portion. And that type must be a scalar, which excludes things like strings.
How do I read in a variable number of characters? The user can input a positive or negative number that is too big to be stored in an integer. I am then checking to make sure the char is a number and storing it in an array of ints (although that will probably be changed to a short since I only need to be able to store 0-9).
istream& operator>>(istream &in, LargeInt &l)
{
char x;
do
{
cin >> x;
int v = (int)x;
switch( v )
{
case 48: v = 0;
case 49: v = 1;
case 50: v = 2;
case 51: v = 3;
case 52: v = 4;
case 53: v = 5;
case 54: v = 6;
case 55: v = 7;
case 56: v = 8;
case 57: v = 9;
default: v=10 /* END INPUT */;
}
l.largeInt[ l.usedLength ] = v;
l.usedLength++;
//need to check array length and make bigger if needed
}
while( (x == 45) || ((x > 47) && (x < 57)) );
}
If you wish to read digits, you need to do it a character at a time. E.g.
char ch;
while (std::cin.get(ch) && ch >= '0' && ch <= '9') {
// You have a digit to process (maybe you want to push_back it into a vector)
}
Notice that you need to use ch - '0' to get the value of the digit because ch contains the character code rather than the value. In ASCII this means that '0' is in fact 48, '1' is 49 and so on (and 'A' is 65). The values may be different for different character encodings but the digits are guaranteed by the standard to be sequential, so that subtracting zero works.
Why not input a string, and then convert it to a number?
A few points. First of all, if you only need to store values from 0 to 9, you might as well store them in a char (which is just a small integer type in C++).
Second, you probably need to add a break; to the end of all the cases in your switch statement -- in C++, execution falls through from one case to the next without a break to stop it. Then again, you should probably just get rid of the switch statement entirely. You'd probably be better off using isdigit from <ctype.h>. Since char is a small integer type in C++, you can also do math on it, so you could just subtract '0' from each digit after verifying that it is a digit. Edit: contrary to the later edit, I would strongly advise against subtracting 48 from each digit. First of all, it's not guaranteed to work (and won't with some character sets -- even if you don't think your code will ever be used on an IBM mainframe, it's a poor habit). Second, it makes the intent much more apparent. I don't think there's a good reason to expect the reader to have memorized the ASCII table so they'll know that 48 is equivalent to '0'.
Finally, to deal with the problem you knew you had, you'll probably want to look up std::vector.