Move element in array in order - c++

How to move element in array in order or remove from array?
Example: arr[3,3,2,1]
move(arr[0],arr[sizeof(arr)]);
arr[3,2,1,3];
I wrote function, but is correctly it ?
void remove(int index, char *arr)
{
arr[index]=NULL;
for(int i=index;i<sizeof(arr)-1;i++)
swap(arr[i],arr[i+1]);
}

Well, first off, I'm going to suggest using std::vector instead of an array since you're using C++. It will make this process much simpler. As for your function, I want to cover a few things...
arr[index] = NULL;
If I remember right, NULL is 0, so this is fine. However, I'm assuming you're under the impression that this is a pointer, which it is not. Although you may have a pointer to the array, each individual element of the array is not a pointer. To get this, you would need to pass a char **. The reason this works in this case is because a char is really an int.
sizeof(arr)-1
This will not get you the number of elements of the array. You asked for the size of arr, which is going to return the size of the pointer data type. A better option here would be to iterate through with pointer arithmetic until you reach the end of the data. Remember, a pointer to an array by the end of the day is still just a pointer and does not contain any overhead about the array itself. It just knows which element it is pointing to.

This already exists in the C++ standard library (std::rotate), and the C standard library (memmove)
If you're using C++, (since it comes with a std::swap function, and C can't swap with parameters like that):
void remove(int index, char *arr, int len)
{
if (len<=0)
len = strlen(arr);
std::rotate(arr+index, arr+index+1, arr+len);
arr[len-1] = NULL;
}
Also, in C++, use a std::vector or std::string rather than a naked char* pointer.
If you're using C:
void remove(int index, char *arr, int len)
{
if (len<=0)
len = strlen(arr);
memmove(arr+index, arr+index+1, len-index-1);
arr[len-1] = NULL;
}
If you are using naked char* pointers, always pass a length.

You don't have to NULL the element or swap.
void remove(int index, char *arr)
{
int i;
for(i=index;i<strlen(arr)-1;i++)
arr[i] = arr[i+1];
arr[i] = NULL; // i now points to last, "extra" element
}

The sizeof(arr) when arr is declared as actual array with dimension will give you the size of the array in bytes (actually, C++ does not know bytes, only chars, but lets not get into that right now). The arr[sizeof(arr)] makes no sense: you are telling the compiler to get the element that is at the index numerically equal to the size of array in bytes, which is always out of bounds. BTW, to get the size of array in elements, use: sizeof(arr) / sizeof(arr[0]).
The sizeof(arr) when char *arr will give you the size of the pointer (typically 4 or 8 bytes depending on bitness), regardless of how large the array "beneath" that pointer is.
Even when you fix all that (and couple of other more minor things such as using NULL as integer), you will still be just moving the element to the end of the array, not actually re-moving it.
I suggest you use std::vector and its erase method. If you are doing a lot of removes from the middle (and you can live without random-access), consider using std::list (and its erase) instead. Alternatively, you may also consider std::remove.

Do not swap your elements just shift all right allocated elements one position left in order to overwrite you element. Do not forget to decrease size of your array.

It looks correct, indeed.
You should distinguish between cases when you want to remove an element from the array, or simply move it.
Perhaps it is a good idea to transfer the count (by how much to move) as a parameter, and when it is equal to the array length (or 0, for example) - the element would be deleted.

Related

What is the fastest way to obtain an index from a pointer of an array element in C++?

Suppose you have a pointer to an int from an array. Is this the best way to find out which item of the array the pointer points to?
int nmbr = pointer - &array[0];
cout<<"Item number "<<nmbr+1;
If the pointer pointed to the 6th item, would this always print "Item number 6"? Is this error-prone? Is there a faster way to do it? Iterating over the array won't work because of possible duplicate values, but does this always work? In this situation we assume the array starts from item 0 to item x. Is there a situation in which an array's items aren't stored in a continuous line (if the array was initialized as int array[x];)?
Assuming pointer is known to point at an element of array, the
std::ptrdiff_t nmbr = pointer - array;
will do it. If pointer does not point at an element of the array, the behaviour is undefined. std::ptrdiff_t is declared in the standard header <cstddef>, and is an implementation-defined signed integral type. Using int is not a good idea, particularly for large arrays, since std::ptrdiff_t may be able to represent a larger range of values than an int (and, if the value is larger than an int can represent, converting the result to int also gives undefined behaviour).
The +1s in your code are incorrect, since array indexing in C++ is zero based.
All arrays, in the sense of something declared as
some_type array[some_positive_value];
have contiguous elements. Note that C++ does not support C's VLAs (variable length arrays) i.e. some_positive_value must be known at compile time.
As mentioned by XTF, yes it is guaranteed to work. There is however, no need for taking the address of the 0'th element, just use array as it is.
For a more generic solution, that will also work on other containers you could consider the following examples:
#include <iostream>
#include <iterator>
#include <array>
int main()
{
{
int array[10];
int * p = &array[5]; // Somehow get a pointer to the sixth element
std::cout << std::distance(std::begin(array), p) << std::endl;
}
{
std::array<int, 10> array;
int * p = &array[5]; // Somehow get a pointer to the sixth element
std::cout << std::distance(std::begin(array), p) << std::endl;
}
}
Both +1's look wrong..
But yes, this is the fastest and simplest way. It's guaranteed to work.

Reversing Array Without Using Array Size

It is relatively easy to reverse an array given a pointer to the array and the size of the array.
But my question is: Is it possible to reverse the array given just a pointer to the array?
( in C++ btw)
EDIT
This was a question apparently asked in an interview at Lockheed Martin. See here
In general the answer is NO.
It is only possible for so called terminated arrays like NULL-terminated char array:
void reverse(char* str)
{
int end = -1;
int front = -1;
while (str[++end] != NULL);
while (--end > ++front)
{
char temp = str[end];
str[end] = str[front];
str[front] = temp;
}
}
No it is not possible. If you dont know the size of your array then you cant reverse it.
It can be possible if you define a "terminator" for your array element type, like \0 used for char arrays. You should always end the array with that value, otherwise you'll obtain runtime errors. But it's always better to use the size or avoid arrays and use vectors since you're using c++ and not c.
Nope. Without knowing the size, you cannot use the iterators to reverse it and without using iterators and not knowing the size, it wouldnt be possible to reverse that particular array. You would have to declare another array, copy the contents from the first array into the new array, and perform the content reverse on the new array.

How to copy a range of data from char array into a vector?

I've read file contents into a char array, and then read some data of it into a vector.
How can i copy a range of the char array into the vector? both vector and char array is the same type (unsigned char).
Current code goes something like this:
int p = 0;
for(...){
short len = (arr[p+1] << 8) | arr[p+0];
p+=2;
...
for(...len...){
vec.push_back(arr[p]);
p++;
}
}
I would like to improve this by dropping the loop with push_back, How?
Appending something to a vector can be done using the insert() member function:
vec.insert(vec.end(), arr, arr+len);
Of course, there's also an assign(), which is probably closer to what you want to do:
vec.assign(arr, arr+len);
However, reading your question I wondered why you would first read into a C array just to copy its content into a vector, when you could read into a vector right away. A std::vector<> is required to keep its data in one contiguous block of memory, and you can access this block by taking the address of its first element. Just make sure you have enough room in the vector:
std::size_t my_read(char* buffer, std::size_t buffer_size);
vec.resize( appropriate_length );
vec.resize( my_read_func(&vec[0], vec.size()) );
Instead of &vec[0] you could also get the address of the first element by &*vec.begin(). However, note that with either method you absolutely must make sure there's at least one element in the vector. None of the two methods are required to check for it (although your implementation might do so for debug builds), and both will invoke the dreaded Undefined Behavior when you fail on this.

Is it necessary to delete elements as an array shrinks?

I'm a student writing a method that removes zeros from the end of an array of ints, in C++. The array is in a struct, and the struct also has an int that keeps track of the length of the array.
The method examines each element starting from the last, until it encounters the first non-zero element, and marks that one as the "last element" by changing the value of length. Then the method walks back up to the original "last element", deleting those elements that are not out of bounds (the zeros).
The part that deletes the ith element in the array if i is greater than the updated length of the array, looks like this:
if (i > p->length - 1) {
delete (p->elems + i); // free ith elem
That line is wrong, though. Delete takes a pointer, yes? So my feeling is that I need to recover the pointer to the array, and then add i to it so that I will have the memory location of the integer I want to delete.
Is my intuition wrong? Is the error subtle? Or, have I got the entirely wrong idea? I've begun to wonder: do I really need to free these primitives? If they were not primitives I would need to, and in that case, how would I?
have I got the entirely wrong idea?
I'm afraid so.
If you make one new[] call to allocate an array, then you must make one delete[] call to free it:
int *p = new int[10];
...
delete[] p;
If your array is in a struct, and you make one call to allocate the struct, then you must make one call to free it:
struct Foo {
int data[10];
};
Foo *foo = new Foo;
...
delete foo;
There is no way to free part of an array.
An int[10] array actually is 10 integers, in a row (that is, 40 bytes of memory on a 32 bit system, perhaps plus overhead). The integer values which are stored in the array occupy that memory - they are not themselves memory allocations, and they do not need to be freed.
All that said, if you want a variable length array:
that's what std::vector is for
#include <vector>
#include <iostream>
struct Foo {
std::vector<int> vec;
};
int main() {
Foo foo;
// no need for a separate length: the current length of the vector is
std::cout << foo.vec.size() << "\n";
// change the size of the vector to 10 (fills with 0)
foo.vec.resize(10);
// change the size of the vector to 7, discarding the last 3 elements
foo.vec.resize(7);
}
If p->elems is a pointer, then so is p->elems + i (assuming the operation is defined, i.e. i is of integral type) - and p->elems + i == &p->elems[i]
Anyhow, you most likely don't want to (and cannot) delete ints from an array of int (be it dynamically or automatically allocated). That is
int* ptr = new int[10];
delete &ptr[5]; // WRONG!
That is simply something you cannot do. However, if the struct contains the length of the array, you could consider the array "resized" after you change the length information contained by the struct - after all, there is no way to tell the size of the array a pointer points to.
If, however your array is an array of pointers to integers (int*[]) and these pointers point to dynamically allocated memory, then yes, you could delete single items and you'd do it along the lines of your code (you are showing so little code it's difficult to be exact).

C++ How can I iterate till the end of a dynamic array?

suppose I declare a dynamic array like
int *dynArray = new int [1];
which is initialized with an unknown amount of int values at some point.
How would I iterate till the end of my array of unknown size?
Also, if it read a blank space would its corresponding position in the array end up junked?
Copying Input From users post below:
Thing is:
a) I'm not allowed to use STL (means: no )
b) I want to decompose a string into its characters and store them. So far I wanted to use a function like this:
string breakLine (string line){
int lineSize = line.size();
const char *aux;
aux=line.data();
int index=0;
while (index<=lineSize){
mySynonyms[index]=aux[index];
index++;
}
I thought that the array aux would end up junked if there was a large blank space between the two numbers to be stored (apparently not). And I was wondering if there was a way to iterate till an undefined end in this type of array. Thanks for you answers.
You don't: wrap the array into a structure that remembers its length: std::vector.
std::vector v(1);
std::for_each( v.begin(), v.end(), ... );
No portable way of doing this. Either pass the size together with the array, or, better, use a standard container such as std::vector
Short answer is that you can't. If you have a pointer to the first element of an array, you can't know what the size of the array is. Why do you want to use a array in the first place. You would be much better off using a std::vector if your array can change size dynamically, or a boost::Array if it will be a fixed size.
I don't understand your second question.
Your code needs to keep to track of the array, so the size would never be unknown. (Or you would have to use some library with code that does this.)
I don't understand the last part of your quesiton. Could you elaborate?
You explained in your post below that you want to look at the guts of a std::string.
If you are expecting your stirng to be like a c-string (aka doesn't contain NULLs), then use line.c_str() instead of line.data(). This will guarantee that aux points to a null terminates c-style string.
After that you can iterate until aux[index] == '\0';
Otherwise, you can use line.data() and string.length/size to get it's size like in your example.
However, "decomposing a string into its characters" is pretty pointless, a string is an array of characters. Just make of copy of the string and store that. You are allowed to do:
char ch = line[index];
Better yet, use iterators on the original string!
for(std::string::const_iterator it = line.begin(); it != line.end(); ++it) {
const char ch = *it;
// do whatever with ch
}
a) I'm not allowed to use STL (means:
no )
What?? Who's moronic idea was that?
std::vector isn't part of the "STL" (which is a copyrighted product of HP), but is (and has been for nearly a decade) part of the C++ Language Standard.
If you're not allowed to use the STL (for whatever reason), the first thing you want to do is actually to implement your own version of it – at least the parts you need, with the level of customizability you need. For example, it's probably overkill to make your own vector class parametrizable with a custom allocator. But nevertheless do implement your own lightweight vector. Everything else will result in a bad, hardly maintainable solution.
This smells like homework, and the teacher's objective is to give you a feeling of what it takes to implement dynamic arrays. So far you're getting an F.
You need to realize that when you allocate memory like this
int *dynArray = new int [1];
you allocate precisely one integer, not an indefinite number of integers to be expanded by some unidentified magic. Most importantly, you can only say
dynArray[0] = 78;
but you cannot say
dynArray[1] = 8973;
The element at index 1 does not exist, you're stepping into memory that was not reserved for you. This particular violation will result in a crash later on, when you deallocate the array, because the memory where you stored 8973 belongs to the heap management data structures, and you corrupted your heap.
As many other responders mention, you must know how many elements you have in the array at all times. So, you have to do something along the lines of
int arraySize = 1;
int *dynArray = new int [arraySize];
arraySize goes together with the array, and is best combined with dynArray in one C++ object.
Now, before you assign to dynarray[1], you have to re-allocate the array:
if (index > arraySize) {
int newSize = index+1;
int *newArray = new int[newSize]
// don't forget to copy the data from old array to new
memcpy(newarray dynArray, sizeof *newArray * arraySize);
arraySize = newSize;
dynArray = newArray;
}
// now you're ready!
dynArray[index] = value;
Now, if you want to make it a bit more efficient, you allocate more than you need, so you don't have to allocate each time you add an element. I'll leave this as an exercise to the reader.
And after doing all this, you get to submit your homework and you get to appreciate the humble std::vector that does all of this for you, plus a lot more.
Use a vector, which has a vector.size() function that returns an integer and a vector.end() function that returns an iterator.
You could create a simple Vector class that has only the methods you need. I actually had to recreate the Vector class for a class that I took this year, it's not very difficult.
If there's a value that cannot be valid, you can use that as a sentinel, and make sure all of your arrays are terminated with that. Of course, it's error-prone and will cause hard-to-find bugs when you happen to miss doing it once, but that's what we used to do while reading files in FORTRAN (back in the all-caps days, and before END= became standard).
Yes, I'm dating myself.