Issue with swapping addresses - c++

I am doing an assignment in which i must write a function that does the following - "You will allocate an array the size of the number of vacancies and load the dynamic array with the pointers to all of the current vacancies. Build the array using the last vacancy first. in this same function, you will move all of the transfers to the available rooms (and mark them as OCCUPIED) using the dynamic array of pointers. You must do this by performing a swap of the transfer addresses with the vacant ones. Start from the back of the array of pointers and continue to the front for these operations until all transfers are done. DO NOT REPROCESS the array of pointers." This is what i wrote in an attempt to do this -
char** tranfers(char hospitalFloors[FLOOR_ARRAY_SIZE][ROOM_ARRAY_SIZE], int &num)
{
int x = 0;
char *temp;
for (int i = 0; i < FLOOR_ARRAY_SIZE; i++)
{
for (int k = 0; k < ROOM_ARRAY_SIZE; k++)
{
if(hospitalFloors[i][k] == 'V')
{
num++;
}
}
}
char **arr = new char*[num];
for (int i = (FLOOR_ARRAY_SIZE - 1); i >= 0; i--)
{
for (int k = (ROOM_ARRAY_SIZE - 1); k >= 0; k--)
{
if (hospitalFloors[i][k] == 'V')
{
arr[x] = &hospitalFloors[i][k];
x++;
}
}
}
for (int i = 0; i < FLOOR_ARRAY_SIZE; i++)
{
for (int k = 0; k < ROOM_ARRAY_SIZE; k++)
{
if (hospitalFloors[i][k] == 'T')
{
x--;
temp = arr[x];
arr[x] = &hospitalFloors[i][k]
&hospitalFloors[i][k] = temp;
}
}
}
return arr;
}
i have no doubt in my mind that there is a problem with trying to set &hospitalFloors[i][k] to a pointer, but no matter what i try differently i cant seem to come up with a solution.
my question is, given what the assignment is asking, how would i swap the address of the room with a transfer to a room with a patient, making sure that the array of pointers keeps its order, but without reprocessing it?
Any help is greatly appreciated.

The wording of the question is quite a bit vague. It looks like what you need to do is move any room marked as a transfer ('T') to a vacant room ('V') and mark it as occupied (assuming 'O') and mark the room transferred from as vacant.
So all you need to do is take the appropriate steps in your last if block.
*arr[x] = 'O'; // set vacant room as occupied.
hospitalFloors[i][j] = 'V'; // set transfer room as vacant
arr[x] = &hospitalFloors[i][j]; // make the vacancy element point at the now vacant room
Of course keeping x--

You do need to work on the pointed-to data, of type char. While the assignment says "swap", it also says to mark the moved transferee rooms occupied, which you could do directly:
*arr[x] = 'O';
hospitalFloors[i][k] = 'V';
To do it literally using a "swap" first:
char temp = *arr[x]; // was vacant
*arr[x] = hospitalFloors[i][k]; // assign transfer
hostpitalFloors[i][k] = temp; // make vacant
*arr[x] = 'O'; // make occupied
The array does say...
You must do this by performing a swap of the transfer addresses with the vacant ones.
It's unclear if addresses above alludes to the [floor][room] aspect, or the char* aspect. There's ostensibly no point in modifying the pointer addresses in arr though, so I'm assuming the former.
You are asked to do this in reverse order of the array though, but you're currently looping over the floors and rooms again. I'm sure you can fix that yourself.

Related

Rearranging the elements of array with specific positions

User has to make an array from any amount of numbers and I need to rearrange the array, so that the elements from EVEN places would move to the start of an array and from UNEVEN places to the end. For example A=[1,2,3,4,5,6] would turn into B=[2,4,6,1,3,5]. Also I need to use POINTERS.... I am very bad at pointers, so help would be very much appreciated.
This is as far as I got myself. I am not using pointers here though, because I don't know how to.. :(
void switcharoo(int a, int b[]){
int temp[a], j=0;
for(int i=1;i<a;i+=2){
temp[j] = b[i];
j++;
}
for(int i=0;i<a;i+=2){
temp[j] = b[i];
j++;
}
b = temp;
}
Oups, you have still to improve your C++ knowledge...
int temp[a] is not valid C++ as you have been told in comment - Variable Length Arrays are a C feature
b is passed as a pointer (an arrays decays to a pointer to its first element when passed to a function). When you write b=temp; at the end of you function, you only change a local copy... which immediately goes out of scope: in short the current code is just a no-op.
array indices start at 0
If you want to train in using pointers, you could do something like that:
void switcharoo(int a, int b[]) {
int *even = new int[a]; // allocate an array of same size
int *odd = even + a / 2; // point at the mid array element
for (int i = 0; i<a - 1; i += 2) {
*odd++ = b[i]; // odd elements in high part
*even++ = b[i + 1]; // even in low part
}
if (0 != a % 2) { // one odd element remains
*odd++ = b[a - 1];
}
even = odd - a; // make even point again to start of allocated array
odd = even; // store a copy
for (int i = 0; i<a; i++) { // copy back in original array
b[i] = *even++;
}
delete[] odd; // and delete the allocated array
}

How to insert an object in the array of pointers

I have an array of pointers:
Hotel *hotels[size];
for (int i = 0; i < size; ++i)
hotels[i] = new Hotel();
And I want to insert an object in this array after some object with name I know:
cin >> tmp_name;
for (int i = 0; i < size; i++) {
if (hotels[i]->get_name() == tmp_name) {
hotels[size] = new Hotel();
size += 1;
Hotel *tmp_hotel;
tmp_hotel = hotels[i+1];
hotels[i+1]->fillHotel();
for (i = i + 2; i < size; i++) {
hotels[i] = tmp_hotel;
tmp_hotel = hotels[i+1];
}
break;
}
}
What I do wrong?
UPD:
My solution:
cin >> tmp_name;
for (int i = 0, j = 0; i < size; i++, j++) {
new_hotels[j] = hotels[i];
if (hotels[i]->get_name() == tmp_name) {
new_hotels[j+1]->fillHotel();
++j;
system("clear");
}
}
hotels[size] = new Hotel();
++size;
for (int i = 0; i < size; i++) {
hotels[i] = new_hotels[i];
}
I can see different errors in your code.
For example:
Hotel *hotels[size];
size should be a constant expression and something let me think this is not the case. VLA are not part of the C++ standard. In short you cannot allocate dynamic memory on the stack. The proper initialization should be:
Hotel* hotels = new Hotel*[size];
The line in the loop:
hotels[size] = new Hotel();
you're actually accessing out of bounds of your array: size index is some memory is not included in your array and this will produce an undefined behaviour.
Another strange line is the following:
size += 1;
Despite the fact that confirms size is not a constant, you cannot increase your size of vector simply changing that variable. You're actually just changing a variable size, but the allocated memory for your array will be the same.
How resolve?
In order in increase (or change) the size of an array, the solution is almost always to create a new array, copy the old one. In your case that solution is pretty reasonable because you should copy just pointers and not entire objects.
There are a lots of question on S.O. where this topic is, for example here.
Despite of that, I strongly suggest you to use the most practical alternative, that is to use a real C++ code.
The most efficient class is std::vector which is a C++ way to handle dynamic array.
Finally, you should also consider the std::unique_ptr<T> class to handle dynamic memory and pointers.
The final solution will be a class:
std::vector<std::unique_ptr<Hotel>> hotels;

C++ Pointer Dereferenced Assignment

I am trying to learn C++ by firstly going through the low level details before I start using abstractions such as std::copy or memcpy. Currently I am stuck in trying to figure out why this code is never assigning into "sortedArray" variable, when looking with debugger I dereference the value from "data" correctly but it is never assigned to "sortedArray". I see value such as "-842150451" instead of "14" for first value. Can you please help me figure out what I am doing wrong ? And any other issues there may be that I do not see or advice would be greatly appreciated !
void swap(int* bigger, int* smaller){
*bigger += *smaller;
*smaller = *bigger - *smaller;
*bigger = *bigger - *smaller;
}
int* bubbleSort(int *data, int size){
bool swapped = true;
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
*(sortedArray++) = *(data++);
}
while (swapped){
swapped = false;
for (int i = 1; i <= size - 1; i++){
if (sortedArray[i - 1] > sortedArray[i]){
swap(&sortedArray[i - 1], &sortedArray[i]);
swapped = true;
}
}
size--;
}
return sortedArray;
}
*(sortedArray++) = *(data++); modifies the pointer so it no longer points to the start of the allocated memory. So, later on sortedArray[i] is whatever happens to be in memory past the array, and accessing it is undefined behavior.
If you must use pointers, a quick fix is to use a temporary one, like:
int *sortedArray = (int*)malloc(size*sizeof(int));
int* s = sortedArray;
for (int i = 0; i < size;i++){
*s++ = *data++;
}
Another way would be:
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
sortedArray[i] = data[i];
}
But, the best way would be to use standard containers and algorithms, like vector and sort.
Here's a demo of the first fix in action.
Change
*(sortedArray++) = *(data++);
to
sortedArray[i] = data[i];
You need to leave intact the pointer to the block of memory you allocated, so you can use it (and free it) later.
Note, there is nothing to be gained by using the *(x+y) syntax instead of x[y], they are equivalent but the latter is easier to read.
In C++ you should not use malloc. Instead use new int[size]. For int there is no difference other than reduced risk of making a typo, however for non-trivial types malloc will not construct them correctly.
That is not C++ at all. You can write generic code that takes a begin iterator and an end iterator in order for it to work with any kind of container that supports such semantic.
template<typename IT>
void bubble_sort(IT begin, IT end) {
while (true) {
bool swapped = false;
for (IT i = begin; i != end-1; i = i+1) {
if (*i > *(i+1)) {
std::iter_swap(i, i+1);
swapped = true;
}
}
if (swapped == false) return;
}
}
Live demo
Where std::iter_swap is like std::swap but works on iterators. You can see iterators as a pair of pointers to the beginning and (past the) end of a container.
You first pointer sortedArray points to some allocated memory.
Then in the first for loop you increment the pointer. not it doesn't point to that memory anymore.
Simply use a temporary pointer for the memory copy.
int* t = sortedArray ;
And now use t in your for loop which copies the data.
Instead of the temporary variable, you can rather count the number of times you called sortedArray++ in your for loop.
If you take a look: for (int i = 0; i < size;i++) you will see that the loop took exactly size number of iterations.
Just subtract size from the pointer after the loop and you point back to your allocated memory.
sortedArray -= size ;

c++ Dynamic array using strings won't accept strings

I am trying to put the strings in a temporary array into a dynamic array. But the compiler just breaks when it hits that.
where dynaicArray is called:
string* dynamicArray = NULL;
Here is where it is breaking:
for (int i = 1; i <= (size); i++)
{
dynamicArray[i] = tempArray[i];
}
Where tempArray is filled:
void populateArray(int& size, string*& dynamicArray)
{
char decide;
string tempArray[100]; //Holds the strings until the size is known
bool moreStrings = true;
while (moreStrings == true)
{
cout << "\nEnter your string here:";
cin >> tempArray[size];
cout << "\nDo you want to enter another string? Y/N:";
cin >> decide;
decide = toupper(decide);
size ++;
dynamicArray = new string[size];
if (decide == 'N')
{
for (int i = 1; i <= (size); i++) //moves all of the strings from tempArray to dynamicArray
{
string temp;
temp = tempArray[i];
dynamicArray[i] = temp;
}
moreStrings = false;
}
}
}
PS: I know vectors are better. Unfortunately they're not an option.
Some design ideas:
the code in the if (decide == 'N') block is better placed after the while, to make the while smaller == more readable
once the above is implemented, you can set the moreStrings var directly with the result of your decide == 'N'; no need for an explicit if there anymore
you now do a dynamicArray = new string[size]; in each pass through the while, which is an enormous memory leak (you'r overwriting the newly created dynamic array with a new copy without reclaiming the old one out first - see dalete[])
as already mentioned: don't assume 100 will be enough - read "Buffer overflow" (only viable solution: make it a dynamic array as well and re-allocate it to a bigger one if it gets full)
better initialize size in the function before you use it - much safer; callers don't need to remember to do it themselves
C++ arrays are 0-based, so when you start copying them you'd also better start at 0 and not at 1
nitpick: for (int i = 1; i <= (size); i++): the () around size are superfluous
bonus advanced nitpick: use ++size and ++i in these contexts; it's a bit more efficient
you now use the var tmp to copy from the temp array to the dynamic one and the code is also somewhat structured to suggest you're using it to swap the strings between the two arrays (you're not) - rename the tmp variable or get rid of it altogether

Initializing array of pointers

I have a Deck object (deck of cards) which is a double-ended queue implemented as a doubly-linked list. I would like to be able to shuffle the queue at will, but the way I would go about it is beyond me. So instead I've opted to pre-shuffle an array a pointers to the cards and enqueue them after the fact. Problem is, the code I have now doesn't seem to be initializing the pointers at all.
void BuildDeck(Deck* deck) {
Card** cards = new Card*[20];
const size_t MAX_INTEGER_LENGTH = sizeof(int) * 4;
char szPostfix[] = "_Card.bmp";
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i-1] = new Card(i,path);
}
ShuffleArray(cards);
for (int i = 0; i < 20; i++) {
deck->PushTop(cards[i]);
}
}
void Swap(Card* a, Card* b) {
Card temp = *a;
*a = *b;
*b = temp;
}
void ShuffleArray(Card** cardArray) {
srand(dbTimer());
for (int i = 0; i < 20; i++)
Swap(cardArray[i],cardArray[rand()%20]);
}
I think where I screwed up is in the card[i] = new Card(...) line, but it somehow looks right to me.
Any suggestions would be appreciated.
DISCLAIMER: I know I should be using the standard library for most of this stuff, but I'm trying to teach myself the hard stuff first. It's just the way I learn.
EDIT: I fixed the index problem. Now I've just gotta figure out why some image aren't drawing now... :/ Thanks for the help!
Your code has many problems
You are looping with 1 <= i <= 20 but for an array of 20 elements indexing goes from 0 <= index <= 19. You need to use cards[i-1] = new Card(i,path);
You are allocating the array of pointers cards but you are not deallocating it (memory leak). Either deallocate it with delete[] cards; once you are done or just use a stack based array with Card *cards[20]; instead of allocating it with new.
The way you compute MAX_INTEGER_LENGTH shows you don't really understand what sizeof does.
This is the reason for which the cards don't get shuffled. You wrote a function that swaps two pointers, but the pointers it is swapping are local variables (parameters) of the function, not the elements of the array. One solution is to pass the parameters as pointer references by declaring swap with void Swap(Card *& a, Card *& b), another solution would be passing pointers to pointers (but this would require a more complex syntax of the implementation because of the double indirection and would also require a change in the way you call the function).
In the first for loop your starting index is 0, while in the second for loop the starting index is 0. That could be the problem.
Your code:
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i] = new Card(i,path);
}
Here the loop should start from 0 to 20 as:
for(int i = 1 ; i < 21; i++) //incorrect - original code
for(int i = 0 ; i < 20; i++) //correct - fix
And after the fix, you could use i+1 instead of i in :
sprintf(path,"%d%s",i+1, szPostfix);
cards[i] = new Card(i+1,path);
if that is required.