C++ Hashing search function stuck in endless "else" and "while" loop - c++

If the generated random number to look for does not exist in hashtable array, then programm gets stuck in endless loop in function void hashSearch(),
whereas it should just get out of the loop and output that search item is not found. The exact place in code is where these to outputs are:
cout << "stuck in else loop \n"; and cout << "stuck in while loop end \n";.
I've googled around, but can't find similar examples.
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <chrono>
using namespace std;
int arr [1000];
int arr2 [1000];
int randArrayInt, n, randSearchItem, searchInt, address, size2;
void printZeroArr();
void linearSentinelSearch();
void printHashArray();
void hashSearch();
int main ()
{
srand (time(nullptr)); //initialize random seed:
n = rand() % 900 + 100; //random integer number from 100 - 1000, length of the array
//n = rand() % 10; // random number in the range 1-10 for sanity tests, length of the array
//randSearchItem = rand() % 10 + 1;
randSearchItem = rand() % 900 + 100; //this is the number to search for
cout << "Array length is " << n << endl;
cout << "[";
for (int i = 0; i <= n; i++)
{
randArrayInt = rand() % 900 + 100;
//randArrayInt = rand() % 10 + 1; // generate random 1-10 number for for sanity tests
arr[i] = randArrayInt; // insert into array position the generated random number
cout<< " " << arr[i]; // print out array element at current loop position
}
cout << " ]\n" << endl;
printZeroArr();
}
void printZeroArr()
{
size2 = n + 1; //length of hashed array
cout << "This is the random key to search for in array: " << randSearchItem << endl;
cout << "This is the size2 length " << size2 << endl;
cout << "This is the hasharray with zeros" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
arr2[i] = 0; // insert into hasharray number 0
cout<< " " << arr2[i]; // print out hasharray element at current loop position
}
cout << " ]\n" << endl;
linearSentinelSearch();
}
void linearSentinelSearch()
{
auto start = std::chrono::high_resolution_clock::now();
arr[n + 1] = randSearchItem;
//cout << "testing arr[n + 1] is " << arr[n + 1] << endl;
int i = 0;
while (arr[i] != randSearchItem) i++;
if (i == n + 1)
cout << "Sentinel search did not found the searchitem in random array" << "\n" << endl;
else
cout << "Searchitem found in array with linearsearch at position " << i << "\n" << endl;
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
printHashArray();
}
void printHashArray()
{
//cout << "printing out 'address' value, or the modulo result: " << endl;
//cout << "[";
for (int i = 0; i <= n; i++)
{
address = arr[i] % size2;
//cout << " " << address;
while (arr2[address] != 0)
{
if (address == size2 - 1)
{
address = 0;
} else
{
address++;
}
}
arr2[address] = arr[i];
}
//cout << " ]\n" << endl;
cout << "This is the hasharray with hashitems" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
cout << " " << arr2[i];
}
cout << " ]\n" << endl; hashSearch();
}
void hashSearch()
{
auto start = std::chrono::high_resolution_clock::now();
int searchInt = randSearchItem % size2;
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem))
{
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
else
{
searchInt++;
cout << " stuck in else loop \n";
}
cout << " stuck in while loop end \n";
}
if (searchInt == 0) {
cout << "Search item not found using hashSearch" << endl;
} else {
cout << "Search item " << randSearchItem << " found using hashSearch at position " << searchInt << " in arr2." << endl;
}
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
}
Whereas it should just get out of the loop and output that search item is not found.
Search for cout << " stuck in else loop \n"; and cout << " stuck in while loop end \n";.

You want to stop your loop when you hit the end of the array: To that effect, you set the item to search for to zero:
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
But in the loop control, you don't test that. You only test the array element at the current index for zero (not found) or the item to search (found):
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem)) ...
You need an additional test:
while ((searchInt != 0) && ...) ...
It took me a while to see that you want to code an open-address hastable where a zero marks unused slots. The hash value is just the number itself. Using zero as indicator for an empty slot is not ideal: You cannot store numbers whose hash code modulo the table size is zero.
I'd also code this with a non-void function where the return value is the index or some unambiguous value meaning "not found", perhaps -1. (Alternatively, you can return a pointer to the found item or NULL if the item isn't found -- after all, the index in the hash array is part of the hash table's internals and non concern to the caller.)
Then you can use early returns:
int hashSearch(const int *arr2, int size2, int item)
{
int i = item % size2;
for (; i < size2; i++) {
if (arr2[i] == -1) break; // -1 indicated unused space
if (arr2[i] == item) return i; // return index of item
}
return -1; // not found!
}
But what do you do if there is no room for a further element when you have a hash code close to the array size? You will need to add extra space at the end or you'll need to wrap around. Perhaps that is what you wanted to achieve by setting the index back to zero. In your case, ther array is full, so there are no zeros that could serve as loop-breaking criterion. You will have to find another criterion. You could ensure that there are zeros by making the hash table 30% or so bigger than the number of entries. Or you could try to detect whether the index has come full circle to the original index.
As already pointed out to you in comments: Try to use function arguments and local variables rather than puttin everything into global space. Also, the chaining of function calls, where the last thing in a function is to call the next one is strange. It's probably better to put all sequential calls into main.

Related

C++ Checking while condition with user input array

I'm student in high school and I wanna to make simple game with guessing random number and I had problem with user inputed array while I need to check the condition.
When it comes to checking condition it says there wasn't declared i.
Below I leave code.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
int PlayerAns[200];
int iNumSecret, iNumGuess;
int iWrongAns = 0;
srand(time(NULL));
int iNumMax = 100;
iNumSecret = rand() % iNumMax + 1;
cout << "========== Simple Game =========== "
<< "\n";
do
{
for (int i = 0; i < 100; i++)
{
cout << "Guess the number od 1 do " << iNumMax << "\n";
cin >> PlayerAns[i];
if (iNumSecret < PlayerAns[i] && PlayerAns[i] >= 0 && PlayerAns[i] <= 100)
{
cout << " - Secret number is lower ! "
<< "\n";
}
else if (iNumSecret > PlayerAns[i] && PlayerAns[i] >= 0 && PlayerAns[i] <= 100)
{
cout << " - Secret number is higher ! "
<< "\n";
}
else if (PlayerAns[i] < 0 || PlayerAns[i] > 100)
{
cout << " - Number is out of scope ! "
<< "\n";
iWrongAns++;
}
}
}
while (iNumSecret != PlayerAns[i]);
{
cout << "--- You get it !!!"
<< "\n";
cout << PlayerAns << "\n";
cout << "You guess number out of scope that many times: " << iWrongAns << "\n";
}
return 0;
}
The variable i is defined only inside the for loop in that case.
If you wanted to, you can define i before the do while loop, and then use it in the for loop like so:
for(i = 0; i < 100; i++) {
...
}
Suggestion:
You can try not using the for loop and make the PlayerAns an integer instead of an array.

How to call a function to search an element an a 2D array?

I'm trying to get my homework done, but there is something is going wrong.
If a 2D array was in the main function, and I want to call a function, which its task is searching for an element in the 2D array, which the user enters the wanted element in the main function. If the wanted element was found, call a function to find its factorial then print the result in the main function, otherwise, call another function to show that the wanted element was not found.
I've tried the lines of code using Visual Studio 2019 as well as Dev C++.
My program does about 13 tasks which I organized them in a Switch Statement,
and the case of doing that task is Case number 9.
But once I enter the element I want to search in the console.
if the element existed in the array, the output always shows up like this:
"
Number 3 Found at position: 4
Factorial of 3 is: 6
3
"
whether the user entered 3 or else number.
Even if it was not found, the output is the same.
#include <iostream>
using namespace std;
// declaring a function to search within B1 array.
int search_B1(int[][3], int, int);
// declaring a function to find the fatorial of the found element.
int fact_num(int);
// declaring a function to print out a searching error.
void search_error();
// This is the main function. Program execution begins and ends here.
int main()
{
int B1[3][3], i, j;
cout << " - Please enter the elements of B1 array: \n";
for (i = 1; i <= 3; i++)
{
for (j = 1; j <= 3; j++)
{
cout << "B1[" << i << "]" << "[" << j << "] = ";
cin >> B1[i][j];
}
}
...
...
...
case 9:
{
int num;
cout << endl << " Enter the element to search in B1 array: ";
cin >> num;
cout << endl << search_B1(B1, 3, num) << endl;
break;
}
}
/**********************************************************************/
// This function is called when user inserts '9'
int search_B1(int B1[][3], int num , int)
{
int i, j, flag = 0;
for (i = 1; i <= 3; i++)
{
for (j = 1; j <= 3; j++)
{
if (num == B1[i][j])
{
flag = 1;
cout << " Number " << num << " Found at position: " << j + 1 << endl;
fact_num(num);
break;
}
}
}
if (flag == 0)
{
search_error();
}
return num;
}
/**********************************************************************/
// This function relates to ' search_B1 ' function.
int fact_num(int num)
{
int fact = 1, f;
for (f = 1; f <= num; f++)
{
fact *= f;
}
cout << " Factorial of " << num << " is: " << fact;
return fact;
}
/**********************************************************************/
// This function relates to ' search_B1 ' function.
void search_error()
{
cout << " The wanted number was not Found in the array!";
}
/**********************************************************************/
I expected the output of searching will be like this:
Example:
If the user entered the elements of the array as '1 2 3 4 5 6 7 8 9' and searched about the element '9'
IF THE WANTED ELEMENTS WAS FOUND:
the output will be :
"Number 9 Found at position: 4
Factorial of 9 is: 362880"
IF THE WANTED ELEMENTS WAS NOT FOUND:
the output will be :
"The wanted number was not Found in the array!"
You have undefined behaviour filling and searching the array
for (i = 1; i <= 3; i++) // B[3][j] is never an element
{
for (j = 1; j <= 3; j++) // B[i][3] is never an element
Array indices start from 0. If you want to display indices from 1, do arithmetic in the output
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
std::cout << "B1[" << (i + 1) << "]" << "[" << (j + 1) << "] = ";
std::cin >> B1[i][j];
}
}

How can I get the array to show the previous list of array content before the next input?

I need the user input to be saved into my array and then output the array before the user inputs the next time. I have been moving things around different ways but cannot seem to get them to perform properly. I tried to cut down the code to the two functions I am having issues with.
void PlayGame()
{
const int HighestNum = 50;
const int LowestNum = 1;
int RandomNumber = LowestNum + rand() % HighestNum; //set for better random results
cout << "Guess the random number between " << LowestNum << " and " << HighestNum << "!\n\n";
const int attempts = 15;// limits the attempts to guess the random number to 15
int Guess [attempts] = {};
cout << "Enter your guess " << endl;
for (int count = 0; count < attempts; count++)
{
cin >> Guess[count];
int z = RandomNumber, y = Guess[count], r;
r = reviewGuess (z,y);//calling the function that determines the results
switch (r)//switch statement for function results, letting the user know if they matched the number, if the number is higher, or lower
{
case 0:
cout << "You Win!!" << endl;
cout << "\n";
cin.get();
return;
case 1:
cout << "The number is higher than your guess" << endl;
break;
case -1:
cout << "The number is lower than your guess" <<endl;
break;
}
if (count == 15)
{
cout << "Sorry, no guesses remain. The random number was... " << RandomNumber << "!";//so the user can see the random number at the end of their attempts
cout << "\n";
cin.get();
Again();
}
}
return;
}
int DisplayGuess(int member[])
{
for(int i = 0; i < 15; ++i)
cout << "\nGuess " << i + 1 << ": " << member[i];
cout << endl;
return;
}
Try this inside your loop
if(count > 0)
{
for (int j= 0; j < count; j++)
{
cout<<Guess[j];
}
}
Call DisplayGuess() in the first line of the for loop. Since the first you time you call it your array is empty, it shouldn't output anything.
So,
for (int count = 0; count < attempts; count++)
{
DisplayGuess(Guess[count]);
cin >> Guess[count];
int z = RandomNumber, y = Guess[count], r;
r = reviewGuess (z,y);//calling the function that determines the
results
. . . . . .

Output (at most) 4 vector Elements in a Row

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
#include <conio.h>
using namespace std;
int main()
{
cout << "Enter the numbers: " << endl << "Write eof() when you want to end" << endl;
int x;
vector<int> num;
//enter numbers till eof() is encountered
while (cin >> x) {
num.push_back(x);
}
//sort the vector
sort(num.begin(), num.end());
//get size of the vector
typedef vector<double>::size_type vec_sz;
vec_sz size = num.size();
//loop to print 4 numbers according to size
for (auto i = 0; i < size; i++)
{
cout << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
cout << endl;
//<< " " << num[i + 1] << " " << num[i + 2] << " " << num[i + 3] <<
}
_getch();
return 0;
}
I want to print 4 numbers at a time of a vector of int's. When I tried to print the vector by doing i+=4 in the for loop, the compiler complained that 'i' was going over the size of the vector and the program crashed.
Right now, what I have is works, but I find it really boring the way it's implemented right now and there must be a nice way to do it.
So my questions are -
1) How can I tidy up the code more?
2) When using a loop, how does the compiler access the memory in which vector contents are stored?
3) How to implement error checking so that the loop variable does not access elements beyond the vector size?
for (int i = 0; i < size; i++)
{
cout << num[i];
if ((i % 4) == 3)
cout << endl;
else
cout << " ";
}
if ((size % 4) != 0)
cout << endl;
One solution could be,
for( int i = 0; i < size; ++i ) {
int nextNumber = i + 1; // Just so you don't mix up the index
if ( ( nextNumber % 4 ) == 0 ) {
std::cout << num[ i ] << std::endl;
}
else {
std::cout << num[ i ] << ' ';
}
}
This allows you to easily change to other sizes by changing only one number. (ie, from 4 to 5, etc )
My entry to this competition is using a free function to your aid:
template <typename RAN_IT>
RAN_IT four_or_last(RAN_IT begin, RAN_IT end){
for (RAN_IT it = begin; it != begin + 4; it++){
if (it == end)
return end;
}
return begin + 4;
}
The loop can then be described as:
for (auto it = num.begin(); it != num.end(); /*inc in inner loop*/) {
for (auto in = it; in != four_or_last(it, num.end()); in++) {
std::cout << *in << " ";
}
it = four_or_last(it, num.end());
std::cout << std::endl;
}

add results of a for loop after each iteration

I‘m having trouble with my for loop. I have a basic 2 times table that goes up from 1 to 10. (see below). I'm trying to add the result so that after every loop, allResult displays the values of all results added. it needs to show all results added after every loop. and I don't know how to go about it. A better description is the desired outcome commented in the code.
my Code...
int main(){
int allResult;
for( int i = 1; i < 11; i++)
{
int result = 2*i;
cout << 2 << " times " << i << " = " << result << endl;
// I want allResult to store results added. so after first loop, result = 2 so allResult = 2
// after second loop, result = 4. so allResult should be 6. (results from 1 and 2 added)
// after third loop, result = 6 so allResult should be 12. (results from 1, 2 and 3 added)
// I'm trying to apply this to something else, that uses random numbers, so i cant just * result by 2.
}
system("pause");
}
int allResult = 0;
for( int i = 1; i < 11; i++)
{
allResult += 2*i;
cout << 2 << " times " << i << " = " << 2*i << endl;
}
int allResult = 0;
for( int i = 1; i < 11; i++)
{
int result = 2*i;
cout << "2 times " << i << " = " << result << endl;
allResult += result;
cout << "allResult: " << allResult << endl;
}
int main()
{
int allResult=0;
for( int i = 1; i < 11; i++)
{
int result = 2*i;
allResult=allResult+result;
/*Initially allResult is 0. After each loop iteration it adds to its previous
value. For instance in the first loop it was allResult=0+2,
which made allResult equal to 2. In the next loop allResult=2+4=6.
Third Loop: allResult=6+6=12. Fourth loop:allResult 12+8=20 and so on..*/
cout << 2 << " times " << i << " = " << result << endl;
}
system("pause");
}