not getting a proper sum - c++

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 :-)

Related

Having trouble with "string subscript out of range" in 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.

Assertion Error using a struct vector c++

I have a program where I want to update a variable from a string. The function will read in a string, find if it is addition, subtraction, etc. and then add it to the variable. The function is this:
using namespace std;
struct variable{
string name;
int value;
};
void update_varabile(string line, vector<variable> & v)
{
char c = line[0]; //variable to be updated
string b;
char d[0];
int flag = 0; //counter
int a = 0;
int temp_value = 0;
int perm_value = 0;
for (int i = 0; i < v.size(); i++) {
if (c == v[i].name[0]) {
flag = 1;
temp_value = v[i].value;
break;
}
}
if (flag == 1) { //variable is present
for (int i = 0; i< line.size(); i++) {
if (line[i] == '+'|| line[i] =='-'|| line[i] == '*'|| line[i] =='/') {
b[0] = line[i+1]; //assuming the integer is between 0 and 9
d[0] = b[0];
a = atoi (d);
if (line [i] == '+') {
perm_value = temp_value + a;
} else if (line [i] == '-') {
perm_value = temp_value - a;
} else if (line [i] == '*') {
perm_value = temp_value * a;
} else if (line [i] == '/') {
perm_value = temp_value / a;
}
}
}
for (int i = 0; i < v.size(); i++) {
if (v[i].name[0] == 'c') {
v[i].value = perm_value;
break;
}
}
}
}
The call in main looks like this:
int main()
{
variable a;
int val = 0;
string up = "c=c+2";
string f = "c";
vector<variable> q;
a.name = f;
a.value = val;
q.push_back(a);
update_varabile(up, q);
return 0;
}
However, when I run the code, I get this error message:
Assertion failed: ((m_->valid == LIFE_MUTEX) && (m_->busy > 0)), file C:/crossdev/src/winpthreads-git20141130/src/mutex.c, line 57
Process returned 1 (0x1) execution time : 0.014 s
Press any key to continue.
I have run the debugger line by line and it shows that the function properly executes. I have also tried to look for that C:/ file on my computer and it doesn't exist. Not sure why this isn't working.
First thing first, get rid of all the breaks. Only place breaks should be used in C++ is at the end of each case statement. Makes near impossible to read code with a bunch of breaks, because I have to go down and figure out what each break is there and why. If you need to get out of a for loop early, then use a while loop. you don't need breaks at the end of if and else statements because they cause the program to leave a function early, your if and else statements will naturally skip over if you are using if, else if, and else condition formatting.
Now having said that, you need to break down better what you are trying to do.
example you get a string value like this.
2+3+4-5+6
Your program is going to read from left to right. I am assuming you want it to take the first value which is two and then add three to it then four and so on and so fourth.
The way to do this is first parse the string for int values and then parse the addition and subtraction values. In other words read the int values out of the string untill you hit a value that is not between 0 and 9. Then see if that non-numerical value is an operator you are looking for. This way your program wont trip up on a value like 2555 and 2.
IE
//intValueHolder is a string.
while(i < line.size() && line[i] >= '0' && line[i] <= '9' ) {
intValueHolder.push_back(string[i]);
}
Then when you hit a '+' or something like that put the char value through a case statements. and don't forget to add a default value at the end to account for garbage input like 'a'. You may want to hold the value just incase you need to get your left side value first before you can get your right side value. But it sounded like you start out with a left side value so you really only need to find right and which operator it needs. I'm not going to rewrite your program because this looks like an assignment for school. But I will point you in the right direction. Let me know, if I was off on understanding your question.
You may also want to look into using queues for this, if you are not being restricted to just strings and vectors.

Checking if value in twodimensional array is equal to a "#"

I have an array that gets populated by either a "." or a "#", and I need a way of checking whether array[y+1][x] is equal to #, do something if it is and stop the loop, otherwise increment y. First I wrote it without the & before lavirint and it gave me an error that it can't compare a pointer and an int, which got me confused cause "#" shouldn't be an int?
The problem is the first condition in the loop never happens although it should, and the loop stops when
y==n
Maybe I'm just stupid and overlooked something but I would really appreciate a solution to this.
char lavirint[500][500];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%c", &lavirint[i][j]);
}
}
bool n_povecava = true;
...
while(n_povecava)
{
if(&lavirint[y+1][x] == "#" || y==n)
{
k--;
m_povecava = true;
n_povecava = false;
}
else
y++;
}
"#" is a string literal of type const char[2] and decays to const char*.
You need '#' which is a character:
if (lavirint[y+1][x] == '#' || ... )

Two variables that are true return false in (tmp1 == tmp2). Why? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I just came upon one problem. I wanted to compare whether my Eratostenes's Sieve contains prime numbers or not. In the code i have this line
if (sieve[2] == is_prime(2)) // returns false
printf ("true");
Now, sieve[2] is a boolean and it's value is true (I even checked in the array, so there's no doubt about it). is_prime(2) is a boolean aswell (I also checked).
Now my problem. The line presented above returns false. Yes - it returns false even though it's statement is:
if ( true == true ) // which normally returns true
printf ("true");
However, after removing one equation sign:
if ( sieve[2] = is_prime(2) ) // returns true
printf ("true");
This statement returns true.
Can someone briefly explain how does one equation mark work in this case in comparison to ==?
Thanks in advance
EDIT
is_prime:
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
sieve:
const int n = 10000;
bool sieve[n+1];
.
.
unsigned long int i;
sieve[0] = sieve[1] = false;
for (i=2; i<=n; i++) sieve[i] = true;
for (i=2; i*i<=n; i++) {
if (sieve[i]) {
unsigned tmp = 2*i;
while (tmp <= n) {
sieve[tmp] = false;
tmp += i;
}
}
}
[EDIT2]
The problem was with "is_prime(x)" Changed loop condition from "i!=x" to "i<=x"
Sorry for the trouble and thanks for the answers
UPDATE
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
Your is_prime() (above) is broken, with undefined behaviour, as when x is 2 (or indeed any actually prime number) it reaches the end of the function without having a return statement - the i!=x test means the x == i inside the loop can never be true.
is_prime(2) it's likely to return effectively random results (based on left over stack or register content / in your documented output it's seeming "returning" x itself, presumably because your ABI uses the same CPU register or stack address to pass in the argument and pass back the function's return value).
Specifically for 2, flow enters the first else clause, then with i=2 the first i!=x test fails and the for loop immediately exits... there's no return after the for's scope. Minimally corrected code (faster implementations are possible, but keeping the simplicity and intended logic):
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i < x; ++i)
if (x % i == 0)
return false;
return true;
}
Equivality / ==
With sieve[2] == is_prime(2) it's checking they have the same value - possibly after converting one of the values to enable the comparison, but you say they're both booleans so that's not necessary. This would yield a "true" value for the if when they're both true or both false.
Now my problem. The line presented above returns false. Yes - it returns false even though...
That doesn't make any sense... I suggest you add the following before the if statement to check the variables' values:
std::cout << "sieve[2] " << sieve[2] << " (bool)" << (bool)sieve[2]
<< ", is_prime(2) " << is_prime(2) << std::endl;
I even checked in the array, so there's no doubt about it
Be wary of mistakes like seeing the array content displayed ala { true false true false } and thinking [2] is the second value... it's actually the third. as array indexing starts at 0.
Assignment / =
With sieve[2] = is_prime(2) you're assigning the value of is_prime(2) into sieve[2], and the if statement is deemed "true" if that value is deemed true in a boolean context (i.e. it's a boolean with value true, or a non-0 number or pointer etc.). For most data types, the execution flow of if (sieve[2] = is_prime(2)) ... is the same as simply if (is_prime(2)) ..., but of course it also modifies sieve[2].
It assigns the right hand operand to left, and returns the left operand.Since you are assigning true to your variable, it evaluates to true. If you set your variable to false, you don't get the output, e.g:
bool x;
if(x = false)
printf("this won't be printed");
Here the equal affect the left operator with the value of the right operator then test the value. So the result must be the value of the right operator.
Your loop in is_prime will never run for the check x == i will be true, because it runs as long as x != i. Those two conditions are mutually exclusive.
That means the function will end without a return statement, which leads to undefined behavior.
This
if ( sieve[2] = is_prime(2) )
contains an assignment, not a comparison.
As the value of an assignment is the value assigned, it is true whenever is_prime(2) is.
However, let's look at your is_prime and see what happens if we pass it a 2...
bool is_prime(int x) {
unsigned int i,j,k;
So far, so good, but j and k are never used, so they shouldn't really be here.
if (x < 2) return false;
2 isn't less than 2, so we'll continue...
else {
for (i=2; i!=x; i++) {
OK, set i = 2, and compare it to x which is 2, and... oops, i is equal to x, so we'll abandon the loop immediately...
if (x == i) return true;
else if (x % i == 0) return false;
}
}
... and fall through here, where we're not returning a value like we promised, and causing undefined behaviour.
}
So, your program is undefined (you really should switch on compiler warnings, or start listening to them).
And this happens on every number that is prime.
You can rewrite the loop like this:
for (i=2; i <= x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
or
for (i=2; i < x; i++) {
if (x % i == 0) return false;
}
return true;
Why does if (is_prime(2)) appear to work?
(Since this code is undefined, the following is largely speculation and should only be taken with suitable measures of salt.)
Often, when a function is supposed to return something but doesn't, the calling function will just grab whatever is stored in the place where the return value should have been and use that.
This value is in this case very likely not the same as the bit pattern that represents true, so will compare unequal to true, in if (is_prime(2) == true).
It will however, also very likely, not be the bit pattern that represents false either, so will be considered true in a conditional, if(is_prime(2)).

Can't seem to break a while loop on collision, hashing

I don't know why this code is not breaking out of the while loop:
int table_size = 953;
store hash_table[953];
for(int i = 0; i < table_size; i++)
hash_table[i].count = 0;
//bunch of stuff to get hash value here
while(hash_table[hashNum].data != pString || hash_table[hashNum].count != 0){
hashNum++;
if(hashNum > table_size)
hashNum = 0;
cout << hash_table[hashNum].count;
// to check the value of the count in the array, it IS 0, thus should have broken the loop
}
you probably mean:
while(hash_table[hashNum].data != pString && hash_table[hashNum].count != 0)
In your code the loop will continue if either case is true, hash_table[hashNum].count == 0 is NOT sufficient to make the clause false.
hash_table[hashNum].count being equal to zero is not sufficient to terminate the loop since you are using || ("or") between the two conditions in the termination test. If hash_table[hashNum].data is not equal to pString then the loop will continue regardless of what hash_table[hashNum].count is.
I think your loop condition should be on hashNum != 0 instead of hash_table[hashNum].count != 0.
Secondly, there should be && instead of || in your while condition.
These are wild guesses since a lot of information is missing in this question.
You should have a look at binary logic, especially De Morgan theorem
!(a && b) is equivalent to (!a) || (!b)