I have a simple program to add an element to an array:
void printArray(int inp[], int size)
{
cout << "[";
for (int i = 0; i < size - 1; i++)
{
cout << inp[i] << ", ";
}
cout << inp[size - 1] << "]" << endl;
}
int addElement(int inputArray[], int inputSize, int element, int atIndex)
{
int cur = inputSize;
while (cur >= 0)
{
if (cur == atIndex)
{
inputArray[cur] = element;
return inputSize + 1;
}
inputArray[cur] = inputArray[cur - 1];
cur--;
}
return inputSize + 1;
}
int arr1[] = {1, 5, 9, 2};
int arr2[] = {1, 5, 9, 2};
int main()
{
int arraySize = sizeof(arr1) / sizeof(arr1[0]);
addElement(arr1, arraySize, 7, 0);
printArray(arr1, arraySize + 1);
printArray(arr2, arraySize);
return 0;
}
This outputs:
[7, 1, 5, 9, 2] [2, 5, 9, 2]
Even though I haven't touched arr2 it is modified. I think because arr1 and arr2 are allocated contiguously in memory, and naively adding an element to arr1 overwrites arr2[0].
How should I handle this case and add only if the next space is unused, otherwise move the entire array to another location?
You can achieve this easily by using std::vector.
It has a method called insert, where you just pass a position and a number as arguments and it will handle the reallocation by itself.
For example: if you write:
vector<int> vec = { 1, 2, 3, 4, 5 };
vec.insert(vec.begin() + 2, 100);
Now elements in your vector are 1, 2, 100, 3, 4, 5.
I don't know if this will help you, but you can also add multiple elements at once:
vector<int> vec = { 1, 2, 3, 4, 5 };
vec.insert(vec.begin() + 3, { 100, 101 });
Now elements in your vector are: 1, 2, 3, 100, 101, 4, 5.
As you can see, the first argument is the position of the first inserted element and the second one is element or list of elements that you want to insert.
You can read more about std::vector here and about std::vector::insert here
Hope this helps.
As what the comments mentioned by #StoryTeller, you can use a std::vector.
But you have to pick on which function of the container you wanna use, there are 2 types.
::insert, which inserts data on the specific location in the
container. This is iterator based.
::push_back, which inserts at the back/last of the container
You can use any of them, depending on your purpose, just be sure of ::insert that you are pointing to the correct position(iterator wise).
Also, as of C++11 you can use ::emplace and ::emplace_back, which constructs and inserts data. You can find more at,
http://www.cplusplus.com/reference/vector/vector/
Hope this helps.
I have a simple program to add an element to an array:
Impossible. An array's size is fixed at compile time. In other words,
int arr1[] = {1, 5, 9, 2};
is a lot like:
int arr1_1 = 1;
int arr1_2 = 5;
int arr1_3 = 9;
int arr1_4 = 2;
I think it is helpful, for learning purposes, to view an array like this, and not like a container which can shrink and grow while the program is running. Adding an element to an array at runtime would be like asking to add a variable at runtime. C++ arrays don't work like that.
You can use new[] to set an array's initial size at runtime, but even then you cannot "add" anything. In fact, don't use new[], ever.
Go to cppreference.com, learn about std::vector and relearn everything from scratch. Start with the example code at the bottom of the page.
Related
This code is about sorting an array :
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + n);
cout << "\nArray after sorting using "
"default sort is : \n";
//Here I started printing the array
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
return 0;
}
Unfortunately, I am unable to understand this line :
sort(arr, arr + n);
How arr+n specifies end position here ?
For arrays, array name arr indicates iterator pointing to first element of array and +n would increment that iterator by n elements. In your case, the sort algorithm should take beginning iterator and iterator pointing to one beyond last element.
arr: beginning iterator
arr+n: ending iterator (one beyond last element)
Typically, algorithms don't count ending iterator in their range, so it's like this.
The convention on the standard libraries is that the ranges must be provided as an iterator pointing to the first element and an iterator pointing to one past the last element.
So your sequence has 10 elements
array = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
index => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
so arr[0] points to the first element and arr[10] points to one past the last element.
I'm trying to write a function called func1 that can shuffle a given deck of cards (an array) uniquely, given two other decks, the starting deck and the resulting deck. For example, a deck of cards [1, 2, 3, 4, 5] is shuffled and produces another deck of cards [4, 5, 2, 1, 3]. I want to complete this same shuffle (putting the card in slot 0 into slot 3, the card in slot 1 into slot 2, etc), but this time on another deck of cards [2, 3, 1, 5, 4]. It should print out [5, 4, 3, 2, 1] if I wrote the code correctly. Although it runs the program, it only prints the first "card" correctly, and the rest are really big numbers. What did I do wrong? Am I using the correct approach, or should I rethink my design?
#include <iostream>
using namespace std;
int * func1(int *deck) // A unique shuffle given two decks, a starting and ending deck (in this case, "start" and "shuff1")
{
int start[5] = { 1,2,3,4,5 }; // Starting deck
int shuff1[5] = { 4,5,2,1,3 }; // Resulting deck after shuffle. This is the specific type of shuffle that we are copying
int finish[5] = {}; // The deck that we are returning
for (int i = 0; i < 5; i++) // Looks at a specific spot (i) in the start deck...
{
for (int j = 0; j < 5; j++) // Looks through all the spots (j) in the shuff1 deck...
{
if (start[i] == shuff1[j]) // And if the cards themselves are identical, then it takes the ith card
{ // in the given deck and puts it in the jth spot in the finish deck
int temp = deck[i];
finish[j] = temp;
j = 5;
}
}
}
return finish;
}
int main()
{
int test[5] = { 2,3,1,5,4 }; // Given deck
int* shuff2 = func1(test); // Calls a specifc shuffle and sets it equal to a deck called shuff2
for (int i = 0; i < 5; i++)
{
cout << shuff2[i] << endl; // Prints shuff2
}
return 0;
}
Your func1 returns a pointer to finish, which is a variable local to the function. When control passes out of the function, that variable passes out of scope-- you could say it expires. So the pointer points to a spot in the wilderness of invalid memory, and dereferencing the pointer (e.g. by shuff2[i]) causes undefined behavior, which means strange numbers if you're lucky.
One solution is to have func1 construct finish on the heap. Another is to have the function accept a pointer to the array which it should fill with shuffled values; the calling code (e.g. main) would be responsible for providing a pointer to a valid array.
Your main problem is that you are returning a pointer to a variable allocated on the stack, which you can't do. Pass a pointer to "finish" as a second argument instead.
I'm not sure if I am following the way you described the proposed algorithm very well, but I think you would want to create an array of offsets, like this:
void func1(int *deck, int *finish) {
int offsets[5] = {3, 1, 2, -3, -3};
for (int i = 0; i < 5; ++i) {
finish[i + offsets[i]] = deck[i];
}
}
or put the actual destination indexes into the array:
void func1(int *deck, int *finish) {
int desti[5] = {3, 2, 4, 0, 1};
for (int i = 0; i < 5; ++i) {
finish[desti[i]] = deck[i];
}
}
Though you did specifically say "using two for loops" so maybe I'm misunderstanding the way you described the algorithm.
I'm writing class that manages dynamic array of objects. Right now I got stuck on method that should insert element at given index, but before it checks if that index isnt bigger than array capacity. Then it should resize array first.
template <class T>
void MyVector<T>::insertAt(int index, const T &m_element) {
if(p_size == p_capacity) extendArray();
if(index >= p_capacity) extendArray(index);
p_size++;
p_array[index] = m_element;
}
template <class T>
void MyVector<T>::extendArray(int new_capacity) {
std::unique_ptr<T[]> temp_array = std::make_unique<T[]>(new_capacity);
for (int i = 0; i <= p_size; i++) {
temp_array[i] = p_array[i];
}
p_array.reset();
p_array = std::make_unique<T[]>(new_capacity);
for (int i = 0; i <= p_size; i++) {
p_array[i] = temp_array[i];
}
}
extendArray()just extends array capacity 2 times, extendArray(int) extends array capacity to the number given by the index. First method works fine, second not so really.
int main(){
MyVector<int> test;
test.insertAt(0, 5);
test.insertAt(1, 3);
test.insertAt(2, 1);
test.insertAt(6, 11);
cout <<"Size " << test.getSize() << "\n";
for(int i = 0; i < test.getCapacity(); i++) {
cout << test.get(i) << ", ";
}
}
Id expect something like 5, 3, 1, 0, 0, 0, 11, 0
But I get just 5, 3, 1, 0 so it never extends array but it increases size (number of elements).
You did not post your extendArray() function but even though you say it's a copy of extendArray(int) first seems to be updating p_capacity when the latter you provided doesn't.
Fixing that would gain you couple of extra zeros in the output 5, 3, 1, 0, 0, 0 since you extending only to the index, not to the index+1. Furthermore, in insertAt(int index, const T &m_element) you are incrementing the p_size, instead of assigning it to index+1
Extending to p_size+1 and fixing the p_size assignment, prints 5, 3, 1, 0, 0, 0, 11 and I am not quite sure how you came to the conclusion that it should have an extra trailing 0 as p_capacity ends up being 7, regardless if the initial value is 1, 2 or 4 as in the code snippet I put a link to.
I also noticed couple of bugs I without looking too close: your loops shouldn't go to the p_size, but rather to p_size-1, so instead for (size_t i = 0; i <= p_size; i++) it should be for (size_t i = 0; i < p_size; i++)
I would also suggest using unsigned int (or size_t) instead of int for indexing as that allows to get compiler warnings when you do something which potentially can result in a negative index.
Lastly, you should be able to use unique_ptr::swap to avoid two allocations in extendArray(..).
Good luck with learning!
Suppose I have an array: int list[] = {1, 2, 4, 5, 6};
and I want to shift the array from the middle to the right and place 3 in the place of 4 so it would look like: {1, 2, 3, 4, 5, 6}.
How would I do it?
If you can use the C++ Standard Library, then std::vector is a replacement for arrays. It has a dedicated method insert to do what you want:
std::vector<int> v;
... // add elements 1, 2, 4, 5, 6 to it
v.insert(v.begin() + 2, 3); // insert 3 at position 2
This is good if you know where to insert your new element. However, it seems that your list should always be sorted, and you want to insert the new element so it remains sorted. If so, you better use std::multiset:
std::multiset<int> v;
... // add elements 1, 2, 4, 5, 6 to it
v.insert(3); // insert 3
Here, you don't need to tell where to insert the new element.
If you cannot use vector, one solution is:
Create an array with a lot of space (with a few empty positions at the end);
int * array = malloc(sizeof(int) * array_size);
Use two variables one to save the size of the array (lets called size) another to count the number of elements already added (lets called number_of_elements_in_the_array)
When you added an element at the position 'x', you do the following (with x < size of the array):
int tmp = array[x]; // save the current value
array[x] = new_value; // update with the new value
int tmp2;
number_of_elements_in_the_array++;
// we reach the limited
if(number_of_elements_in_the_array == size)
{
size = 2 * size; //lets double that size
int *new_array = malloc(sizeof(int) * size);
// copy the first elements
for(int i = 0; i <= x; i++)
new_array[i] = array[i];
new_array[x+1] = tmp;
// copy the last elements
for(int i = x+1; i < number_of_elements_in_the_array; i++)
new_array[i+1] = array[i];
free(array) // free the old space
array = new_array; // update the new pointer
}
else
{
// shift the remaining elements
for(int i = x+1; i < number_of_elements_in_the_array; i++)
{
tmp2 = array[i];
array[i] = tmp;
tmp = tmp2;
}
}
when you reach the limited, create a new array with more memory, copy from the old array to the new one, and update the variables number_of_elements_in_the_array and size accordingly.
Disclaimer : I didn't tested, thus it might be some minor erros, but the overall ideia is there.
I am trying to write a function that loops through an array, and skips over a given index. For example.
If have the array:
int Array[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
I want the output to skip over a given index. For example index 5, would skip "4". And output an array of smaller size, by skipping the "4", or index 5.
0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
My current function to skip over an index looks like this:
void deleteArray(int original[], int origLen, int newArray[], int index){
for(int i = 0; i < origLen--; i++){
newArray[i] = original[i];
if(original[i] == index){
newArray[i] = original[i-1];
}
}
}
I'm trying to iterate through the original array and copy its indexes until it gets to a certain index, and then skip over that given index, and creating a new array. Essentially, shifting all the arrays items to the left while skipping over a given index in a new array copied from the original array.
However, in my if statement, I'm not sure how to skip over the index. My current code substitutes the index with the previous index. Outputs:
0, 1, 2, 3, 4, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
Desired output:
0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
For a start, your condition is incorrect:
if(original[i] == index){
You're comparing the value of the element with the desired index, rather than the index itself (which in this case should be i).
Once past the desired index, you actually want every element in the new array to be the same as the previous element in the original array - not just one - so you need to deal with this somehow. I would suggest that you keep a boolean flag to track whether you've gone past the index, and in that case, assign original[i-1] to newArray[i]; if the flag is false, then assingn original[i] to newArray[i] (as you already do) instead.
You can simplify the function by using two loops instead of using one loop and performing check for every run of the loop.
void deleteArray(int original[], int origLen, int newArray[], int index){
// Get everything up to index.
// When index is 5, get everything until i = 3
for(int i = 0; i < index-1; i++) {
newArray[i] = original[i];
}
// Now get everything after index.
for(int i = index; i < origLen; i++) {
newArray[i-1] = original[i];
}
}
std::copy it:
auto newArrayPosition = std::copy(original, original + index, newArray);
std::copy(original + index + 1, original + origLen, newArrayPosition);
If you always know that your new array would be one element smaller than the original i suggest you doing like this:
int Array[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
int newArray[19];
then
void deleteArray(int original[], int origLen, int newArray[], int index){
j = 0;
for(int i = 0; i < origLen; i++){
if(i == index){
continue;
}
newArray[j] = Array[i];
j++;
}
or even you can write in the boby of your loop smth like this (if you don't want to use j):
for(int i = 0; i < origLen; i++){
if(i == index){
continue;
}
if (i < index){
newArray[i] = Array[i];
}
else {
newArray[i-1] = Array[i];
}
}
I would just keep two counters, one for the insert position and one for the reading position:
void deleteArray(int original[], int origLen, int newArray[], int index){
int insertPos = 0;
for(int readPos = 0; readPos < origLen; readPos++){
// If this position is equal to the index we want to skip
if (readPos == index)
{
// continue onto next loop iteration
continue;
}
// Copy over the data
newArray[insertPos] = original[readPos];
// increment the counter
insertPos++;
}
}
Like others have said, avoid i < origLen-- as that is very complicated and you actually ended up not even parsing through your whole array because you kept decrementing.