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.
Related
If i have array of pointer to an array of pointer to int
int **arrs = new int *[n];
and assign each element to new array of pointer to int
for i<n
arrs[i] = new int[size]
Now, when i try to get size of these arrays, give me wrong value
int size = sizeof(arrs[0])/sizeof(int);
It gives me wrong value.
So how can i get the right value ?
You can't. arrs[0] is a pointer, so sizeof(arrs[0]) gives the size of that pointer.
It comes as a surprise to some that there is no way to get the size of an array from only a pointer to that array. You have to store the size somewhere else.
In C++ the simplest and best solution is to use std::vector. Why reinvent the wheel? std::vector has everything you would want from a dynamic array, and should be the first choice in this situation.
I was recently learning to use struct datatype in c++. I know how the basics of struct datatype work and how to manipulate its variables. But I was wondering how would I determine the end of struct datatype array. For example consider the code below:
struct PersonDetails
{
string name, address;
int age, number;
}
Now in c++ program I create an array of struct type as follows:
PersonDetails Data[500];
Now consider that I have 30 records in data array and I have to display these records by looping through data array's index. So how would I determine that I have to loop through only first 30 indexes as the data is only stored in these indexes. As in char array we compare all indexes with '\0' to determine the end of array. Then what method will we use for Data[] array?
An edit that I have no idea about Vectors and the project i am working on requires me to use basics of c++(functions, control structures, loops, etc.).
It's not feasible.
For char[], back in times of C standardization, developers agreed to use \0 (integer value 0) as a special character marking end-of-string. Everything works as long as everyone is following this convention (i.e. both standard library functions and developers using those functions).
If you wanted to have such a convention for your type, you could just write down "Data object with both strings empty and both ints equal to 0 is array terminator", but you would have to follow this convention. You'd have to write functions that would stop processing array upon finding such an object. You'd have to make sure that in every array there is at least one such object.
Instead
You should use std::vector<Data> which can automatically accomodate for any number of Data objects and will now precisely how many of them are currently stored (using size() method)
or
use std::array<Data, 30>, which can store exactly 30 objects and you can assume all of them are valid objects.
IMHO the correct way to solve this is to not use a C-style array, but instead use a std::array or std::vector that knows it's .size().
Iterating a std::vector or std::array is trivial:
for (const auto& element : Data_array) {
// Do something with the array element
}
See also:
https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/language/for
https://en.cppreference.com/w/cpp/language/range-for
The simplest solution is to just have a separate variable specifying how many array elements are filled in.
PersonDetails Data[500];
int numPersons = 0;
Data[0].name = ... ;
Data[0].address = ...;
Data[0].age = ...;
Data[0].number = ...;
numPersons = 1;
Data[1].name = ... ;
Data[1].address = ...;
Data[1].age = ...;
Data[1].number = ...;
numPersons = 2;
...
Then you use that variable when looping through the array.
for (int i = 0; i < numPersons; ++i)
{
// use Data[i] as needed...
}
I don't really agree using std::array makes any difference.
The problem you currently have doesn't occur in whether we have such an element in the container, but whether the element we are inspecting useful.
Consider the example you gave, for an array of chars, we simply check whether one of the elements is \0 to decide whether or not we should halt the iteration.
How does that work? The ramaining elements, of course, default initialized to be \0, they exist, but of no use.
Similarly, you can check, in this example, whether
name.empty()
Or, in order to avoid any possible exception, as mentioned in the comment section, do this:
add user-defined constructor to the class ( or struct, they are same actually.) which initialize age to -1 and then check if age == -1.
because it's impossible for a people not having any name, that means, you have not assign to any of the remaining elements. Thus, stop iteration.
As a supplement, using std::vector makes sense, but if that isn't a option for you for the time being, you don't need to consider it.
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.
I have an C++ SDK that requires a char[][512] as a parameter. I know that this is supposed to be a list of file names and the number of files could vary. For the life of me I cannot figure out how to declare this. I have an array of CStrings and I am trying to copy them over using strcpy_s and then pass them into the SDK. Any idea on how to do this?
This declaration has a special meaning when used to declare parameter of a function. Within the parameter list it is equivalent to char[100][512], char[123][512], char[3][512] (you get the idea - the first size can be just anything, it is simply ignored) and also to char (*)[512]. Effectively, it will accept as an argument a 2D array of chars with flexible (arbitrary) first size.
The array that you will actually pass to this function should be declared with a concrete first size, for example
char names[3][512] = { "abc", "cde", "fgh" };
if you know the first size at compile time, of course.
If the first size is only known at run time (say, n), you'll have to allocate the array dynamically
char (*names)[512] = new char[n][512];
// Now fill it with names
or, more elegantly, with a typedef
typedef char TName[512];
TName* names = new TName[n];
// Now fill it with names
I expect that the SDK function you are talking about also asks you to pass the first size of the name array as another parameter.
It means 2D array of char. The number of rows could vary, and it should/may be specified in another parameter. C/C++ compilers need to know the number columns when a 2D arrays is passed ,So they can build the mapping function. Simply because arrays decay to pointers when they are passed as parameters, size information is lost. For example:
void fun(char matrix[][512], int rows);
...
char matrix[100][512];
...
fun(matrix, 100);
The mapping function that the compiler construct for a 2D array is similar to:
// arrays in C/C++ are stored in Row-Major Order
matrix[i][j] == matrix[i*numberOfColumns + j]
As you can see, when a 2D array is passed and the size information is lost, we need only the number of columns to index any element in this array.
Here is a way to convert an argv-style array of filenames into the form your SDK needs.
typedef char Char512[512];
Char512 * convert(const char *names[], int n)
{
Char512 * arr;
arr = new char[n][512];
for (int i = 0; i < n; n++)
::strncpy(arr[i], names[i], 512);
return arr;
}
When in doubt, use a typedef.
Just a reminder, if you new[] something, you must delete[] (not delete) it sometime.
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.