I am trying to do the following:
in main.cpp:
// Create an array of pointers to Block objects
Block *blk[64];
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
int x_low = i*80;
int y_low = j*45;
blk[j*8+i] = new Block(30, x_low+40.0f, y_low+7.5f, &b);
}
}
And then I am trying to pass it to the graphics object I have created:
Graphics g(640, 480, &b, &p, blk[0], number_of_blocks);
the graphics constructor looks like:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p, Block *blk, int number_of_blocks) {
if I look at what is contained in the array from the graphics object, only the first item exists and then all the other items are in hyperspace:
for (int i=0; i<64; i++) {
printf("for block %d, %f, %f ", i, (_blk+(sizeof(_blk)*i))->_x_low, (_blk+(sizeof(_blk)*i))->_y_low);
printf("blah %d\n", (_blk+(sizeof(_blk)*i)));
}
and if I look at the addresses, they are different (6956552 rather than 2280520 when I examine the addresses in the main class using:
printf(" blah %d\n", &blk[j*8*i]);
I am sure there must be something subtle I am doing wrong as its like I have copied the first item from the blk array to a new address when passed to the graphics object.
Does this make sense? Any ideas?
Cheers,
Scott
If you want to pass the whole array, the constructor should look like this:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p,
Block **blk, int number_of_blocks)
and you should pass the array like this:
Graphics g(640, 480, &b, &p, blk, number_of_blocks);
It looks like:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p, Block *blk, int number_of_blocks) {
is expecting an array of Blocks, not an array of pointers to Blocks. Passing the first element would probably work if you made_number_of blocks 1, but it can't work for anything else using your current data structure. If I were you, I would give up on using arrays and use std::vector instead - it will greatly simplify your code.
The Graphics function is expecting a contiguous array of Block objects in memory and you are creating each new Block independently. Try
Block* blk = new Block[64];
then loop through and initialize each Block's values. This will only work if you can initialize the block objects in another way from using the constructor with arguments since new in this case can only call the default constructor. If the only way to initialize a Block is using the constructor with arguments, you'll have to do something else like passing Block** to the function.
From what I can see, you are passing the first element of the array to the contructor, not the whole array. This is what you are doing:
#include <iostream>
#include <cstdlib>
void foo(int* item, const int length);
int main() {
const int length = 10;
int* array[length];
for (int i = 0; i < length; ++i) {
array[i] = new int(i + 100);
}
foo(array[0], length);
return (EXIT_SUCCESS);
}
void foo(int* item, const int length) {
for (int i = 0; i < length; ++i) {
std::cout << item[i] << std::endl;
}
}
I believe this is what you wanted to do:
#include <iostream>
#include <cstdlib>
void foo(int** array, const int length);
int main() {
const int length = 10;
int* array[length];
for (int i = 0; i < length; ++i) {
int* item = new int(i + 100);
array[i] = item;
}
foo(array, length);
return (EXIT_SUCCESS);
}
void foo(int** array, const int length) {
for (int i = 0; i < length; ++i) {
int* item = array[i];
std::cout << *item << std::endl;
}
}
Regards,
Rafael.
Related
I'm a little stuck with my school project.
So I need to make a dynamic 2-dimensional array.
It has to be created in a function with 3 parameters: 2-dimensional char array, length and width.
This is what I have so far. Length and width come from another function and there are no problems with that. I feel like I am very close but I don't know how do I save the array to theArray[][] and do I need to create a new variable for where i put /*what here?*/ .
Didn't find anything this specific from the web(maybe I just don't know what to search exactly)
Thanks in advance!
void doArray(char theArray[][], unsigned int length, unsigned int width) {
char** /*what here?*/ = new char*[lenght];
for(unsigned int i = 0; i < length; i++){
/*what here?*/[i] = new char[width];
}}
int main() {
unsigned int lenght = 0;
unsigned int width = 0;
char theArray[][];
size(lenght, width);
doArray(theArray, lenght, width);}
A 2-dimensional dynamic array in C++ is: std::vector<std::vector<TYPE>> a(SIZE_M, std::vector<TYPE>(SIZE_N));
#include <vector>
void doArray(auto &theArray, std::size_t length, std::size_t width) {
theArray = std::vector<std::vector<char>>(length, std::vector<char>(width));
}
int main() {
std::size_t lenght = 0;
std::size_t width = 0;
std::vector<std::vector<char>> theArray;
size(lenght, width);
doArray(theArray, lenght, width);
}
Another way would be to use malloc.
char **arr;
arr = (char**)malloc(length * sizeof(char*));
for(i=0;i<length;i++){
arr[i]=(char*)malloc(width * sizeof(char));
}
It's duplicated. See here for a better explanation.
Whatever, this is what you want:
void doArray(char **theArray, unsigned int length, unsigned int width) {
theArray = new char*[length];
for(unsigned int i = 0; i < length; ++i)
theArray[i] = new char[width];
}
Please don't comment I should use size_t instead of unsigned int.
When you want a function to create something, the normal way to to return the created object, not to pass it in as a parameter. I think maybe that is what is confusing you. For some reason beginners have often have trouble with the idea of functions returning things.
So rewriting your code to use a return instead of a parameter, you get this
char** doArray(unsigned int length, unsigned int width) {
char** arr = new char*[length];
for(unsigned int i = 0; i < length; i++) {
arr[i] = new char[width];
}
return arr;
}
Then in main you call the function like this
int main() {
char** theArray;
...
theArray = doArray(length, width);
As others have pointed out, the correct way in C++ to do this is to use a vector. But either way the lesson about writing functions to return values applies.
Below is my current code for my latest assignment and I cannot figure out what the problem is printing the array. Forgive me for the crappy code, in my class we were thrown into C++ and none of us have ever used it before so it may be a simple mistake but no one in the house can help me.
Header file DynamicArray.h:
//
// DynamicArray.h
///#include <rpcndr.h>
#ifndef DYNAMIC_DYNAMICARRAY_H
#define DYNAMIC_DYNAMICARRAY_H
#endif //DYNAMIC_DYNAMICARRAY_H
// union
// intersection
// relative complement
// insertion - if the element is already in the set, then nothing happens
// deletion - if the element is not in the set, then nothing happens
// query to check whether an element is in a set
// query to find the number of number of elements in a set
// display the set
//destructor
// copy constructor
// ***********************************overloading assignment operator***************************************************
class DynamicArray{
public:
DynamicArray(int size);
DynamicArray(const DynamicArray &original, int Size);
/// DynamicArray(int Size);
~DynamicArray();
void Union();
void Intersection();
void Complement();
int Insert(int position, int entry, int size);
int Delete(int position, int entry, int size);
bool Qelement(int size, int entry);
int Qset(int size);
int size = 20;
int *array;
};
//
//
//
Source file DynamicA.cpp- here I define the constructors and member functions:
//
// DynamicA.cpp
//
//Union();
//Intersection();
//Complement();
//Insert();
//Delete();
//Qelement();
//Qset();
#include <iostream>
#include "DynamicArray.h"
using namespace std;
DynamicArray::DynamicArray(int &size = 30){
size = 20;
*array = new int[size];
for(int i = 0; i < size; i++){
array[i] = 0;
};
}
/// DynamicArray::DynamicArray(int Size) {
///
/// }
DynamicArray::DynamicArray(const DynamicArray &original, int size) {
size = original.size;
array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = original.array[i];
}
}
DynamicArray::~DynamicArray(){
delete[] array;
}
void DynamicArray::Union(){
}
void DynamicArray::Intersection() {
}
void DynamicArray::Complement(){
}
int DynamicArray::Insert(int position, int entry, int size) {
if(!Qelement()){
for(int i = size+1; i > position+1; i--){
array[i] = array[i-1];
}
array[position] = entry;
}
}
int DynamicArray::Delete(int position, int entry, int size){
for(int i = 0; i < size; i++){
if(array[i] == entry) {
for(int x = i; x < size; i++){
array[x] = array[x+1];
}
size--;
}
}
}
bool DynamicArray::Qelement(int size, int entry) {
for(int i = 0; i < size; i++){
if(array[i] == entry){
return true;
}
}
}
int DynamicArray::Qset(int size){
return size;
}
main.cpp - this is where my issue is. The error I continue to receive is that dArray is not an array.
//main.cpp
#include <iostream>
//#include <DynamicArray.h>
#include "DynamicArray.h"
//#include "DynamicA.cpp"
//using namespace std;
int main() {
DynamicArray dArray();
for(int i = 0; i < array; i++) {
cout << dArray[i];
}
}
Your class DynamicArray is not an array, the compiler has it right. It's just a class you've defined. For your code to work, you need to overload DynamicArray::operator[](int), for example, like so:
#include <cassert>
int DynamicArray::operator[](int idx)
{
assert(idx < size);
return array[i];
}
The reason is that operator[] is only defined for the built-in array type, where it has an established meaning and understood by the compiler. But you have defined an arbitrary class, and your understanding that it is an array is only your understanding, i.e. an assumption, which in no way is perceived by the compiler, so to say.
Now, let me point this one out before you run into issues caused by that mistake: the fields size and array must be private or at least protected! Read up on encapsulation in C++, as well as the other two or three founding principles of this language. You may wonder how to access the size of the array form the outside given this change, well that's where the so-called getter-setter methods come into play. Define int DynamicArray::size() const { return size; } to let the array tell its size to its clients.
Now you can use the previously defined operator[](int) with int size():
DynamicArray myArray(5);
for(int i = 0; i < myArray.size(); ++i)
std::cout << myArray[i] << " ";
Other errors: two pointed out by#crashmstr: *array = new int[size]; should be array = new int[size]; and DynamicArray myArray(); isn't going to build, since this calls the undefined default constructor.
My weekend assignment was to make a function that gets an array of integers and the size of the array, and creates an array of pointers so that the pointers will be sorted using bubble sort (without changing the original array).
While debugging I found out that it works just fine, but when the function goes back to main() the pointers array gets initialized and everything's gone.
#include <iostream>
using namespace std;
void pointerSort(int arr[], int size, int* pointers[]);
void swap(int a, int b);
void main()
{
int arr[5]={7,2,5,9,4};
int size = 5;
int* pointers[5];
pointerSort(arr, size, pointers);
for (int i = 0; i < 5 ; i++)
cout << *pointers[i] << endl;
}
void pointerSort(int arr[], int size, int* pointers[])
{
int j, i;
bool change = true;
pointers = new int*[size];
for (i = 0; i < size; i++)
pointers[i] = &arr[i];
i = 0;
j = 1;
while (i <= size-1 && change == true)
{
change = false;
for (i = 0; i < size-j; i++)
{
if (*pointers[i] > *pointers[i+1])
{
swap(pointers[i], pointers[i+1]);
change = true;
}
}
j++;
}
}
void swap(int&a, int&b)
{
int temp;
temp = a;
a = b;
b = temp;
}
pointers = new int*[size];
At this point pointers is already an array of pointers, no allocation is needed.
After this line pointers IS NO LONGER THE ARRAY IN YOUR MAIN FUNCTION.
This is why your function is failing, because you are reassigning the array to which pointers is pointing to. The original array ISNT getting reinitialized, its just ignored throughout the entire code.
It is also a memory leak as ATaylor mentions, since you do not delete the allocated space, and cannot delete the space after the function finishes.
To fix everything: just remove the above line.
I'm trying to create a function that would dynamically allocate an array, sets the values of the elements, and returns the size of the array. The array variable is a pointer that is declared outside the function and passed as a parameter. Here is the code:
#include <cstdlib>
#include <iostream>
using namespace std;
int doArray(int *arr) {
int sz = 10;
arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
For some reason, the program terminates on the first iteration of the for loop in main()! Am I doing something wrong?
If you want to allocate memory that way you have to use:
int doArray(int*& arr)
else the pointer will only be changed inside the function scope.
You're passing in the array pointer by value; this means that when your doArray function returns, the value in arr in main is still NULL - the assignment inside doArray doesn't change it.
If you want to change the value of arr (which is an int *), you need to pass in either a pointer or a reference to it; hence, your function signature will contain either (int *&arr) or (int **arr). If you pass it in as a ** you'll also have to change the syntax inside the function from using arr to *arr (pointer-dereferencing), and you'll call it like so: doArray(&arr).
Also, in C++ you should really be using new int[sz] instead of malloc.
You need to add an extra level of indirection to doArray. As written it allocates the array properly but it doesn't communicate the pointer value back to the caller correctly. The pointer from malloc is lost once you return.
If you wrote a function to take a float and change the value, passing the changed value back to the caller, it would need to take a pointer: foo(float *f). Similarly, here you want to pass back an int* value to the caller so your function must be declared as doArray(int **arr) with a second asterisk.
int doArray(int **arr) {
int sz = 10;
*arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
(*arr)[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
Notice how it now dereferences *arr inside of doArray, and how the call is now written as doArray(&arr).
The arr variable in your function is a local copy of the arr pointer in the main function, and the original is not updated. You need to pass a pointer-to-pointer or pointer reference (the former will also work in plain c, the later only in c++).
int doArray(int **arr)
or
int doArray(int*& arr)
Change signature to (specific for c++):
int doArray(int *&arr)
so pointer would be changed at exit from doArray.
You need a pointer to a pointer in your doArray() parameter. If you've never done any programming with pointers before, this can be confusing. I find that it can be easier to see the right types if you annotate your code abundantly with typedefs.
You have the right idea that (int*) can be used to represent an array. But if you want to change the value of your variable arr in main(), you need a pointer to that, and so you will end up with (untested code) something like the following
typedef int *IntArray;
int doArray(IntArray *arr) {
int sz = 10;
*arr = (IntArray) malloc(sizeof(int) * sz);
IntArray theArray = *arr;
for (int i=0; i<sz; i++) {
theArray[i] = i * 5;
}
return sz;
}
when calling doArray, you will need to pass the address of your variable (so doArray knows where to write to):
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
This should work.
As others have pointed out, you're passing your array (the int *) by value, so when you say arr=... you're not actually changing the array you passed in.
You're also got a memory leak, as you've written it. It's not a big deal when you only call doArray once in the body of your program, but if it gets called repeatedly and the array is never freed (or deleted, if you made it with new) then it can cause problems. Typically the best way to deal with this is by using the STL. You'd then write
#include <vector>
#include <iostream>
int doArray(std::vector<int> &arr) {
int sz = 10;
arr.resize(sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
std::vector<int> arr;
int size = doArray(arr);
for (int i=0; i<size; i++) {
std::cout << arr[i] << std::endl;
}
return 0;
}
However, with the STL there are more idomatic ways than returning the size, since you can just ask for arr.size(), and if you get really fancy, can use functions like for_each or the ostream_iterator to print all your elements.
Is there some way to delay defining the size of an array until a class method or constructor?
What I'm thinking of might look something like this, which (of course) doesn't work:
class Test
{
private:
int _array[][];
public:
Test::Test(int width, int height);
};
Test::Test(int width, int height)
{
_array[width][height];
}
What Daniel is talking about is that you will need to allocate memory for your array dynamically when your Test (width, height) method is called.
You would declare your two dimensional like this (assuming array of integers):
int ** _array;
And then in your Test method you would need to first allocate the array of pointers, and then for each pointer allocate an array of integers:
_array = new *int [height];
for (int i = 0; i < height; i++)
{
_array [i] = new int[width];
}
And then when the object is released you will need to explicit delete the memory you allocated.
for (int i = 0; i < height; i++)
{
delete [] _array[i];
_array [i] = NULL;
}
delete [] _array;
_array = NULL;
vector is your best friend
class Test
{
private:
vector<vector<int> > _array;
public:
Test(int width, int height) :
_array(width,vector<int>(height,0))
{
}
};
I think it is time for you to look up the new/delete operators.
Seeing as this is a multidimensional array, you're going to have to loop through calling 'new' as you go (and again not to forget: delete).
Although I am sure many will suggest to use a one-dimensional array with width*height elements.
(Months later) one can use templates, like this:
// array2.c
// http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html
// is professional, this just shows the principle
#include <assert.h>
template<int M, int N>
class Array2 {
public:
int a[M][N]; // vla, var-len array, on the stack -- works in gcc, C99, but not all
int* operator[] ( int j )
{
assert( 0 <= j && j < M );
return a[j];
}
};
int main( int argc, char* argv[] )
{
Array2<10, 20> a;
for( int j = 0; j < 10; j ++ )
for( int k = 0; k < 20; k ++ )
a[j][k] = 0;
int* failassert = a[10];
}