I'm a c++ beginner, I want to initialize an array so that the element of the array is actually a reference to a variable.
string string_1;
string string_2;
string strings[2] = {&string_1, &string_2};
Is this allowed? So any operation done to the array will be applied to the variables string_1 and string_2 themselves?
You can simulate an array of references:
using s_ref = std::reference_wrapper<std::string>;
s_ref strings[] = { std::ref(string_1), std::ref(string_2) };
Or just use pointers (that's really what reference_wrapper does underneath).
Related
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.
I want to ask how a pointer helps a user to input array. I thought constant variables were required to declare an array...
Programming Language is C++ .
C++ is not an IDE, you probably have an IDE that uses a C++ compiler.
Constant variables are NOT needed to declare an array, constant variables are used to declare something that will not be changed.
Arrays are defined by the size, so I suppose that's what you mean by constant. However, the fields in the array are changeable (thus not constant).
To answer your question, using an array is frowned upon when getting input, as you have no idea what the user will input and the size is suppose to be constant.
My suggestion is to use a std::vector as a container to hold and store an ever-expanding collection of data
Here's some more information about arrays, and declaring them / getting input:
Example of a constant array:
const std::string days[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
Example of a non-constant array:
std::string days[5];
Example of getting input from user (and putting it inside the first position of the array (0)):
std::cin >> days[0];
Example of non-constant array using a pointer (this is an array, as it's using the new keyword):
std::string *days;
days = new std::string[5];
Example of using a std::vector (better choice for storing data, that will not be constant in size):
std::vector<std::string> days;
days.push_back("Monday");
If you define a raw C-like array allocated on the stack, like:
int arr[10];
then the element count (in this case 10) must be known at compile-time.
If you still want a raw C-like array, but with size based on some user's input (which happens at run-time), then you can use new[]:
int count; // Elment count
cin >> count; // Read from user
assert(count > 0); // Check validity
// Create raw array on the heap at run-time.
// Use a *pointer* to store the address of the beginning of the array.
int* arr = new int[count];
... work with the array ...
// Cleanup the array
delete[] arr;
Note that in modern C++, it's better to just use std::vector. In this case, you don't need pointers, and dynamic memory allocation (as well as cleanup) happens under the hood of std::vector:
// count read from user input.
// Vector of integers allocated at run-time.
std::vector<int> arr(count);
// ... work with vector ...
// No need to manual cleanup: thank you C++, destructors and RAII.
I have a 4D array and i would like to create a function that i could use to refer to a 2D array inside the 4D array and read its data by appending square braces with indexes to the function call.
int numbers[2][3][4][4] = {
{
{{1,2,3,4}, {4,3,2,1}, {6,7,8,9}, {9,8,7,6}},
{{0,1,0,1}, {1,0,1,0}, {1,1,0,0}, {0,0,1,1}},
{{5,4,1,8}, {4,2,5,1}, {7,2,5,8}, {4,2,5,1}}
},
{ /* same stuff */ }
};
If i wanted to access just {4,2,5,1} for example, i could create a function that returns a pointer to the first int of that array (&number[0][2][1][0]), and access the elements with func()[1], func()[2], func()[3], well... you know that.
int* func() {
return &numbers[0][2][1][0];
}
// func()[2] => 5
But how could i create a function that returns a reference to numbers[0][2], so for example i could do func()[1][0] and it would return 5?
It seems i should work up my understanding of C/C++ pointers, references and arrays, but i will also appreciate "std" and C++11-specific solutions (using some cool std::class over standard arrays). Thanks :)
In C++ the best approach would be to return a reference to a 2D array
int (&func())[4][4] {
return numbers[0][2];
}
Now you can access it as
func()[i][j]
This fully preserves the 2D array type and keeps the natural access syntax.
If you insist on returning a pointer specifically, then you can return a pointer to the first 1D array in that 2D array
int (*func())[4] {
return numbers[0][2];
}
which will preserve the access syntax as
func()[i][j]
but, as you can see, the price of this is decay of 2D array type to 1D array type.
Or, as has already been suggested, you can return a pointer to a 2D array
int (*func())[4][4] {
return &numbers[0][2];
}
but in this case you will have to remember to access that 2D array elements as
(*func())[i][j]
i.e. it preserves the 2D array type, but forces you to use a more convoluted access syntax.
For this reason reference seems to be the best approach (as long as you insist on working with raw arrays), combining the "best" features of both pointer-based approaches.
P.S. Typedefing the 2D array type will produce much more readable function declarations. E.g. if you do
typedef int Numbers2D[4][4];
then the first variant will turn into
Numbers2D &func() {
return numbers[0][2];
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ multi dimensional array
I'm trying to create a class that creates an arbitrary sized array of strings based on one of the objects constructor arguments.
Here, the code for the object constructor I'm trying so far:
commandSpec::commandSpec(int numberOfCommands)
{
std::string * commands = new std::string[3][numberOfCommands];
}
I get an error: 'numberOfCommands cannot appear in a constant expression', could someone show me the correct way to specify an array in an object that i dont know the size of until execution.
Thanks, j
This should probably be implemented as a structure and a vector, like this:
struct command {
std::string first;
std::string second;
std::string third;
};
commandSpec::commandSpec(int numberOfCommands)
{
std::vector<command> commands(numberOfCommands);
}
Of course, you should choose appropriate names for the members of command.
Variable length arrays are allowed only when allocating on heap.
You need to allocate the array in 2 steps - first allocate array with length 3 (from pointers) and then loop through the 3 elements and allocate new string for each.
I'd recommend you to use std::vector instead.
I would use a std::vector instead, makes life easier:
commandSpec::commandSpec(int numberOfCommands)
{
std::vector<std::vector<std::string>> mystrings(numberOfCommands);
}
Invert the order of the dimensions...
commandSpec::commandSpec(int numberOfCommands)
{
std::string (*commands)[3] = new std::string[numberOfCommands][3];
}
However, I highly recommend you consider using vectors instead.
I have the following program where two variables are to be passed by reference to a function where their values will be determined based on external factors before being returned to main() so that they can be used by other functions. The first variable I am trying to pass is an int, and that goes fine, but the other is an array of strings, which is causing me some problems.
I've done enough research into this to know that you can't have an array or references (though I've yet to figure out why) and I was wondering if anyone could help me figure out how to do this? The various methods I've tried have all resulted in segmentation faults.
NB: The code below has the array being passed by value since I just don't know what to write for it.
Update: I'm required to use an array for my coursework. Some other data structure, such as the vector that has been suggested, would be great, but I have to use specific structures.
void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[100]);
int main()
{
int no_of_existing_devices = 0;
string existing_devices[100];
initialise_existing_devices(no_of_existing_devices, existing_devices[100]);
}
void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[100])
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_devices[i] = line;
}
}
A reference to an array looks like:
void f(std::string (&a)[N]) { }
where a is the name of the parameter and N is the number of elements in the array.
However, usually in C++ you don't pass an array by reference (you can; it's just not common). Other options include:
Pass a pointer to the initial element of the array; in this case, consider passing the size of the array as a second argument to the function.
Use a std::vector<std::string> or a std::array<std::string, N> instead and pass it by reference (you can also find the array psuedo-container in Boost; barring that, consider writing your own. If you take a look at the Boost source code, it's quite simple and straightforward).
Pass a pair of iterators (begin and end) to the function and use them to manipulate the range.
The last option is the most idiomatic C++ approach; it is also the most generic because you can use any type of container, including arrays, standard library containers, or containers that you've written yourself.
Since you are actually trying to use the parameter as an "out" parameter, it's probably better just to return a std::vector<string> or a std::array<string, 100> containing the results; this is much cleaner.
this line is not doing what you are expecting:
initialise_existing_devices(no_of_existing_devices, existing_devices[100])
hint: array index, 100 ...
I would suggest that you use a std::vector<std::string> rather than the array and pass that by reference.
EDIT: okay, given the update:
can you use a struct? If so, you can wrap the array in a struct:
struct string_array
{
string data[100];
};
and then define an instance of this in main, and pass that by reference? I'm sure you can fill in the details.. :)
You should use a std::vector<T> for heap-managed arrays or a boost::/std::array<T, N> for stack-based arrays. These objects will hold their own size.
This is one of those things C++ has in common with C. Arrays are not passed by value. They're demoted to pointers to their first elements. The array syntax in the function parameters is essentially just a comment. You can tell by doing a sizeof(existing_devices) inside your function call. So the answer to your question is that you're already doing it.
You can use templates, like so:
template <size_t size>
initialise_existing_devices(int& no_of_existing_devices, string (&existing_devices)[size])
{
}
or you can do:
typedef string hundred_strings[100];
initialise_existing_devices(int& no_of_existing_devices, hundred_strings &existing_devices)
{
}
For the actual argument, use just the array name, which represents the address of the array:
initialise_existing_devices(no_of_existing_devices, existing_devices);
For the parameter, use this for a constant pointer to the array:
void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[])
That said, using a std::vector as the return type or a reference parameter would avoid the need to guess the number of devices before the call.