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

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)

Related

How can I create an "isalnum" equivalent?

I was wondering if I am writing correct "isalnum" logic. This program is checking if the string is a palindrome or not and when I input the string "race a car", it keeps saying it is true, i.e. it's a palindrome.
bool isPalindrome(string s) {
for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
while ((s[i] < 'a' || s[i] > 'z') && (i < j) ||
(s[i] < 'A' || s[i] > 'Z') && (i < j) ||
(s[i] < '0' || s[i] > '9') && (i < j))
i++;
while ((s[j] < 'a' || s[j] > 'z') && (i < j) ||
(s[j] < 'A' || s[j] > 'Z') && (i < j) ||
(s[j] < '0' || s[j] > '9') && (i < j))
j--;
if (toupper(s[i]) != toupper(s[j])) return false;
}
return true;
}
No, your logic is not correct, well, at least not for all the character sets that C++ can use. In ASCII, the letters of the alphabet are in contiguous blocks, so something like
(s[i]<'A'||s[i]>'Z')
works just fine. The issue with that is that ASCII isn't the only character set C++ supports. The most common example to counterpoint ASCII is EBCDIC which has the characters {, }, and \ in between A and Z.
One thing that is guaranteed though is that 0 through 9 are contiguous in all character sets that C++ supports so it's always legal to text if a character is a number using
if (char_var >= '0' && char_var <= '9')
Assuming contiguous alphabets (which isn't going to hold in reality), your logic is broken by the fact that you're doing multi-range checking, where disqualification in one range is still qualified in another.
Specifically, this:
while((s[i]<'a'||s[i]>'z')&&(i<j)||(s[i]<'A'||s[i]>'Z')&&(i<j)||(s[i]<'0'||s[i]>'9')&&(i<j))i++;
Now, consider this: suppose a[i] is in 'a'..'z', so the first range check will be false. But, if that's the case then it is NOT in 'A'..'Z' and is certainly not in '0'..'9'. Since both of those tests result in true, the loop advances i and continues on. As your loop is written, so long as the character is not in at least one of those ranges the loop continues. Since the ranges are mutually exclusive, there will ALWAYS be at least one the current character is not within. That OR separating condition is wrong. It shouldn't be not-in one of those ranges; it should be not-in ALL of those ranges. Thus.. AND is appropriate.
Short work with a debugger will tell you the very first pass of your outer-for-loop is advancing i all the way to j. The second loop is skipped because j and i are already equal, and since s[i] == s[j] is definitely true when i == j, the result is true.
Short version: your loop conditions are broken, even on contiguous character sequence platforms.
The loop you're more inclined to succeed with would be something like:
while( (i < j) && (s[i]<'a'|| s[i]>'z') && (s[i]<'A'||s[i]>'Z') && (s[i]<'0'||s[i]>'9') )
i++;
I leave the other loop and consideration for not doing any of this because of encodings where it will not work as an exercise for you.

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

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

continue program in c++

my program is
#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int exit;
while(1==1)
{
float a,b,c;
printf("Enter length(in metre)");
scanf("%f",&a);
printf("Enter width(in metre)");
scanf("%f",&b);
printf("Enter height(in metre)");
scanf("%f",&c);
if(5.919<a<=12.056 && 2.340<b<=2.347 && 2.380<c<=2.648)
{
printf("40' high cube \n");
}
else if(a<=5.662 && 2.340<b<=2.438 && c<=2.16)
{
printf("20' open top");
}
else
{
printf("40' flat rack");
}
cout << "Would you like to exit?(Yes/No)"<<endl;
cin >> exit;
if(exit == 1)
{
break;
}
}
return 0;
}
But, the code is given wrong asnwers.No matter whatever feed i give..it is selecting 40" high cube
Also,I want to input yes/no to continue,instead of 1. How should I do it?
Unfortunately, while the following is valid syntactically, it does not do what you expect:
5.919<a<=12.056
This is parsed as (5.919 < a) <= 12.056 and works as follows: a is compared to 5.919, and the result of that comparison (0 or 1) is compared to 12.056. Since both 0 and 1 are less than 12.056, the overall expression always evaluates to 1.
To fix, rewrite it as:
5.919 < a && a <= 12.056
The same goes for all the other similar expressions.
For input yes/no, You can use this way..
char exit;
// in while loop waiting for user input
exit = getch();
if(exit == 'y' || exit == 'Y' )
break;
//else again go for input.
This line isn't doing what you think.
if(5.919<a<=12.056 && 2.340<b<=2.347 && 2.380<c<=2.648)
to do what you seem to want, you would need to change it to:
if(5.919<a&& a<=12.056 && 2.340<b&& b<=2.347 && 2.380<c&& c<=2.648)
same for this line:
else if(a<=5.662 && 2.340<b<=2.438 && c<=2.16)
that needs to be changed to:
else if(a<=5.662 && 2.340<b && b <=2.438 && c<=2.16)
When you write this:
2.340 <b <= 2.347
what C and C++ understand is (2.30 < b) <= 2.347 and that is always true (1 in C) for all values of b because (2.30 < b) is either 0 or 1, which is always less or equal than 2.347. This is arcane and backwards, but it is how C and C++ see the world. I'm sure that this will only bite you once, and this was your turn.
Also, it is bad practice to mix printf and scanf with cin and cout, make a choice about how you want to do your I/O and stick to it, mixing them brings other subtle bugs that are difficult to troubleshoot.
For the final part of your question, you can do:
#include<stdio.h>
#include<string.h>
int main(void){
char answer[16];
printf("Yes or No\n");
scanf("%s",answer);
if (strncmp(answer,"Yes",3)==0){
printf("yes\n");
}else{
printf("no\n");
}
}
For the second part question :
Change the condition to Y/N instead of 1 and 0. Use character data type, or string or anything similar. And then you can compare the input with "exit".

Are semicolon-terminated if-statements good coding practice?

I am looping i, j, k and n. I want a statement to execute except when k == j and n == k.
If I use the code like this:
if (k != j && n != i)
//statement
The statement will not execute in two cases:
When k != j when n == j.
When k == j when n != j. (which is not what I need)
So I used a code like this:
if (k == j && n == i)
;else
//statement
By this code the statement will successfully execute except when k == j && n == i.
Is semicolon-terminated if-statements is a good way of coding in C++?
No it's not a good way of coding. The usual way is to use ! to invert the logic:
if(!(k==j && n==i))
//statement
Or you could use De Morgan's Law to invert the logic:
if(k!=j || n!=i)
//statement
Your problem is that you're negating the condition incorrectly. You should just do:
if (!(k==j && n==i))
// statement
Or, by De Morgan's laws:
if (k != j || n != i)
// statement
... is a good way of coding?
No.
You should write
if (!(k == j && n == 1))
{
//statement
}
Putting a semicolon after an if, for, or while is almost always wrong. It is highly unexpected and makes reading your code very difficult.