I have been struggling with the output of a linear search algorithm for a bit of time now. I have the function that searches the list and returns the position, either -1 if it is not found, or the numeric value of where the matching number was found. Any suggestions on how to get this to output correctly?
The output needs to search through testList, see if that number is in stdList, and give its position
Number 1 (34) was located in position 15.
Number 2 (74) was not in the file.
Number 3 (56) was not in the file.
Number 4 (103) was located in position 75.
etc.
Here is the main section of code that I am having problems with.
ARRAY_STANDARD is referring to the size of the array stdList.
stdList is the array being compared against
Position is what is being returned by the function searchList()
testList is referring to the array that is being compared to stdList
value is the element that we are searching for
//Outputs
if (position == -1)
cout << "Number " << testCount+1 << "(" << testList << ")" << " was not in the file." << endl;
else
cout << "Number " << testCount+1 << "(" << testList << ")" << " was located in position " << value << endl;
}
int searchList(int stdList [], int numElems, int value)
{
int index=0;
int position = -1;
bool found = false;
while (index < numElems && !found)
{
if (stdList[index] == value)
{
found = true;
position = index;
}
index++;
}
return position;
}
You seem to have lost a few lines of code in the last edit. What you want to do (pseudo code) is this:
for each element in testList: <<<<< this is the for statement you lost
position = findElement(element, stdList) <<<<< this is the function you were not calling
if(position < 0):
print "not found"
else:
print "found element " element " at position " position
Take it away...
You should change your method in following way:
int searchList(int stdList [], int numElems, int value)
{
int index=0;
while (index < numElems)
{
if (stdList[index] == value)
{
return index;
}
index++;
}
return -1;
}
int searchList(int stdList [], int value)
{
for(int i = 0, length = sizeof(stdList); i < length; ++i)
{
if (stdList[i] == value)
return i;
}
return -1;
}
Successful output.
int results;
for(int i = 0; i < 22; i++)
{
results = searchList(stdList, ARRAY_STANDARD, testList[i]);
if (results == -1)
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was not in the file." << endl;
else
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was located in position " << results+1 << endl;
}
Related
Just to provide background, I'm trying to write a function in C++ that takes a vector of ints and a particular int, and removes all of the elements of the vector in place that match the particular int, while returning the number of times it appears.
I'm not asking for help solving the problem. I am stuck trying to figure out why the wrong elements are being erased. Here is the code:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output+=1;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}
Here is what I'm using to test it:
int main() {
vector<int> firstOne = {3,2,2,3};
cout << removeElement(firstOne,2) << "\n";
firstOne = {3,2,2,3};
cout << removeElement(firstOne,3) << "\n";
}
The output is supposed to be {3,3} and then {2,2} but it's {3,3} twice. Not only that, but the whole thing crashes when I try to test it with a vector with only 2 elements. I suspect there is a gap in my understanding of how vectors work. Can anyone explain to me what I'm doing wrong?
It is better to use erase-remove idiom
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
// remove if moves elements "to be removed" in the end
auto newend = std::remove_if(nums.begin(), nums.end(), [&](int element){
cout << element << " " << i << " " << (element == val) << "\n";
i++;
if(element == val) {
output++;
return true; // if true, element will be removed
}
return false; // if false, element will not be removed
});
nums.erase(newend, nums.end());
cout << "---------------\n";
return output;
}
Besides the problems suggested in the comments that you just fixed, your code works fine. You are also not updating output anywhere so the function always returns 0 instead of the number of times the int appears in the passed vector. I edited your function a little and it's good to go:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output++;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}
Below I have my two functions which are, when when insertItem calls findIndex producing a segmentation fault. For some reason this happens when the value is returned. (I will include the cout statements so that it is easy to see exactly where this error happens). I am trying to locate the index of a value which is not in the list so -1 should be returned but never does. The output is below.
template <class ItemType>
int SortedList<ItemType>::findIndex(ItemType item) {
cout << "Entering findIndex function" << endl;
int first = 0;
int last = length-1;
int middle;
bool found = false;
while(!found) {
middle = (first+last)/2;
cout << "In findIndex, this is middle: " << middle << " and this is the item: " << item << " and this is the length: " << length << endl;
if(info[middle] == item) {
cout << "In findIndex found is now true" << endl;
found = true;
}
else if(item < info[middle])
last = middle-1;
else// if(item > info[middle])
first = middle+1;
if(first > last)//else// if(first > last)
break;
}
cout << "About to exit and return value from findIndex function" << endl;
if(found == true) {
cout << "findIndex Function: the index of the found value was " << middle << endl;
return middle;
}
else {
cout << "findindex Function: -1 was returned" << endl;
return -1;
}
}
template <class ItemType>
void SortedList<ItemType>::insertItem(ItemType item) {
cout << "Inside insertItem function, length: " << length << endl;
if(findIndex(item) != -1)
cout << "**Item already in the list" << endl;
else if(length == Max_Items)
cout << "**There is no room in the list" << endl;
else {
cout << "before the try" << endl;
try{
cout << "This is length at the start of the insertItem function: " << length << endl;
if(length == 0) {//if the list is empty item becomes the first item in the list \
cout << "This is right after length==0 in insertItem function" << endl;
info[0] = item;//was this->inf...
length++;
cout << "This is length right after incrementing it up" << length << endl;
}
else {//its not the first item in the list
for(int i = 0; i <= length; i++) {
cout << "This is the length and i respectively right inside the for in insertItem" << length << " " << i << endl;
if(i == length) {
cout << "this is where i == length" << endl;
info[i] = item;
length++;
break;
}
if(info[i] < item)
continue;
//inserting the item where it needs to go
for(int p = length; p > i; p--) {//was >=
info[p] = info[p-1];
}
//item = info[i];
info[i] = item;
length++;
break;
}
}
}catch(...) {cout << "**insertItem failed" << endl;}
}
cout << "This is length at the end of the insert item function: " << length << endl;
}
output:
...
Inside insertItem function, length: 0
Entering findIndex function
In findIndex, this is middle: 0 and this is the item: Name: Eman ID: 81012 and this is the length: 0
About to exit and return value from findIndex function
findindex Function: -1 was returned
Segmentation fault (core dumped)
~$:
So even the print saying -1 was returned is hit but nothing ever gets back to the original function. I am not sure as to what could cause a seg fault in this area. Could this return do it?
The following loop:
for(int p = length; p > i; p--) {
info[p] = info[p-1];
probably writes to 1 index past the length of the array, because valid array indexes probably range from 0 to length - 1.
A write to an illegal memory location can corrupt the stack, and this is likely to manifest as a crash when returning from a function.
Still, you really need to start using a debugger.
This is just for one of the exercises in my book, where it asks me to search through a vector for a specific name and return a score from another corresponding vector once the name has been found. If the name isn't found, it'll return the message "Name not found!"
int main()
{
vector<string>name;
vector<int>score;
string n = "0";
int s = 0;
while (cin >> n >> s && n != "NoName") {
for (int i = 0; i < name.size(); ++i)
if (n == name[i]) {
cout << "Error! Name is already in database!" << '\n';
break;
}
name.push_back(n);
score.push_back(s);
}
for (int i = 0; i < name.size(); ++i)
cout << "(" << name[i] << " " << score[i] << ")" << '\n';
cout << "Type in a name to find the score" << '\n';
string search = "0";
cin >> search;
for (int i = (name.size() - 1); i >= 0; i = i - 1) {
if (search == name[i])
cout << "Score is " << score[i] << '\n';
else
cout << "Name not found!" << '\n';
}
}
The above is my code. The only problem I'm having is that it'll loop through the vector and return "Name not found!" multiple times because it searches each individual position. I only want it to return the message once the whole vector has been searched. I've tried googling it, and I've found something like this:
#include <algorithm>
...
std::vector<std::string>::const_iterator it = std::find(vec.begin(), vec.end(), "some string");
if (it != vec.end())
{
std::cout << "Found '" << *it << "' in the vector." << std::endl;
}
which, unfortunately, I don't quite understand.
std::vector<std::string>::const_iterator it = std::find(vec.begin(), vec.end(), "some string");
This searches for the string "some string" in the range [vec.begin(), vec.end()[ and returns an iterator to the element in the range if it is found. If it is not found, the end of the range (vec.end()) is returned.
So if (it != vec.end()) is saying if (the string was found).
Regarding your original code and the unwanted prints, there are several ways of fixing that. One way would be:
int i;
for (i = (name.size() - 1); i >= 0; i = i - 1) {
if (search == name[i]) break; // exit the loop as soon as the element is found
}
if (i >= 0) {
cout << "Score is " << score[i] << '\n';
} else {
cout << "Name not found!" << '\n';
}
std::vector<std::string>::const_iterator it = std::find(name.begin(), name.end(), name_to_search);
Please refer to function template std::find. It searches range [name.begin(), name.end()) and compare every element with "name_to_search". It returns an iterator to the first element that is equal to "name_to_search".
If no elements match, the function returns name.end().
P.S. You can also go through the range like this:
int i = 0;
for (; i < name.size(); i++) {
if (search == name[i]){
cout << "Score is " << score[i] << '\n';
break;
}
}
if(i == name.size()){
cout << "Name not found!" << '\n';
}
int listRecSearch(list<int>list, const int data)
{
if (list.empty())
{
cout << "The number is not in the list, try again..." << endl;
return -1;
}
else if (list.back() == data)
{
// cout << "list.size(): " << list.size() << endl;
list.pop_back();//I needed the index begins from 0 instead of 1
return list.size();
}
else
{
// cout << "list.back(): " << list.back() << endl;
list.pop_back();
listRecSearch(list, data);
}
}
//funtion used
int main()
{
list<int>list = listGenerator(size);//generate a list with 20 random numbers.
cout << "Specify the element to be searched for: ";
cin >> data;
int position = listRecSearch(list, data);
if (position > -1)
cout << "\nFind the element at position: " << position << endl;
}
The function listRecSearch was able to display correct list.size() value and correct pop_back values. But once it returned, it always return a garbage value. I figured there were steps were still went through after return, but I can't see where and how.
There exists a code path which does not return a value. listRecSearch(list, data); should become return listRecSearch(list, data);.
I used the code from this post, How to display binary search tree in console properly?. It complies fine on my IDE, but it doesnt print out anything so it basically shows nothing. I want it to print out in the tree structure like the post mentioned I posted here. I think I have the code typed wrong for 3rd argument for the printLevel function in int main(). Would char* x = " " work fine? It does give warning message, but I'm not sure if I do it right.
string printLevel(Node *pRoot, int level, string gap)
{
if (level == 1)
{
if (pRoot == 0)
{
cout << ".. printLevel - " << pRoot << ": " << gap << "-" << gap << "\n";
return gap + "-" + gap;
}
stringstream out;
out << pRoot->data;
//cout << ".. printLevel - " << pRoot << ": " << gap << pRoot->data << gap << "\n";
return gap + out.str() + gap;
}
else if(level > 1)
{
string left = printLevel(pRoot ? pRoot->pLeft : 0, level - 1, gap);
string right = printLevel(pRoot ? pRoot->pRight : 0, level - 1, gap);
//cout << ".. printLevel - " << pRoot << ": '" << left << "', '" << right << "'\n";
return left + " " + right;
}
else return
"";
}
void printLevelOrder(Node* pRoot, int depth)
{
for (int i = 1; i <= depth; i++)
{
string gap = "";
for (int j = 0; j < pow(2, depth - i) - 1; j++)
{
gap += " ";
}
string levelNodes = printLevel(pRoot, i, gap);
cout << levelNodes <<endl;
}
}
in the main
Node *pRoot = NULL;
int inputValue = 0;
char* gap = " ";
// Loop to read in input values
cout << "To build a BST enter positive integer values, followed by -1 \n";
while (inputValue != -1)
{
cin >> inputValue;
if( inputValue != -1)
{
insertIntoTree( pRoot, inputValue);
}
}
cout << endl;
// Display the tree
printLevel(pRoot, inputValue, gap);
printLevelOrder(pRoot, inputValue);