The code below is my own implementation a push_front method for my items array. I was wondering if someone could help me figure out how to implement the method so that i am just moving the indexes up or down. I need my items to stay in the array, rather then dumping them into a "front" varaible:
stack::stack(int capacity) : items(new item[capacity]), maxSize(capacity),
count(0), top(-1)
{
intFront = 0;
}
bool stack::pushFront(const int nPushFront)
{
if ( count == maxSize ) // indicates a full array
{
return false;
}
for ( int shift = 0; shift < count; )
{
if ( shift == top+1 )
{
intFront = items[top+1].n;
}
items->n = items[++shift].n;
items[shift].n = intFront;
if ( shift != maxSize-1 )
{
intFront = items[++shift].n;
items[shift].n = items->n;
}
}
++count;
items[top+1].n = nPushFront;
return true;
}
items->n is pointing to the struct member n, which is a int type varaible
As you can see im moving elements out of my array into temp varaibles. My question is how would i get around that? How would i just move my indexes up or down to push items to the front of the array? I am trying to get the contents of the array to stay in the array..
Any thoughts?
What you have there, or had there before, is a stack.
What you want, I presume, is a ring buffer.
When your index goes past the end of the array, you reset it back to 0. (It wraps.) And when it goes past the end index you set that index back to the start. You can insert elements after the end index, so long as it doesn't overlap the start one.
Related
I have this function for a Go Fish Card game.
// Remove a Card from the player's hand
// In: _index The index of the card to remove from the array
// _discard A reference to store that value in
//
// Return: True if there was a card actually stored at that index.
// False if the index was "empty"
bool Player::Discard(int _index, Card& _discard)
{
return true;
}
Should store the requested card into the reference being passed in.
After that, "shift" the array back to show this card has been removed.
Example:
[ 7♥ 3♣ 5♦ 9♥ ] m_numCards: 4
discarding index 1 (the 3♣) *
[ 7♥ 5♦ 9♥ 9♥ ] m_numCards: 3
Even though it looks like there are two 9♥, we won't ever be displaying that to the user, and it will be the first one that gets overwritten if
another card is added to the hand. **/
// Just here for compilation
in the header i have this member variables.
char m_name[32];
Card m_hand[7];
int m_numCards;
int m_maxCards;
int m_score;
I had this inside to do the first part But im pretty sure im missing something.
if (m_hand[_index] != FALSE)
{
_discard = m_hand[_index];
return true;
}
else
return false;
If you define your "hand" as an array:
Card m_hand[7];
Then you always have 7 cards. Sure you could add a "sentinel" Card value or something, but really there's always 7 cards. You can't remove or append to a raw array. On the other hand, if you used a dynamic container instead:
std::vector<Card> m_hand;
Now, you can have a variable-sized hand and add and remove cards as you see fit. And your discard function becomes easy:
bool Player::Discard(int _index, Card& _discard)
{
if (m_hand.size() > _index) {
_discard = m_hand[_index];
m_hand.erase(m_hand.begin() + _index);
return true;
}
else {
return false;
}
}
Although with Go Fish, it probably makes more sense to discard a card by value:
bool Player::Discard(Card const& card)
{
size_t cur = m_hand.size();
m_hand.erase(std::remove(m_hand.begin(), m_hand.end(), card), m_hand.end());
return m_hand.size() != cur;
}
There are 52 cards in a standard deck and an unsigned char can represent more than 52 distinct values.
Assign zero as a 'no card' value and use values 1 - 52 to represent the cards. Instead of removing cards from the array and then rearranging it, simply overwrite the value to be erased with zero.
When adding a card to the array, iterate until you find an index where the value is zero.
ok so I figured it out
bool Player::Discard(int _index, Card& _discard)
{
if (_index < m_numCards)
{
_discard = m_hand[_index];
for (int i = _index + 1; i < m_numCards; ++i)
{
m_hand[i - 1] = m_hand[i];
}
m_numCards -= 1;
return true;
}
else
return false;
}
Even though this is probably homework assignment, you should really use built-in methods in objects such as std::vector or std::list. If you really want to use arrays, you can delete an element by moving all elements to the left that are after the element you want to delete. It would look something like this:
for (int i = 0; i < cardsLength; i ++) {
if (cards[i] == theCardYouWantToDelete) {
for (int j = i; j < cardsLength - 1; j ++) {
cards[j] = cards[j + 1];
}
break; // to break out of outer for loop
}
}
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.
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
}
I thought i'd post a little of my homework assignment. Im so lost in it. I just have to be really efficient. Without using any stls, boosts and the like. By this post, I was hoping that someone could help me figure it out.
bool stack::pushFront(const int nPushFront)
{
if ( count == maxSize ) // indicates a full array
{
return false;
}
else if ( count <= 0 )
{
count++;
items[top+1].n = nPushFront;
return true;
}
++count;
for ( int i = 0; i < count - 1; i++ )
{
intBackPtr = intFrontPtr;
intBackPtr++;
*intBackPtr = *intFrontPtr;
}
items[top+1].n = nPushFront;
return true;
}
I just cannot figure out for the life of me to do this correctly! I hope im doing this right, what with the pointers and all
int *intFrontPtr = &items[0].n;
int *intBackPtr = &items[capacity-1].n;
Im trying to think of this pushFront method like shifting an array to the right by 'n' units...I can only seem to do that in an array that is full. Can someone out their please help me?
Firstly, I'm not sure why you have the line else if ( count <= 0 ) - the count of items in your stack should never be below 0.
Usually, you would implement a stack not by pushing to the front, but pushing and popping from the back. So rather than moving everything along, as it looks like you're doing, just store a pointer to where the last element is, and insert just after that, and pop from there. When you push, just increment that pointer, and when you pop, decrement it (you don't even have to delete it). If that pointer is at the end of your array, you're full (so you don't even have to store a count value). And if it's at the start, then it's empty.
Edit
If you're after a queue, look into Circular Queues. That's typically how you'd implement one in an array. Alternatively, rather than using an array, try a Linked List - that lets it be arbitrarily big (the only limit is your computer's memory).
You don't need any pointers to shift an array. Just use simple for statement:
int *a; // Your array
int count; // Elements count in array
int length; // Length of array (maxSize)
bool pushFront(const int nPushFront)
{
if (count == length) return false;
for (int i = count - 1; i >= 0; --i)
Swap(a[i], a[i + 1]);
a[0] = nPushFront; ++count;
return true;
}
Without doing your homework for you let me see if I can give you some hints. Implementing a deque (double ended queue) is really quite easy if you can get your head around a few concepts.
Firstly, it is key to note that since we will be popping off the front and/or back in order to efficiently code an algorithm which uses contiguous storage we need to be able to pop front/back without shifting the entire array (what you currently do). A much better and in my mind simpler way is to track the front AND the back of the relevant data within your deque.
As a simple example of the above concept consider a static (cannot grow) deque of size 10:
class Deque
{
public:
Deque()
: front(0)
, count(0) {}
private:
size_t front;
size_t count;
enum {
MAXSIZE = 10
};
int data[MAXSIZE];
};
You can of course implement this and allow it to grow in size etc. But for simplicity I'm leaving all that out. Now to allow a user to add to the deque:
void Deque::push_back(int value)
{
if(count>=MAXSIZE)
throw std::runtime_error("Deque full!");
data[(front+count)%MAXSIZE] = value;
count++;
}
And to pop off the back:
int Deque::pop_back()
{
if(count==0)
throw std::runtime_error("Deque empty! Cannot pop!");
int value = data[(front+(--count))%MAXSIZE];
return value;
}
Now the key thing to observe in the above functions is how we are accessing the data within the array. By modding with MAXSIZE we ensure that we are not accessing out of bounds, and that we are hitting the right value. Also as the value of front changes (due to push_front, pop_front) the modulus operator ensures that wrap around is dealt with appropriately. I'll show you how to do push_front, you can figure out pop_front for yourself:
void Deque::push_front(int value)
{
if(count>=MAXSIZE)
throw std::runtime_error("Deque full!");
// Determine where front should now be.
if (front==0)
front = MAXSIZE-1;
else
--front;
data[front] = value;
++count;
}