How can I find position of the element inside an array? I have following piece of code where I need to test if the element is at some position, however it is not working as expected. I need your help about it.
string knockemdead[4], bashemup[4], street[4], newyork[9999];
string car;
if (knockemdead[i] == car)
{
if (knockemdead[i].find(1)){ // tried knockemdead[i] = knockemdead[1] and knockemdead[i].at(1) but all it did was nothing
fare = 10;
}
else if (knockemdead[i].find(2))
{
fare = 15;
}
else if (knockemdead[i].at(3) || knockemdead[i].at(4))
{
fare = 25;
}
if cont is some form of container of T, and obj is an object of T,
and T implements ==, then:
auto iter = find( begin(cont), end(cont), obj );
will return either an iterator to the object (or something that compares equal to it),
or end() if no such object exists in the container.
if the container is random-access (vector,array etc), then:
auto idx = iter - begin(cont);
will return the index of the found object
find is declared in <algorithm>, and namespace std is assumed to be accessible
A different solution would be to do it 'manually'
int idx;
for(idx=0; idx<SZ; ++idx)
if( cont[idx] == obj ) break;
you need to put the size of the container in SZ prior.
idx will have the value SZ if no object was found, or the index if it was
You can make a method that finds the position.
Example
int findElementPositionInArray(TYPE[] array , TYPE elementValue){
for(int i=0 ; i<array.length ; i++){
if(array[i]==elementValue){
return i;
}
//let's also treat the case in which the element is not found in the array
//this way we can test the output (we know that if this method returns -1
//the element is not in the array
return -1;
}
}
So just replace TYPE with your desired type (String for your case as I can see) and call this method .
For more complex data types (example your own class that might contain multiple primitive typess) be sure to properly override the "==" operator.
Might contain errors , I don't have an IDE to test this right now.Hope it helps
Related
I need to write a function which compares every element of an std::vector<std::shared_ptr<Shape >> shapes_ to every other element determine if the shapes overlap, and then remove one of the overlapping shapes if so. Here is what I've got currently:
class Shape {
public:
...
virtual bool overlaps(const std::shared_ptr<Shape>&) const = 0;
...
};
class Square : public Shape { ... } ;
class Circle : public Shape { ... } ;
And utilizing these classes:
std::vector<shared_ptr<Shape>> shapes_;
// ... some code populates the array
for (auto& shape : shapes_) {
// Compare to every other shape
for (unsigned long j = 0; j < shapes_.size(); j++) {
// If they overlap and they aren't the same shape
if (shape->overlaps(shapes_.at(j)) && shape!=shapes_.at(j)) {
shapes_.erase(shapes_.begin() + j);
}
}
}
However I keep running into problems where I'm iterating over a null (removed) element, or beyond the end of the array or something. I keep re configuring it this way or the other but one of these problems keeps popping up.
What would be considered the most sensible, clean way to deal with a problem where you're comparing every element of a vector to every other element, and in the process sometimes deleting some elements?
Additionally, what if I would like to print some information about each overlap that is found, and the shape that is removed?
You can use erase-remove idiom:
auto it = vec.begin();
auto end = vec.end();
while( std::distance( it, end ) > 1 ) {
auto condition = [shape=*it]( const auto &other ) { return shape->overlaps( other ); };
end = std::remove_if( ++it, end, condition );
}
vec.erase( end, vec.end() );
this lambda syntax requires C++14, but it can be easily modified to work with C++11 if necessary (by introducing temp variable shape before lambda for example, or capturing it by value not reference).
I am trying to find out what is the easiest way to get a subset of C-Array if there are start and end points give.
Example: I have a class Trip:
class Trip
{
private:
char* final_destination;
char* description;
public:
//all constructors, operators and stuff
};
And, lets say I have an array of Trips:
Trip* trips = new Trip[10];
I am trying to write a function that takes the Trip array, starting point(given destination), end point(given destination) and return a subset of type Trip*.
E.g.
Trip* GetSubTrip(Trip* trips, char* start_point, char* end_point)
{
//Logics that returns Trip*
}
In other words, If I had:
[{"London", "Big Ben"}, {"New York", "Manhattan"}, {"Paris", "Eifell Tower"}, {"Moscow", "Lots of fun"}]
That would be the Trip* trips and "New York" as a start and "Moscow" as an end passed to the GetSubTrip I am trying to make it return Trip*.
And the return has to be:
[{"Paris", "Eifell Tower"}, {"Moscow", "Lots of fun"}]
What I do is:
In an integer counter I get the length between start and end
Create a new pointer Trip* and assign it with length of the counter from 1
Iterate over the 'trips' parameter and keeping a track if I am between start and end and if yes-> add the object to the result else procceed further.
But this is a lot of code. I am sure that there is much easier way.
EDIT:
It has to be done WITHOUT the use of VECTOR!
Using std::vector:
std::vector<Trip> route;
bool go = false;
for( int i=0; i<tripsSize /* trips[i] != TRIP_GUARD */; ++i )
{
if( go )
{
route.push_back( trips[i] );
if( trips[i] == end )
break;
}
else if( trips[i] == start )
go = true;
}
Why use std::vector? You don't have to keep the size of resulting array. You may modify it freely and conveniently. You don't have to worry about memory allocation for Trip objects.
In case you don't want to use std::vector you would need some sort of guard for both of your arrays (input and output one ) or to pass length of the array.
Without std::vector:
Trip * route;
int tripsNum;
int startNum, endNum;
for( int i=0; i<tripsSize /* trips[i] != TRIP_GUARD */; ++i )
{
if( trips[i] == start )
startNum = i;
else if( trips[i] == end )
{
endNum = i;
break;
}
}
tripsNum = endNum - startNum;
route = new Trip[ tripsNum ];
for( int i=startNum + 1, j=0; i<=endNum; ++i, ++j )
route[ j ] = trips [ i ];
Since you are using C++ you can consider using std::vector class instead of raw C arrays.
For raw C arrays you would need to keep the size (number of elements) of the array somewhere.
If you prefer arrays the solution depends on whether you are going to modify the original array/sub-arrays.
If you don't modify the Trips array, you can get the pointer to the sub-array with pointer arithmetic:
return trips + 2;//The returned pointer points to {"Paris", "Eifell Tower"}
You would also need to store the size of the sub-array.
If you do need to modify the original array (and/or sub-array), then you would have to create a copy (I would strongly suggest using vectors in that case). You might find this useful:
Best way to extract a subvector from a vector?
I need some assistance with a C++ project. What I have to do is remove the given element from an array of pointers. The technique taught to me is to create a new array with one less element and copy everything from the old array into the new one except for the specified element. After that I have to point the old array towards the new one.
Here's some code of what I have already:
I'm working with custom structs by the way...
Data **values = null; // values is initialized in my insert function so it is
// populated
int count; // this keeps track of values' length
bool remove(Data * x) {
Data **newArray = new Data *[count - 1];
for (int i = 0; i < count; i++) {
while (x != values[i]) {
newArray[i] = values[i];
}
count -= 1;
return true;
}
values = newArray;
return false;
}
So far the insert function works and outputs the populated array, but when I run remove all it does is make the array smaller, but doesn't remove the desired element. I'm using the 0th element every time as a control.
This is the output I've been getting:
count=3 values=[5,6,7] // initial insertion of 5, 6, 7
five is a member of collection? 0
count=3 values=[5,6] // removal of 0th element aka 5, but doesn't work
five is a member of collection? 0
count=4 values=[5,6,5] // re-insertion of 0th element (which is stored in
five is a member of collection? 0 // my v0 variable)
Could anyone nudge me in the right direction towards completing this?
First of all, your code is leaking memory like no good! Next you only copy the first element and not even that if the first element happens to be the one you want to remove. Also, when you return from your function, you haven't changed your internal state at all. You definitely want to do something along the lines of
Data** it = std::find(values, values + count, x);
if (it != values + count) {
std::copy(it + 1, values + count, it);
--count;
return true;
}
return false;
That said, if anybody taught you to implement something like std::vector<T> involving reallocations on every operation, it is time to change schools! Memory allocations are relatively expensive and you want to avoid them. That is, when implementing something like a std::vector<T> you, indeed, want to implement it like a std::vector<T>! That is you keep an internal buffer of potentially more element than there are and remember how many elements you are using. When inserting a new element, you only allocate a new array if there is no space in the current array (not doing so would easily result in quadratic complexity even when always adding elements at the end). When removing an element, you just move all the trailing objects one up and remember that there is one less object in the array.
Try this:
bool remove(Data * x)
{
bool found = false;
// See if x is in the array.
for (int i = 0; i < count; i++) {
if (x != values[i]) {
found = true;
break;
}
}
if (!found)
{
return false;
}
// Only need to create the array if the item to be removed is present
Data **newArray = new Data *[count - 1];
// Copy the content to the new array
int newIndex = 0;
for (int i = 0; i < count; i++)
{
if (x != values[i])
newArray[newIndex++] = values[i];
}
// Now change the pointers.
delete[] values;
count--;
values = newArray;
return true;
}
Note that there's an underlying assumption that if x is present in the array then it's there only once! The code will not work for multiple occurrences, that's left to you, seeing as how this is a school exercise.
I'm trying to eliminate extra elements in the string array and I wrote the code below. There seems a problem with strcmp function and string arrays. Strcmp doesn't accept the string array elements that way. Can you help me fix that? array3 is string array. I'm coding in C++ and What I want to do is like there are multiple "apple"s or "banana"s in the string array. But I only need one "apple" or one "banana".
for(int l = 0; l<9999; l++)
{
for(int m=l+1;m<10000;m++)
if(!strcmp(array3[l],array3[m]))
{
array3[m]=array3[m+1];
}
}
strcmp returns 0 on equality, so if (strcmp(s1,s2))... means "if the strings are equal then do this...". Is that what you mean?
First of all, you can use operator== to compare strings of std::string type:
std::string a = "asd";
std::string b = "asd";
if(a == b)
{
//do something
}
Second, you have an error in your code, provided 10000 is the size of the array:
array3[m]=array3[m+1];
In this line you are accessing the m+1st element, with m being up to 10000. This means you will eventually try to access the 10001st element, and get out of array bonds.
Finally, your approach is wrong, and this way will not let you remove all the duplicate strings.
A better (but not the best) way to do it is this (pseudocode):
std::string array[];//initial array
std::string result[];//the array without duplicate elements
int resultSize = 0;//The number of unique elements.
bool isUnique = false;//A flag to indicate if the current element is unique.
for( int i = 0; i < array.size; i++ )
{
isUnique = true;//we assume that the element is unique
for( int j = 0; j < result.size; j++ )
{
if( array[i] == result[j] )
{
/*if the result array already contains such an element, it is, obviously,
not unique, and we have no interest in it.*/
isUnique = false;
break;
}
}
//Now, if the isUnique flag is true, which means we didn't find a match in the result array,
//we add the current element into the result array, and increase the count by one.
if( isUnique == true )
{
result[resultSize] = array[i];
resultSize++;
}
}
strcmp works on Cstrings only so if you wanna use it I suggest you alter it to the following: strcmp(array3[l].c_str(),array3[m].c_str()) which makes the strings C Strings.
Another option would be to simply compare them with the equality operator array3[l]==array3[m] this would tell you if the strings are equal or not.
Another way to do what you're trying to do is just to put the array in a set and iterate over it. Sets don't take more than one string of the same content!
References:
More about strcmp :http://en.cppreference.com/w/cpp/string/byte/strcmp
And moreabout c_str: http://en.cppreference.com/w/cpp/string/basic_string/c_str
Regarding String Comparison: http://en.cppreference.com/w/cpp/string/basic_string/compare
C++ Sets http://en.cppreference.com/w/cpp/container/set
Trying not to lose it here. As you can see below I have assigned intFrontPtr to point to the first cell in the array. And intBackPtr to point to the last cell in the array...:
bool quack::popFront(int& nPopFront)
{
nPopFront = items[top+1].n;
if ( count >= maxSize ) return false;
else
{
items[0].n = nPopFront;
intFrontPtr = &items[0].n;
intBackPtr = &items[count-1].n;
}
for (int temp; intFrontPtr < intBackPtr ;)
{
++intFrontPtr;
temp = *intFrontPtr;
*intFrontPtr = temp;
}
return true;
}
In the else statement I'm simply reassigning to ensure that my ptrs are where I want them. For some reason I'm popping off the back instead of off the front.
Anyone care to explain?
I'm not entirely sure I understand what you're trying to do, but if I;m guessing right you're trying to 'pop' the 1st element of the array (items[0]) into the nPopFront int reference, then move all the subsequent elements of the array over by one so that the 1st element is replaced by the 2nd, the 2nd by the 3rd, and so on. After this operation, the array will contain one less total number of elements.
Not having the full declaration of the quack class makes most of the following guesswork, but here goes:
I'm assuming that item[0] represents the 'front' of your array (so it's the element you want 'popped').
I'm also assuming that 'count` is the number of valid elements (so item[count-1] is the last valid element, or the 'back' of the array).
Given these assumptions, I'm honestly not sure what top is supposed to represent (so I might be entirely wrong on these guesses).
Problem #1: your nPopFront assignment is reversed, it should be:
nPopFront = items[0].n;
Problem #2; your for loop is a big no-op. It walks through the array assigning elements back to their original location. I think you want it to look more like:
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
Finally, you'll want to adjust count (and probably top - if you need it at all) before you return to adjust the new number of elements in the data structure. The whole thing might look like:
bool quack::popFront(int& nPopFront)
{
if ( count >= maxSize ) return false;
if ( count == 0 ) return false; // nothing to pop
nPopFront = items[0].n;
intFrontPtr = &items[0].n; // do we really need to maintain these pointers?
intBackPtr = &items[count-1].n;
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
count -= 1; // one less item in the array
return true;
}
The original question seems to be that you don't understand why the function popFront returns 3 times when there are 3 elements?
If that's the case, I think you are missing the point of recursion.
When you make a recursive call, you are calling the same function again, basically creating a new stack frame and jumping back to the same function. So if there are 3 elements, it will recurse by encountering the first element, encountering the second element, encountering the third element, returning from the third encounter, returning from the second encounter, and returning from the first encounter (assuming you are properly consuming your array, which you don't appear to be).
The current function cannot return until the recursive call has iterated, thus it may appear to return from the last element before the second, and the second before the first.
That is how recursion works.
I wasn't able to make sense of your example, so I whipped one up real fast:
#include <iostream>
using namespace std;
bool popfront(int* ptr_, int* back_) {
cerr << ptr_[0] << endl;
if(ptr_ != back_) {
popfront(++ptr_, back_);
}
return true;
}
int main() {
int ar[4] = {4,3,2,1};
popfront(ar, ar + 3);
return 0;
}
That's not great, but it should get the point across.
Can't you just use a std::list?
That makes it really to pop from either end using pop_front or pop_back. You can also add to the front and the back. It also has the advantage that after popping from the front (or even removing from the middle of the list) you don't have to shift anything around (The link is simply removed) which makes it much more efficient than what you are, seemingly, proposing.
I'm assuming you're trying to assign the popped value to nPopFront?
bool stack::popFront(int& nPopFront)
{
//items[4] = {4,3,2,1}
if ( intFrontPtr < intBackPtr )
{
nPopFront = *intFrontPtr;
++intFrontPtr;
}
return true;
}
bool quack::popFront(int& nPopFront)
{
if(items.n==0) throw WhateverYouUseToSignalError;
nPopFront = items[0];
for (int =0;i<items.n-1,++i){
items[i]=items[i+1]
}
//update size of items array
}