I have this main function and i want to get an multidimensional array out of this to generate a graph instead of cout
int main(){
zoro z;
std:ifstream k("ggg.grf");
z.getfromstream(k);
for(int i =0 ; i < z.nnodes; i++){
edge_iteratore s = z.begin(i);
while(s != z.end(i)){
std:cout << "(" << (*s).height << "," << (*s).weight << ")" << std::endl;
++s;
}
}
return 0;
}
I' trying to get std::out to a function to generate a multidimensional array
so i have implemented this function to get an array,
int createarr(height,width){
int** ary = new int*[height];
for(int i = 0; i < height; ++i)
ary[i] = new int[weight];
}
but nothing works, how can i return an multidimensional array to use it in another function call instead of outputting it to the screen.
If height and weight are constexpr values you know at compile time, declare std::array<<std::array<int>, weight>, height>. This gets you locality of reference. If they are values you compute at runtime or that could vary, use vector<vector<int>>(height) and initialize each row. Then the compiler takes care of freeing the memory for you. If only one is fixed, you can also do a vector of arrays or an array of vectors.
It’s unfortunate that, because of the legacy char** argv interface of main(), every beginning C and C++ programmer thinks that’s how you do a two-dimensional array. A ragged array like that is almost never what you really want. But if you do, use std::vector to manage the memory for you.
The problem with your createarr() as written is that it doesn’t return any array pointer, but RAII is more likely what you want. And if you do have a sparse matrix that would benefit from raggedness, you can use a format like Compressed Sparse Row.
You need to return a pointer to the created array.
But you'll need to somehow deal with the fact that this is dynamically allocated memory, ie, you need to release it when you're done.
And you'll need to somehow encapsulate the dimensions too, which then means it needs to be a struct.
When you finally get tired of dealing with memory leaks, and understand how pointers work, use std::vector like the other guy said.
In the meantime, don't try to implement complicated algorithms in C without understanding the basics first. Brush up hard on how pointers and arrays actually work, first.
Related
In the case I am creating an 'array' on stack in c++, is it better to initialise an empty vector with a reserved number of elements and then pass this to a function like foo() as a reference as below. Or is it better to set an array arrb of size nelems, then using a pointer p_arrb to the address of the first element increment the pointer and assign some value?
#include <iostream>
#include <vector>
void foo(std::vector<int>& arr){
int nelems = arr.capacity();
for (int i = 0; i < nelems; i++){
arr[i] = i;
}
}
int main()
{
int nelems;
std::cout << "Type a number: "; // Type a number and press enter
std::cin >> nelems;
std::vector<int> arr;
arr.reserve(nelems); // Init std lib vector
foo(arr);
int arrb[nelems];
int* p_arrb = &(arrb[0]); // pointer to arrb
for (int i = 0; i < nelems; i ++){
*(p_arrb++) = i; // populate using pointer
}
p_arrb -= nelems; // decrement pointer
return 0;
}
It seems people prefer the use of vector as it is standardised and easier to read? Apart from that, is there any performance benefit to using vector instead of a basic pointer in this case where I do not need to change the size of my vector/array at any point in the code?
What you should use depends on the exact goal you have. In general the best approach is to avoid using "raw arrays" (both dynamic and static) wherever possible.
If you need dynamic array, use std::vector. If you need static array, use std::array.
You can't use the arrb variant because the size of an array must be a compile-time constant in C++, but you are trying to use a runtime size here.
If your compiler is compiling this, then it is doing so only because it supports these so-called variable-length arrays as a non-standard extension. Other compilers will not support them or have differing degree of support or behavior. These arrays are optionally-supported in C, but even there they are probably not worth the trouble they cause.
There is no way to allocate a runtime-dependent amount of memory on the stack in C++ (except if you misuse recursive function calls to simulate it).
So yes, you should use the vector approach. But as discussed in the comments under the question, what you are doing is wrong and causes undefined behavior. You need to either reserve memory and then emplace_back/push_back elements into the vector or you need to resize the vector to the expected size and then you may index it directly. Indexing a vector outside the the range of elements already created in it causes undefined behavior.
I have a dynamically populated array of strings in C++:
string** A;
it is populated like this:
A = new string*[size1];
and then:
for (unsigned int i = 0; i < size1; i++)
{
A[i] = new string[size2];
for (unsigned int j = 0; j < size2; j++)
{
A[i][j] = whatever[j];
}
}
elsewhere, I want to find out the dimensions (size1 and size2).
I tries using this:
sizeof(A[i]) / sizeof(A[i][0])
but it doesn't work.
Any ideas ?
Thanks
When you allocate memory via new T[N], the value N is not stored anywhere . If you need to know it later, you will need to keep track of it in your code.
There are pre-existing classes for allocating memory that also remember the length that was allocated. In your code:
vector<vector<string>> A(size1, vector<string>(size2));
// (code to populate...)
then you can access A.size() to get size1, and A[0].size() to get size2.
If the dimensions are known at compile-time you may use array instead of vector.
It is very simple to find the size of a two dimensional (more exactly of one-dimensional dynamically allocated arrays) array. Just declare it like
std::vector<std::vector<std::string>> A;
and use
std::cout << A.size() << std::endl;
As for your approach then you have to store the sizes in some variables when the array is allocated.
If you are learning C++, I would recommend that you learn Classes. With a class you can encapsulate int variables along with your 2D array that you can use to store the dimensions of your array. For example:
class 2Darray{
string **array;
int rows;
int cols;
}
You can then get the dimensions of your 2Darray object anytime by reading these member variables.
vectors will do this for you behind the scenes but its good for you to learn how to do this.
You can't create an array just using pointer operator. Every array is basically a pointer with allocated memory. That's why compiler wants constant before creating array.
Basically; sizeof(A[i]) won't give you the size of array. Because sizeof() function will return the a pointers size which is points to A[i] location. sizeof(A[i]) / sizeof(A[i][1]) will probably give you 1 because you are basically doing sizeof(int)/sizeof(int*)
So you need to store the boundary yourself or use vectors. I would prefer vectors.
Can't get array dimensions through pointer(s)
Inside a function, I make a 2d array that fills itself from a text file and needs to get returned to main. The array stays a constant size through the whole program.
I know this is something that gets asked a lot, but I always seem to get one of two answers:
Use std::vector or std::array or some other STD function. I don't really understand how these work, is there any site actually explaining them and how they act compared to normal arrays? Are there any special #includes that I need?
Or
Use a pointer to the array, and return the pointer. First, on some of the answers to this it apparently doesn't work because of local arrays. How do I tell when it does and doesn't work? How do I use this array back in the main function?
I'm having more trouble with the concept of pointers and std::things than with the actual code, so if there's a website you know explains it particularly well, feel free to just put that.
Not necessarily the best solution, but the easiest way to get it working with vectors. The advantages are that you don't need to delete memory (happens automatically) and the array is bounds-checked in debug mode on most compilers.
#include <vector>
#include <iostream>
using array2D = std::vector< std::vector< int > >;
array2D MyFunc(int x_size, int y_size)
{
array2D array(y_size, vector< int >(x_size));
int i = 0;
for (int y = 0; y < array.size(); y++)
{
for (int x = 0; x < array[y].size(); x++)
{
// note the order of the index
array[y][x] = i++;
}
}
return array;
}
int main()
{
array2D bob = MyFunc(10, 5);
for (int y = 0; y < bob.size(); y++)
{
for (int x = 0; x < bob[y].size(); x++)
{
cout << bob[y][x] << "\n";
}
}
}
Live example:
http://ideone.com/K4ilfX
Sounds like you are new to C++. If this is indeed the case, I would suggest using arrays for now because you probably won't be using any of the stuff that STL containers give you. Now, let's talk about pointers.
You are correct that if you declare a local array in your function, the main function won't have access to it. However, this is not the case if you dynamically allocate the array using the new keyword. When you use new to allocate your array, you essentially tell the compiler to reserve a chunk of memory for your program. You can then access it using a pointer, which is really just the address of that chunk of memory you reserved. Therefore, instead of passing the entire array to the main function, all you need to do is pass a pointer (address) to that array.
Here are some relevant explanations. I will add to them as I find more:
Dynamic Memory
The easiest way to create a 2d array is as follows:
char (*array)[10];
array = new array[5][10];
Two dimensional arrays can be tricky to declare. The parenthesis above in the variable declaration are important to tell the compiler array is a pointer to an array of 10 characters.
It is really essential to understand pointers with C and C++ unless using the std:: collections. Even then, pointers are widely prevalent, and incorrect use can be devastating to a program.
#include<iostream>
using namespace std;
int main() {
int *p=new int [10];
}
After creating the array, I am confused and want to know if it's possible to do the following:
read an array of integers without builtin arrays such as vector.
print out this array.
Is there any built-in command that we can use in cpp to get the actual size of the array, which means we don't have to use sizeof(*p)/size(p[0]).
And what do you think will be the easiest way of doing this task, on the condition that we still use the pointer of an array.
Thanks for helping me out!
I think you could use std::for_each. Together with c++ lambda functions it is a very comprehensive tool:
for_each(p, p+10, []->(int element){ cout << element; })
sry, I didn't compile the code above, so it might contain errors. But the pattern is clear, I hope.
If your compiler does not support lambdas, you can use functors or function pointers (just google for it). I really like this approach and I don't like loops either.
But, of course as mentioned above, internally the for_each loops.
This does not create an array, but it gives you a pointer to a single integer.
int *p=new int;
change this for example to:
const unsigned size = 10;
int * p = new int[size]; /*dont forget to call delete[] on p when you are ready.*/
Now p points to 10 ints, you know the size since you've put size to 10.
Sure you can print the values of p without a loop
/*Assuming you initialize the values.*/
cout << p[0];
cout << p[1];
/*etc*/
cout << p[9];
That said I think the easiest way to solve your problem is to use vector<int> ( but this doesn't satisfy you first point ). You'll always get the proper size of a vector with vector<TYPE>::size() and a intance of vector makes it easy to iterate ( which is also looping ) over the items to print them.
You would have to print the array manually one item by one... accessing every value, like:
cout << "index 5:" << p[5] << endl;
I think that the loop is a way to go. I would avoid a loop only if the array had few items, and fixed length like 3 to 5 items or so and desperately needed to optimize the code for speed, but not with console output which will be slow anyway. But the compilers usualy support loop unrolling optimalisations.
#nio, but dude, I think I still have trouble of doing this. for example, is there any way that I can input in this simple way "1 2 3 4" with space and then it reads the array? or I have to do it with enter? (Now, I don't care if we use loop or not any more :P) – Cancan
This code will read 4 items separated by combination of spaces and newlines:
int *p=new int[10];
int i;
for(i=0;i<4;i++)
{
cin >> p[i];
}
for(i=0;i<4;i++)
{
cout << "index " << i << " :" << p[i] << endl;
}
1. read an array of integers without using loops nor some builtin arrays such as vector.
Recursion. Everything that can be done using loops can be done recursively.
2. print out this array without using loop.
Recursion too.
3. Is there any built-in command that we can use in cpp to get the actual size of the array, which means we don't have to use sizeof(*p)/size(p[0]).
No, when you're using arrays in c++ you need to remember the length of an arrays by yourself. sizeof(*p)/size(p[0]) won't help you too
I have a problem with an array of pointers to objects :(..
I need to generate a dynamic vector of object and then return it in
order to manipulate it in another class. In the code below there is
Event class that is abstract and CarArrival that inherits from it and
can be instantiated.
Inside the class that generate and fill the array I have this function:
Event** EventGenerator::getEvents() {
Event* cars[EVENTS];
for (int i=0; i<EVENTS; i++) {
cars[i] = new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4)));
}
sort(cars, cars+(EVENTS), Event::cmp);
return cars;
}
I invoke this function in onther class in this way:
Event** cars = generator->getEvents();
for(int i=0; i<EVENTS; i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
after the print of the first element i get "Segmentation Fault".
I have read some things online and I understand that I mistake since (*cars) evaluates to a
pointer to the first element of the array, in fact I can print the first element and not the other, but I cannot figure out how to access every element of the array in the second class.
How can I face this?
Thanks to all,
Alberto
I'd suggest that you use a std::vector<Event*> instead. You'll save a lot of pain this way. It takes care of all the nasty memory management in the background, and you can easily push any number of items into it. The best part in your case is, that you can simply return a vector which is not safe with a normal array.
Also your Event* cars[EVENTS]; is declared locally in you function. After you have finished it, it ceases to exist, which might cause your Segfault. You'd have to dynamically allocate the array with new, but still, try it with std::vector, see the documentation here.
EDIT: Sample Usage:
std::vector<Event*> EventGenerator::getEvents() {
std::vector<Event*> cars;
for (int i=0; i<EVENTS; i++) {
cars.push_back(new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4))));
}
sort(cars.begin(), cars.end(), Event::cmp);
return cars;
}
std::vector<Event*> cars = generator->getEvents();
for(int i=0; i<cars.size(); i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
I believe the cleanest way to handle a dynamic vector of pointers to dynamically allocated objects is to use a boost::ptr_vector. It handles everything you need, including allocation of the space to store the pointers, and deletion of those pointers afterwards.
Wouldn't be better to return vector<Event*> or vector<shared_ptr<Event>> instead of raw pointers? This way you would gain:
Automation of the memory management
Dynamic array with built-in length instead of fixed one
As mentionned by Constantinuis, you are returning the value of a pointer to a memory location that is only valid in the scope of the getEvents() function (it's allocated on the stack). You're bound to get a segfault next time.
You probably want to allocate the memory for this array in the heap (using 'new' if my C++'s isn't too rusty), and then you'll have to deal with freeing the memory later.
http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter13.html