Having trouble with "string subscript out of range" in C++ - c++

every time I try and input 't' it returns a "string subscript out of range"
while ((y != sequence.length()) && (base != 'u' || base != 't')) {
base = sequence[y];
y++;
if (base == 't')
{
//if the sequence is DNA
while (sequence[y] != sequence[z])
{
if (sequence[y] == 't')
{
mRNA_sequence += 'a';
}
else if (sequence[y] == 'a')
{
mRNA_sequence += 'u';
}
else if (sequence[y] == 'c')
{
mRNA_sequence += 'g';
}
else if (sequence[y] == 'g')
{
mRNA_sequence += 'c';
}
y++;
}
DNA = sequence;
sequence = mRNA_sequence;
}
}
if I input 't' it should turn it into an 'a'. it works for the rest.

#Yksisarvinen is correct. The incrementing of y is your primary issue. The other reason that it works for u and not for t is because your code does no processing on any other letter. if (base == 't') is the only case provided in your snippet.
You also use y as the variable for both the outer-while loop and the inner-while loop. This may be intended behavior, just be cautious. Your inner-while loop will increment y and that new, larger value will be the y value used in the outer-while loop.
You set DNA = sequence; and sequence = mRNA_sequence; inside the while loop without breaking it. Keep in mind that the while loop will now have a new 'sequence' to use in the sequence.length() call of the while loop. Since I believe your code is meant to have the same length values for DNA and mRNA sequences, you may sneak by, but it is dangerous. Your condition states while (y != sequence.length()) and if the mRNA_sequence was shorter than the initial sequence, then y could be greater than the length and this would still pass your while condition.

Related

not getting a proper sum

I'm trying to get ready for an exam for my year one programming course. I need my if statement to return a sum with the number of characters before the user enters a 'p' or 'P' in a 10 character string. However, I can't seem to get it to count properly.
for (int i=0;i<=strlen(toProcess);i++){
if (toProcess[i]!='p'|| toProcess[i]!='P'){
sum=sum+1;
printf("%c ", toProcess[i]);
}
}
if (toProcess[i] != 'p' || toProcess[i] != 'P') {
Short of some quantum-mechanical-weird universe where something can be p and P at the same time, this condition will always be true(a):
if it's neither p nor P: true || true -> true.
if it's p: false || true -> true.
if it's P: true || false -> true.
You need to use && for this particular case:
if it's neither p nor P: true && true -> true.
if it's p: false && true -> false.
if it's P: true && false -> false.
And, of course, if you want to stop after finding the first p or P, you need to break out of the loop as well. You could either do that as an else block for your (corrected) condition:
int sum = 0; // probably needed.
size_t len = strlen(toProcess); // cache for efficiency.
for (int i = 0; i < len); i++) {
if (toProcess[i] != 'p' && toProcess[i] != 'P') {
sum++;
printf("%c ", toProcess[i]);
} else {
break;
}
}
Or, you could change the condition to just be an early exit:
int sum = 0; // probably needed.
size_t len = strlen(toProcess); // cache for efficiency.
for (int i = 0; i < len); i++) {
if (toProcess[i] == 'p' || toProcess[i] == 'P')
break;
sum++;
printf("%c ", toProcess[i]);
}
You'll notice in both those cases, I've also changed <= into <. A ten-character string has character positions 0..9 so those are generally the indexes you should use. I've also ensured that, for efficiency, we're only calling strlen() once, on the assumption the string doesn't change while processing.
(a) Of course, my physicist buddies will tell me that the act of observing toProcess[i] will cause it to collapse to one or the other, so this isn't technically correct. Leave it to physicists to spoil an otherwise funny physics joke :-)

Why is my code not calculating the correct value for the expression string?

In the code I use an expression tree "3 + 2.53 - 1.75" that should return a result of 3.78. However, it ends up adding all the values within the string and outputs 7.28. I ran through the code multiple times on paper trying to see what happens in each iteration of the for loop where the index variables i and distance_operator are used too. As far as I have gone through it I cannot find a reason why the program continues to add each float value. By the time the '-' character is reached it should subtract the next value.
The distance_operator is used to be an offset from the first operator where index i will be pivoted so that I can take a portion of that string and calculate it using the substr() function.
float total = (float)value(expression[0]);
int distance_operator;
for (i = 1; i < expression.size(); i++) {
if (expression[i] == '+' || expression[i] == '-') {
distance_operator = i + 1;
while (expression[distance_operator] != '+' || expression[distance_operator] != '-') {
distance_operator++;
if (distance_operator == expression.size())
break;
}
if (expression[i] == '+')
total += std::stof(expression.substr(i, distance_operator - i));
else if(expression[i] == '-')
total -= std::stof(expression.substr(i, distance_operator - i));
}
}
The code is almost correct but there is an "off-by-one" error.
The problem is that when finding the - the right substring used will be "- 1.75" with a negative value when parsed as a number and you will be subtracting it, basically negating the value you wanted to use. The accumulating code should be:
if (expression[i] == '+')
total += std::stof(expression.substr(i+1, distance_operator-i-1));
else if(expression[i] == '-')
total -= std::stof(expression.substr(i+1, distance_operator-i-1));
Note that i+1 is used, so the expression sign found will be skipped.
Also note that this check
while (expression[distance_operator] != '+' || expression[distance_operator] != '-')
will always be true, because a thing is always different from A OR different from B. The correct logical operator is &&.

Extracting int from String on Arduino

I have a buffer of random characters streaming into my Arduino from a XBee module. I want to extract the first integer that it sees (will be <= 3-digit int if that makes a difference), then move on with that number and stop looking at the rest of the incoming characters.
For reference, I'm trying to use this as part of a 2-way handshake with a node.js server that doesn't get messed up when other Arduinos are also attempting to handshake or are already connected and sending data.
I think I have a way that might work to extract an int, but it seems really ugly, so I'm thinking there must be a much shorter/cleaner way to go about this. Here's my very long code to do something that's probably pretty simple:
String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
while (intStart != 2) {
if (intStart == 0) {
if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') ||
(msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') ||
(msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') ||
(msg[i] == '9')) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is still int
if (intStart == 1) {
if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') ||
(msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') ||
(msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') ||
(msg[i] == '9')) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is not int
else if ((msg[i] != '0') && (msg[i] != '1') && (msg[i] != '2') &&
(msg[i] != '3') && (msg[i] != '4') && (msg[i] == '5') &&
(msg[i] != '6') && (msg[i] != '7') && (msg[i] == '8') &&
(msg[i] != '9')) {
intStart = 2;
}
}
}
int number = intString.toInt();
Serial.println(number);
Any suggestions/advice is greatly appreciated.
Rather than compare against every number from 0 to 9, use the standard C function isdigit().
String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
while (intStart != 2) {
if (intStart == 0) {
if (isdigit(msg[i])){
intString += msg[i];
intStart = 1;
}
}
// previous int, next is still int
if (intStart == 1) {
if (isdigit(msg[i])) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is not int
else if ( isdigit(msg[i]) ) {
intStart = 2;
}
}
}
"Rubber duck debugging":
Let's assume the first char of the msg is a digit:
set intStart to 0
take the first char of the msg
while intStart is not yet 2
if intStart is 0 (it is, we haven't adjusted it) and the first char of the msg is digit (we assumed it is), then append the first char to intString and make intStart = 1
if intStart == 1 (it is, we set it at the prev step) and the first char of the msg is digit (it is still the first, i didn't change), then append the first char to intString (great, now I have it twice) and set intStart=1 (hey, intStart didn't change). Else... well, we can ignore else, we are in the good conditions for then
so back to the step 3, with the intStart==1 and i still 0 and the first char of the msg still a digit.
Should I continue or are you able to do it?
In essence, with the first char of the msg a digit, you'll never get out from while (intStart != 2) until you run out of heap-space due to intString growing by repeating the same fisrt char all over.
Is that what you want?
Is it so hard to explain this to your rubber duck before asking SO?(yes, I understand, Arduino doesn't have a debugger, but you still can use Serial.print)
[Update on the comments]
Sorry if I was unclear, but it doesn't necessarily start with an integer, the integer could be in the middle of the char buffer.
The first sequence of digits in the char buffer of any length (really doesn't have to be restricted to max 3-digit, only if it makes it easier)
So, before stating to collect, we just need to position ourselves on the first digit of the string buffer
int startScan=0;
// no body for the cycle, everything works just from
// the exit condition and increment
for(
;
startScan < msg.length() && ! isdigit(msg[i]); // as long as it's not a digit
startScan++
);
// from this position, start collecting for as long as we have digits
int intValue=0;
String intString;
for(; startScan < msg.length() && isdigit(msg[startScan]); startScan++) {
intString += msg[startScan]; // take it inside the string
// careful with this one, it may overflow if too many digits
intValue = intValue*10 + (msg[startScan]-'0');
}
// if we reached here with an empty intString, we didn't find any digits
If you don't need the intString, just the intValue, don;t use the intString - at most a bool hasDigits to init to false and set to true in place of intString += msg[startScan]; (to act as a signal for the 'no digits encountered' case).
If you don't need the intValue, just wipe out from the code anithing that uses it.
So, if my understating is correct, you have the following problem:
I have a String message which starts by at most 3 decimal digits and ends possibly with other info I don't need. I want that 'at most 3 digits' prefix transformed in an integer for me to use further
If this is you problem, then try this:
int intValue=0;
String intString;
int maxLookInto=(msg.length() > 3 ? 3 : msg.length()); // at most 3 digits
for(int i=0; i<maxLookInto && isdigit(msg[i]); i++) {
// if we got here, we know msg[i] is still a digit, otherwise
// we get out of cycle ealier
intString += msg[i]; // take it inside the string
intValue = intValue*10 + (msg[i]-'0'); // transforming in base 10 in an int
}
// Do what you like with either intString (textual representation of the
// at-most-3-digits or with the same value converted already to a number
// in intValue
If Arduino doesn't have the isdigit function available, you can implement your own like
int isdigit(char c) {
// we are using ASCII encoding for characters, aren't we?
return (c>='0' && c <='9');
}
One way is to use the String object. This has a toInt method.
BTW there is an Arduino specific stack exchange. arduino.stackexchange.com

Keeping Tally of Characters in Arrays

I'm working on a Caesar Cipher program for an assignment and I have the general understanding planned out, but my function for determining the decipher key is unnecessarily long and messy.
while(inFile().peek != EOF){
inFile.get(character);
if (character = 'a'|| 'A')
{ aCount++; }
else if (character = 'b' || 'B')
{ bCount++; }
so on and so on.
What way, if it's possible, can I turn this into an array?
You can use the following code:
int count [26] = {0};
while(inFile().peek != EOF){
inFile.get(character);
if (int (character) >=65 || int (character) <=90)
{ count [(int (character)) - 65] ++; }
else if (int (character) >=97 || int (character) <=122)
{ count [(int (character)) - 97] ++; }
}
P.S. This is checking for the ASCII value of each character and then increment its respective element in the array of all characters, having 0 index for A/a and 1 for B/b and so on.
Hope this helps...
P.S. - There was an error in your code, = is an assignment operator and == is a conditional operator and you do not assign value in if statement, you check for condition... So always use == to check for equality...
You can use an array in the following manner
int letterCount['z'] = {0}; //z is the highest letter in the uppercase/lowercase alphabet
while(inFile().peek != EOF){
inFile.get(character);
if (character > 'A' && character < 'z')
letterCount[character]++;
}
You can also use a hashmap like this
#include <unordered_map>
std::unordered_map<char,int> charMap;
while(inFile().peek != EOF){
inFile.get(character);
if (charMap.find(character) == charMap.end())
charMap[character] = 1;
else
charMap[character] = charMap[character] + 1;
}
In case you do not know, a hashmap functions as an array, where the index can be any class you like, as long as it implements a hash function.

Is there a faster/shorter way of doing these tests in C++ instead of using "if"?

...
int x;
int z1 = '-';
int z2 = '-';
int z3 = '-';
int z4 = 'a';
if ((z1 == 'a' || z1 == 'b')) x++;
else if ((z1 == '-' && z2 == 'a' || z2 == 'b')) x++;
else if ((z1 == '-' && z2 == '-' && z3 == 'a' || z3 == 'b')) x++;
else if ((z1 == '-' && z2 == '-' && z3 == '-' && z4 == 'a' || z4 == 'b')) x++;
else x = 0;
printf("x=%d\n",x);
...
My code is much longer than this, and I'm wondering if there is a shorter way to get the same results or a faster way for the program to execute it!
Thanks in advance for your help and attention!
To make the code shorter (and more readable, extendable, and all-around better), put the z variables in an array and then loop over it. The below solution will remain the same number of lines for any number of z variables you want to have. Just adjust the size of the array.
int z[4];
for (int i = 0; i < 4; i++)
{
if (z[i] != '-')
{
x += (z[i] == 'a' || z[i] == 'b'); // note the implicit conversion from boolean to int
break;
}
}
Note you still need to account for the last index being a - and x never being incremented or set to 0, but that can be done with a simple modification. I suggest putting the above into it's own evaluation function and than you can simply have a catch all return.
Note: You should probably be using the char datatype for your variables since you are specifically storing characters in them.
In terms of speed, this solution is probably equivalent if not better than your current solution. It will branch just as many times as your if-else statements but will probably have better branch prediction during run-time (thanks to the for-loop) and will evaluate less expressions.
You can make it faster by using switch statements.
switch (z1)
{
case 'a':
case 'b':
x++;
break;
case '-':
switch ( z2 )
{
case 'a':
case 'b':
x++;
break;
case '-':
x += (z3 == 'a' || z3 == 'b');
x += (z3 == '-' && z4 == 'a' || z4 == 'b');
break;
}
break;
default:
x = 0;
}
You can do simething like this:
int main(void) {
int x;
char z[5] = "---a";
for (int i = 0; i < 4; i++) {
if (z[i] == 'a' || z[i] == 'b') { x++; break; }
else if (z[i] != '-') { x = 0; break; }
}
return 0;
}
Here are some tips to optimize your code (runs faster)
++x is more faster way to increment x than x++. (Refer : Avoid Postfix Increment Operator)
If you are using GNU C, you can use unlikely/likely macros to optimize your if statement. To use those macros efficiently, you have know which if statements are going to be executed more often.
If you are using windows, you can use _assume(). But this function is not recommended to use because it is dangerous. Instead look at what Intel says
According to a document from Intel:
In order to effectively write your code to take advantage of these
rules, when writing if-else or switch statements, check the most
common cases first and work progressively down to the least common.