how to pass array size to function in C++ - c++

just I want to ask how can I pass array size to throw function to set size of my game recoreds the only reason I am not using vector because I will base this recored to PMI lib and it doesn't support C++ Constrainers because it written in C that's why I use array
void playGame(int max_streak_length)
{
int tracker =0 ;
const int arrsize = max_streak_length;
int gameRecored[arrsize]={0};
while( tracker < 4)
{
Craps games;
if( games.Play()== true)
{
tracker++;
}
else
if(tracker >0)
{
gameRecored[tracker-1]++;
tracker = 0;
}
}
gameRecored[tracker-1]++;
int v= 0;
}

C++ does not support the variable length array feature available in C.99. However, C++ offers std::vector<> which is as easy to use, and some may say safer.
std::vector<int> gameRecored(arrsize, 0);
You can use gameRecored as an array like you do in your current code, and it will clean itself up when the function call returns.

you can't not define an array whose size is a VARIABLE. If you want a dynamic size, you should use operator new, just like this:
int mysize = 10;
int* array = new int[mysize];
the variable mysize can be a dynamic number, such as function parameter.
If your array will never change its size, you can use :
int array[10];
remember, if you use operator new, you must use operator delete to delete your array when you don't need it.
Hop can help you.

Related

Make array in cpp

I am trying to make a new array in my project
the code is:
#include <iostream>
using namespace std;
void makeArray( int *& arrayPtr, int size );
int main( )
{
int * arrPtr;
int size =10;
makeArray( arrPtr, size );
for(int j=0;j<size;j++)
{
cout<<arrPtr[j]<<endl;
}
}
void makeArray( int *& arrayPtr, int size )
{
int arr[size-1];
for(int i=0;i<size;i++)
{
arr[i]=0;
}
*&arrayPtr=*&arr;
}
According to the requirements i need to use the above "makeArray" method inorder to make the array.
When i run the code the output is garbage values not zero.....
any help will be appreciated
thank you
The way you are creating the array is on the stack, which means that it will not exist after the makeArray function finishes.
You will need to allocate the array on the heap.
So:
int arr[size-1];
should be:
int *arr = new int[size-1];
Also, I think you mean to do this in makeArray():
arrayPtr = arr;
Instead of:
*&arrayPtr=*&arr;
Which compiles but is more complex and is functionally the same thing in this context.
But you may prefer just returning an int* instead of taking a reference to the pointer.
Then when you are done using the array in main(), and set it to NULL just in case you accidentally use it again, like this:
for(int j=0;j<size;j++)
{
cout<<arrPtr[j]<<endl;
}
delete [] arrPtr;
arrPtr = NULL;
Why are you declaring a parameter as 'int *& arrayPtr'? Do you just need a pointer to an array? You should use 'int *arrayPtr' instead.
To answer your question, the problem is that you are declaring an array in the function makeArray's stack. Upon the completion of a function, that function's stack is destroyed, so you're passing the address of junk data. To avoid this, use dynamic memory allocation instead.
EDIT: Also, you should use memset instead of a for loop to zero an array. It's much faster.
The "arr" which you allocate in "makeArray()" is local. and when the functione is over the array is release. When you back to main you get garbage.
What you want to do, is to use the "new" operator to allocate this new array to be used in all program, unless you will free this memory by "delete".
so you can set your makeArray() to:
int* makeArray(int size )
{
int *arr = new[size];
for(int i=0;i<size;i++)
{
arr[i]=0;
}
return arr;
}
the in you main you need to initialize your arry by:
int * arrPtr = makeArray(10);
just don't forget to release this memory after you finsh:
delete[] arrPtr ;

What's the best way to rewrite this generic function I wrote in C++ in C?

//Prints out a given array
template <typename T>
void print(T t)
{
for(int i = 0; i < t.size(); i++)
{
cout << t[i] << " ";
}
cout << endl;
}
I have an idea but it includes passing the size of the array. Is it possible to avoid this?
*Update
Thanks for all of the answers/ideas but this problem is getting way deeper than my snorkeler can handle. I wanted to rewrite my C++ code in C because it was horribly written and slow. I see now that I have an opportunity to make it even worse in C. I'll rewrite it from the ground up in Python(performance be damned). Thanks again
If you don't have ELEMENTS, it's
#define ELEMENTS(a) (sizeof(a)/sizeof(*a))
Then,
#define print_array(a, specifier) print_array_impl(a, specifier, ELEMENTS(a), sizeof(*a))
void print_array_impl(void* a, char* specifier, size_t asize, size_t elsize)
{
for(int i = 0; i < asize; i++)
{
// corrected based on comment -- unfortunately, not as general
if (strcmp(specifier, "%d") == 0)
printf(specifier, ((int*)a)[i]);
// else if ... // check other specifiers
printf(" ");
}
printf("\n");
}
Use like this
print_array(a, "%d") // if a is a int[]
and, a needs to be an array name, not a pointer (or else ELEMENTS won't work)
You cannot know what is the size of an array without passing the size of that array (except operating with sizeof in static arrays). This is because the a pointer to a block of memory will only point to the base of the block of memory, from which you can know where the array/block of memory starts, but as there is no end defined you cannot determine where it will end.
You either need to set your own length per array and preserve it, and use it with the array like as described:
You can make a new type like:
struct _my_array {
typename arr[MAX];
int n;
} my_array;
OR
struct _my_array {
typename *arr;
int n;
} my_array;
In this case you need to allocate the a block of memory dynamically with new or malloc , and when finished free the memory with delete or free (respectively).
Or you can simply pass the array number of elements through the function.
Another way is to use a special terminator value of your array type which if encountered will be determined as the end of the array. In this case you need not preserve the size. For example a string is '\0' terminated, so all the string functions know that when a '\0' character is encounter in the char array it will consider that the string has end.
UPDATE
Because this is a generic function and the array can be of any type, one thing which you can do is like this:
struct _my_generic_arr {
void *arr;
int n;
int type;
} my_generic_arr;
When populating this array you can use any type. To identify which type, pass an identified in the type component. Each unique value will determine which type does the arr pointer actually points to (was actually the intended type to be pointed). The n will define the length. Now, depending on different values of type make a switch - case or an if - else ladder or nest, and process the array as you need.
It is impossible in c to track the size of an array in other block,,
It would be a better option to pass the size of the array along..
The other option would be to declare a global variable that has the size and using that variable inside the function
Eg,,
int size=<some value>
void main()
{
int arr[<same value>];
}
void print(T t)
{
for(int i = 0; i < size; i++)
{
printf("%d ",t[i]) //assuming T as int
}
printf("\n");
}
In C, you would need to pass two additional parameters: the size of the array (as you mentioned), and some way of indicating how to convert t[i] into a string. To convert t[i] to a string, you could create a custom switch statement to decode possible types, pass a pointer to a function that will return the string pointer, or you could pass the printf format specifier (e.g. "%d" for integer).
The problem is larger than you think. If you have an array of size 12, how do you know what data is held in that array? It could be 3 char*'s (on 32 bit system), 3 int32_t's, or even 12 chars. You have no way of knowing how to interpret the data. The best you could do is to implement your own version of a v-table and putting a print or toString function into it.
typedef struct {
void *array;
size_t length;
int element_width;
printer_t to_string;
} container;
printer_t is a type that describes a function pointer that takes an element pointer and returns a string (or prints it, if you don't want to free the string). This is almost never worth doing in C. That doesn't mean it can't be done. I would emphasize, though, that none of this is intended to imply that it should be done.
The function itself would look something like this:
void print(container *thing)
{
size_t offset;
int width;
char *stringified;
width = thing->element_width;
for (offset = 0; offset * width < thing->length; offset += width)
{
stringified = thing->to_string(thing->array + offset);
printf("%s ", stringified);
free(stringified);
}
}
What this does is essentially turn a struct into a faux class with a function pointer for a method. You could be more object-oriented and put the method in the type being printed and make it an array of those instead. Either way, it's not a good idea. C is for writing C. If you try to write in a different language, you'll end up with all sorts of terrible stuff like this.

Dynamic array and void pointers

I have quite peculiar problem. I want initialize an array pointed by a void pointer to which memory is allocated using new as shown below.
const int ARRAY_SIZE = 10;
void InitArray()
{
int *ptrInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrInt[i] = 1; //OK
}
void *ptrVoid = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
*(int*)ptrVoid[i] = 1; //Culprit : I get a compiler error here
//(error C2036: 'void *' : unknown size)
}
}
Now, I want to initialize the elements of this array which is pointed by ptrVoid with say 1. How do I go about it? With this code I get a compiler error as shown in the code(I am using VS 2010). Any suggestions?
You have an order of operations problem (and an extra *). Try this inside your second loop:
((int *)ptrVoid)[i] = 1;
*(int*)ptrVoid[i] is *((int*)(ptrVoid[i])), and you're dereferencing too many times (the [] does a dereference).
Write ((int*)ptrVoid)[i] (or, better, static_cast<int*>(ptrVoid)[i]) then re-consider your use of void* at all.
You just need to parenthesize correctly and cast the void* to an int*, so that the compiler knows how many bytes to offset when you index it with [i].
for(int i=0; i<ARRAY_SIZE;i++)
{
((int*)ptrVoid)[i] = 1;
}
How about:
int* ptrVoidAsInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrVoidAsInt[i] = 1;
}
void* ptrVoid = ptrVoidAsInt;
But, one has to wonder what the meaning of either a void array or 1 initialised data is. Is this really an array of int or some other type that is going to be passed as a void* and then recast back to a typed array?

C++: How to read dynamic data elegantly into a struct?

Lets say i store headers in some file, but some part of the header is dynamic length, something like this it would look:
struct HeaderTest {
int someparam;
int more;
int arrsize; // how big array, read arrsize elements into arr:
int arr[arrsize]; // not valid
};
Is there some elegant way for reading dynamic data into a struct?
Instead of having arr and arrsize variables in your struct, you can define your struct like this:
struct HeaderTest
{
int someparam;
int more;
std::vector<int> data;
}
No arr, no arrsize. Just use std::vector, and std::vector::size(). That is elegant!
And if you want to read binary data from a file, then you can write like this:
struct HeaderTest
{
int someparam;
int more;
int size;
char *data;
}
Otherwise, go with the first struct!
An Advice:
Reading your comments everywhere, I feel that I should suggest you to get a good book, and study it first. Here is list of really good books:
The Definitive C++ Book Guide and List
Well, if you don't want to use a container class (not sure why you wouldn't) you can declare arr as a pointer to int and leave it to the client to initialize the pointer to a valid memory location as well as correctly initialize arrsize.
That said, you should just use a vector. Why make things more difficult than they need to be?
This answer is more C than C++, but, you can easily make use of realloc() to resize a buffer to be as large as you need it. As demonstrated in this pseudo code.
struct HeaderTest {
int someparam;
int more;
int arrsize;
int arr[];
};
HeaderTest* pkt = (HeaderTest*)malloc(sizeof(HeaderTest));
read(&pkt,sizeof(pkt));
pkt = (HeaderTest*)realloc(pkt,sizeof(HeaderTest)+sizeof(pkt->arr[0])*pkt->arrsize);
read(pkt->arr,sizeof(int)*pkt->arrsize);
I don't think there is a very elegant way. You should probably make that dynamic member a pointer, then read all other members first, allocate memory for the last one, and then read the remainder of the data.
Since you're in C++, you can nicely encapsulate this in a class so that you don't have to worry about this detail in your code anymore. Also, as other have said, a std::vector would be a more C++-like approach than a simple pointer and manually allocated memory. It would also be more resistant to memory leaks.
No one was able to give you the solution you wanted, but I have devised it for you.
This function takes a C-string filename, opens the file and reads the contents for you. It returns an int*, which can be assigned to t.container. Enjoy.
int* read(char* filename)
{
// open file
ifstream f;
f.open(filename, ios::binary);
// get file size
f.seekg (0, ios::end);
int length = f.tellg();
f.seekg (0, ios::beg);
// allocate new int*
length = (length -(sizeof(int)*2)) / sizeof(int);
int* buf = new int[length];
for(int i = 0; i < length; ++i)
{
// create byte array to hold bytes
unsigned char* temp = new char[sizeof(int)];
stream.read((char*)temp, sizeof(int));
// convert byte array to int
for(int j = 0; j < sizeof(int); ++j)
{
buf[i] = buf[i] + (temp[j] << (j*8));
}
delete[] temp;
}
f.close();
return buf;
}

Dealing with array size

I happened to ask myself a question about arrays in c++.
Well, we all know that arrays are fixed collections of something, I say fixed because it is necessary to declare array length when defining arrays.
Well, let's consider an example:
char myarray[10] = {'\0'};
int sz = sizeof(myarray); // It is supposed to be 10
Well, it is correct, 10 is the number returned by sizeof. This can be done by the compiler because he knows how much space it placed for that variable.
Now consider what happens in this situation:
void dosome(mystruct* arr) {
int elements = sizeof(arr)/sizeof(mystruct);
for (int i = 0; i < elements; i++) {
// Do something hoping no overflow will ever occur
}
}
Nice... but I suppose it can be overflow prone. If I pass to this function an array I created in a "normal" way, everything should be fine:
mystruct array[20];
dosome(array);
No problem. But if I do this:
mystruct* array = (mystruct*)malloc(80*sizeof(mystruct));
dosome(array);
WHAT HAPPENS???????????????????
I would like to understand how sizeof behaves, this function is evaluated at compile time right??? ok, what happens when I use not an array, but something very cumbersome like a block of data like that one? furthermore, I could realloc it woth another call to malloc and ask to dosome to process that datablock again. Will it work?
I could try it physically, but I would get some exact answer about the behavioir of sizeof.
Thank you.
it's wrong starting from the mystruct array[20] example. Because the function receives a pointer type, and not an array type, it cannot deduce the number of elements in the array. you are actually getting the size of a mystruct* when you perform sizeof(arr).
You can use templates to write functions which take arrays as parameters, but the suggested way in C++ is to use vectors, if I am not wrong.
The "way" to receive arrays as parameters would be to write something like:
template <int N> void somefunction(int (&v)[N]);
EDIT corrected the function declaration. oops.
void dosome(mystruct* arr) {
int elements = sizeof(arr)/sizeof(mystruct);
for (int i = 0; i < elements; i++) {
// Do something hoping no overflow will ever occur
}
}
What type does arr have in this example? mystruct*! And it's size is most likely 4 or 8. If you want to pass statically/automatically allocated arrays (not new'd) to functions preserving the size so that your trick works, pass by REFERENCE!
template <int N>
void dosome(mystruct (& arr) [N]) {
for (int i = 0; i < N; i++) {
// Do something . No overflow will occur
}
}
Also note this
int a[20];
sizof a; //equals to 20*sizeof(int)
int* b = new int [20];
sizeof b; //equals to sizeof pointer, most likely 4
sizeof is a compile-time operator. And here it computes only the size of a pointer.