C++ how does this work? (array as parameter) - c++

So looking in IDA i found a function like this
struct exampleStruct {
int a, b, c;
};
void example(exampleStruct *(*exampleList)[3])
{
//blah blah
}
so this is the part that confuses me *(*exampleList)[3])
from just looking at it i would image i would call the function like this
exampleStruct forCall[3];
example(&forCall);
then after it is called i would imagine i can fetch the values like so
//forCall[0].a
//forCall[2].c
//etc...
So my question is, is what i said above correct? e.g. is that how i would call a function like that?

If you want to pass an array of exampleStruct to example, then the latter would like this:
void examplefoo(examplestruct somename[]) {
allnames[0].a += 1;
}
or:
void examplefoo(examplestruct* somename) {
allnames[0].a += 1;
}
Basically both are the same: you give the function a pointer to the first element of you array.
This function will take the first element of the array and increase its .a by 1. Let's see how we can call this function.
First you have to create and array of examplestruct, eg.:
examplestruct somename;
somename.a = 1;
somename.b = 2;
somename.c = 3;
examplestruct othername;
othername.a = 7;
othername.b = 8;
othername.b = 9;
examplestruct allnames[2] = {somename, othername};
And call the function like this:
examplefoo(allnames);
If you then print allnames[0].a you will see that its value is now 2.

Related

Update a struct by returning a moved parameter instead of passing by reference

Say we have a struct:
struct S{ int _i = 1; };
I would like to write a function which updates an instance of S, like this:
void update(S& s) { s._i += 1; }
I usually prefer to return values rather than passing an argument by reference and changing it. Something like this:
S update(S s)
{
S ret = std::move(s);
ret._i += 1;
return ret;
}
I would then be able to call this last function like this (in case I want a copy of the previous and updated instance):
S s{};
S u = update(s);
Or like this (in case I'm only interested in keeping the updated value):
S s{};
s = update(std::move(s)); // is this legal?
So, I move s into the argument of the update function, and retrieve it back at the assignment (last line). Is this legal? Apart from that, is this just silly and should I go with the first solution?

How to Pass Struct Data Member into Function

I want to be able to pass a struct member into a function:
struct threeBuckets {
int bucketA;
int bucketB;
int bucketC;
};
threeBuckets allCombinations[512000] = {{0,0,0}};
int totalCombinations = 1;
int counter = 0;
//note that pourer, receiver, and other are one of the struct members (bucketA, bucketB, and bucketC)
void pour(pourer, receiver, int receiverCap, other) {
int finalTriple[3];
allCombinations[totalCombinations].bucketA = allCombinations[counter].bucketA;
allCombinations[totalCombinations].bucketB = allCombinations[counter].bucketB;
allCombinations[totalCombinations].bucketC = allCombinations[counter].bucketC;
allCombinations[totalCombinations].receiver = allCombinations[totalCombinations].receiver + allCombinations[counter].pourer;
allCombinations[totalCombinations].pourer = 0;
if (allCombinations[totalCombinations].receiver > receiverCap) {
allCombinations[totalCombinations].pourer = allCombinations[totalCombinations].pourer + allCombinations[totalCombinations].receiver - receiverCap;
allCombinations[totalCombinations].receiver = receiverCap;
}
finalTriple[0] = allCombinations[totalCombinations].bucketA;
finalTriple[1] = allCombinations[totalCombinations].bucketB;
finalTriple[2] = allCombinations[totalCombinations].bucketC;
//some more irrelevant code
}
As I've hopefully made clear, the parameters pourer, receiver, and other are bucketA, bucketB, and bucketC (in no particular order, the order does change depending on when I call the function.) There are several places where I want to modify the instance
allCombinations[totalCombinations].pourer
for example. How do I use the struct member as a parameter, and what type do I use to specify it?
Note: I'm mostly a beginner and am new to StackOverflow, so if anything else I'm doing is wrong, please feel free to tell me.
Note 2: If any of you do or have done USACO, you might recognize this problem as the milk3 training gateway problem. This might aid you if you don't know what I'm doing here.
It sounds like you need to use pointer to member variable for the argument types in pour.
void pour(double threeBuckets::(*pourer) ,
double threeBuckets::(*receiver),
int receiverCap,
double threeBuckets::(*other)) {
...
}
In the function, change the use of
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
by
allCombinations[totalCombinations].*pourer
allCombinations[totalCombinations].*receiver
allCombinations[totalCombinations].*other
respectively.
At the point of calling the function, use:
pour(&threeBuckets::bucketA,
&threeBuckets::bucketB,
0, // Any appropriate value
&threeBuckets::bucketC);
Another option that is worth considering is:
Change threeBuckets to use an array.
Change the arguments to pour to be indices to the array.
struct threeBuckets {
int buckets[3];
};
void pour(int pourerIndex ,
int receiverIndex,
int receiverCap,
int otherIndex)) {
...
}
Then, instead of using
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
use
allCombinations[totalCombinations].buckets[pourerIndex]
allCombinations[totalCombinations].buckets[receiverIndex]
allCombinations[totalCombinations].buckets[otherIndex]
Of course, change the call to use indices.
pour(0,
1
0, // Any appropriate value
2);

Retrieve array name

I have written a function in c++ which receives a struct as a input. The struct object received has two arrays. I need to use both the arrays for different purposes. The array names have been created in a certain format. How to retrieve array names in a string.
struct INFO
{
float fADataLHS[3] = {1,2,3};
float fADataRHS[3] = {4,5,6};
Struct INFO has been defined where two arrays have been defined an initialized. The function useStruct uses both the function for different purposes.
void useStruct(struct *INFO)
{
--------;
--------;
}
int main()
{
struct INFO info;
useStruct(info);
}
I want a method in which I can retrieve the name of the array as for ex. fAdataLHS and store it to a string. The idea is to find the sub-string LHS and RHS from the string names and process then accordingly.
PS: I am quite new to c++.
I will go simple as you're a begginer to C++.
If you want to use both of arrays for different purposes, just doit. For instance:
void use_array_for_different_purposes(INFO *info)
{
// Purpose one, printing values using fADataLHS.
for (int i = 0; i < 3; i++) {cout << info->fADataLHS[i] << endl;}
// Purpose two, computing total sum using fADataRHS.
int acum;
for (int i = 0; i < 3; i++) {acum += info->fADataRHS[i];}
}
As you can see, you don't need to get the arrays names as strings values.
If I understand corectly, your use case is this: you have two (or more) names and each has a float array associated with it. You want to get the array by name and process the data.
Consider this code:
class INFO
{
std::map<std::string, std::vector<float>> vectors;
public:
INFO() : vectors{}
{
vectors["fADataLHS"] = { 1, 2, 3 };
vectors["fADataRHS"] = { 4, 5, 6 };
}
const std::vector<float>& operator[](const std::string& key) const // access vector by key
{
return vectors.at(key);
}
};
void useStruct(const INFO& info) // pass instance by const reference
{
std::cout << info["fADataLHS"][0] << "\n"; // access element 0 from the fADataLHS array
// get the entire array:
const auto& arr = info["fADataRHS"];
// this will throw a std::out_of_bounds
const auto& arr = info["non-existent-key"];
}
EDIT: A few other notes:
in C++ try not to use float - use double instead
if you need to alter the vector contents from client code, add a non-const version of the operator[]

Dynamic Polymorphic Memory Container - Return Value Incorrect

I am currently working on an dynamic memory container.
Basic idea of the class is that you should be able to get the iterator of an object if you really do not know it, without the use of a for loop throughout all the elements to boost performance. The issue I have is the following; when you pass your pointer address to the object you want to get the iterator of it type casts the object into the extended memory containers structures type. This type contains an extra element, an integer. (IteratorNum)
When following the code the integer within the function is set to correct value, as below would be 50. But when the returned value is set into the local integer used in the main function it is 200? I've been adding watches and cannot figure out how it is possible that the function returns 50 but value gets set to 200.
template <typename DataType> class MemoryContainer {
public:
struct LevelData : DataType
{
int element;
};
DataType &New()
{
elements++;
//Reallocate the size of the array
ld = (LevelData*)realloc(ld, sizeof(LevelData) * elements);
//Set the iteratorNumber
ld[elements - 1].element = elements - 1;
return ld[elements - 1];
}
DataType *reserve(int num)
{
return calloc(num, sizeof(DataType));
}
DataType &operator[](int i)
{
return ld[i];
}
bool inArray(DataType *type)
{
//Compare memory addresses and see if it's within.
return (type >= &ld[0]) && (type < &ld[elements - 1]);
}
static unsigned int getIterator(DataType *type)
{
// v this is 50, but in main says returns 200.
return ((LevelData*)type)->element;
}
MemoryContainer()
{
elements = 0;
}
~MemoryContainer()
{
free(data);
}
private:
unsigned int elements;
LevelData *ld;
};
struct Effective
{
//Set it to polymorphic classes
virtual void dummy()
{
}
char * testvar;
Effective(char * c)
{
testvar = c;
}
Effective(){}
};
MemoryContainer<Effective> myContainer;
int _tmain(int argc, _TCHAR* argv[])
{
//Create 200 elements in the array
for(int i = 0; i < 200; i++)
myContainer.New().testvar = "E";
//Add pointer for testing purposes to get the iterator.
Effective * pointer = &myContainer[50];
//Test setting it's value
pointer->testvar = "HEHEHE";
//Get iterator of our pointer in the array
unsigned int i = myContainer.getIterator(pointer);
printf(pointer->testvar);
system("PAUSE");
return 0;
}
I suspect it is the visual studio debugger getting confused between your two i variables. If you print out the value of i, it will print correctly. If you change the name of your variable to something else, the value shows as 50 in the debugger.
That said, your code is a mish-mash of c and c++ and won't work correctly with anything that requires a copy constructor. I would suggest at the very least using new [] rather than realloc.
Also, any user of this collection who tries to store a class with a member variable called element is going to get mighty confused.
The unsigned int i in the main function really has a value of 50, but the debugger is confusing it with the i declared in the for loop (I reproduced this with Visual Studio 2013). If you cout i it will be 50, and if you change the variable name it will show up as 50 in the debugger. I've never seen this problem before so I wonder if it might be due to your use of malloc/realloc/free with C++ objects.

Initialize array of objects from a function (C++)

How do I initialize an array of objects from a function? I'm aware the code below is impractical; I'm just teaching myself C++.
Here is a structure that contains data.
struct pointStruct {
int numberPoints;
Point2D pointArray;
};
The Point2D class has instance variables x and y. In a separate function, I have:
void setPoints(void) {
pointStruct myPointData;
myPointData.numberPoints = 4;
myPointData.pointArray[4]; // here is the problem
// loop with i
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
I'm trying to initialize the array so that I can loop through it and set the x,y coordinates. I've tried using new and some other methods but I can't work through what I need to do. How can I fix this?
When I try to compile this code, I get the error "no match for 'operator[]' in 'myPointData.pointStruct::pointArray[4]' "
You should probably use std::vector like MadScienceDreams suggests.
However, if you want to learn about such things, you could use a pointer instead. For example:
struct pointStruct {
int numberPoints;
Point2D* pointArray;
};
void setPoints(void) {
pointStruct myPointData;
const int num_points = 4;
myPointData.numberPoints = num_points;
myPointData.pointArray = new Point2D[num_points];
for(int i = 0; i < num_points; ++i) {
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
// Do stuff with myPointData...
// Don't forget to have a "delete" for every "new" when you're done.
delete[] myPointData.pointArray;
}
Point2D pointArray;
pointArray is a single instance to Point2D. It is not an array of instances in which case it's type is Point2D [N].
myPointData.pointArray[4];
The above statement calls operator [] taking a parameter of type int, which is not you actually want. Since there is no such member function in Point2D, compiler complains. If you wish to create array of instances, use std::vector<Point2D>.