Passing a pointer of a structure from a function to another function - c

I have a structure of structures which is global. I am using functions to change the data of the structure.
In general I manipulate the structure easily (e.g. send it to a function).
My problem is that now I have a function that changes the data of the structure, but it also has to call another function. And this is my problem.
In general my structure is the: "name".
I have a pointer: name_ptr->name[i]....
In case of a function I am passing it like this:
find_max = calc_max(i, &name_ptr);
and this function id declared as:
int find_max(int x, vectname **pr)
So inside the function I am working like this:
(*pr)->name[i]...
If I am into the function and I want to sent this pointer to another function how can I call it?

In simple words you have an array of structures and to your first function you get the pointer to the array.
So either you can use:
int find_max(int x, vectname **pr)
{
// method - 1 (if your second function is intreseted only in changing the nth structure instance of the array )
SecondFunc( &pr[n]);
// method - 2 (if your second function is intreseted in changing the any structure instance of the array )
SecondFunc( pr );
}

Your question is quite cryptic but i'll give it a shot:
int find_max(int x, vectname **pr)
{
...
another_function(x, pr);
...
}

Related

Long arguments list, how to process them nicely, now I have many if/else statements ... pure C

I have an application where the arguments list cant be reeeealy long. I can run my app like this:
./app -operations a b c d e f g h i j ...
And so on. My a,b,c ... are algorithms which I would like to run (functions defined in my code). To be able to execute them, I have something like this:
if(a)
funA();
if(b)
funB();
if(c)
funC();
...
It does not look nice, does it? I must say, there's much more calls than just 26, since my application grows and grows, my arguments list grows too. I'm looking for a fancy way to make it simpler/prettier. Is it possible, anyone with an idea?
I dont want to use C++ nor external libraries for making it simpler. Can it be done in pure C?
Here is a very simplified possible option:
#include <stdio.h>
// create a common structure to hold all your
// function parameters;
typedef struct Parameters
{
int p1;
int p2;
} Param_Type;
// sample function 1
void func1( Param_Type *params ) {
printf("hi from func1: %d\n", params->p1 );
}
// sample function 2
void func2( Param_Type *params ) {
printf("hi from func2: %d\n", params->p2 );
}
int main() {
Parameters p;
// parse the command line and populate the parameters struct;
p.p1 = 1;
p.p2 = 1;
//create a lookup table with pointers to each function.
void (*F_A[2])(Param_Type *) = {func1, func2};
//You will still need some function, that given a set of arguments, can
// derive and return an index into the array that maps to the correct
/ function.
int func_idx = your_mapping_function(...) // todo
// dispatch the correct function call.
(*F_A[func_idx])(&p);
return 0;
}
You can use use getopt() to read the command line parameters.
And I don't see any optimization in the way you are deciding what action to take depending upon the arguments. I'd say it's just a bad design of doing things. You could try changing your approach.
You could use enums and function pointers to define handlers for every different set of arguments.
Something in the lines of:
typedef enum {
ARG_A,
ARG_B,
ARG_C,
// etcetera
MAX_ARGS
} CmdArgId;
bool cmdArgStates[MAX_ARGS];
typedef void (*CmdHandler_f)();
CmdHandler_f cmdHandlers[MAX_ARGS] = {
// TODO: set function pointers
};
int main()
{
// set cmdArgStates[] indexes to true or false,
// according to the program command line.
ParserCmdArgs();
for (int i = 0; i < MAX_ARGS; ++i)
{
if (cmdArgStates[i] == true)
{
cmdHandlers[i]();
}
}
}
If you need the handler functions to have different numbers of arguments, you can define a common function with a fixed number of args and just ignore them when they are not needed. I.e.: typedef void (*CmdHandler_f)(); could also de something like typedef void (*CmdHandler_f)(int, int, int);
One idea would be to create a structure that can be used to abstract each command line option. Here is a possible method you could use to implement that idea :
Create a structure that can represent each function you need to
support, and have it hold a pointer to the function and a string for the search key.
Create an array of this structure and initialize the members accordingly
Use an algorithm, such as a binary search, to find the key in the structure array when looping through the command line arguments.
Once you have the structure from the key, you can then call the function which will handle the behavior desired in the option.
It's possible this won't apply to your situation, but this really is an implementation specific problem. If you want a more specific solution, you should probably post more details about your functions and the implementation behind them.

Resizing a dynamic array of objects in c++

Hi I am working on a project where I access info from a file and then put it into an array of objects then manipulate the data in the object from a options from a menu. The problem I am currently having is that one of the options in the menu is to add a new element to the object. The project states that I must use an array of objects so I can't just use a vector the class that I'm putting the array into to resize it uses a temporary dynamic array for the object then deleting the original array.
Here's what the class looks like
class Info
{
private:
string name;
double money;
public:
Info(){
name="";
money=0;
}
void Setname(string n){
name=n;
}
void Setmoney(double m){
money=m;
}
string GetName()const{
return name;
}
double GetMoney()const{
return money;
}
};
now that was just a sample of the class the actual class has equations with it to alter the money variable but for the purpose of this question this is all that is needed. Now here is the function where I am having the problem
void Addinfo(Info in [], int & size){
string newname;
double newmoney;
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
delete []in;
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
in=temp;
size=size+1;
}
Now when I run the program everything runs fine until I try using this function in which the data in the arrays gets corrupts. Am I supposed to make the in Info variable a new dynamic array that can hold the can hold all the info then use another for loop to put the variables into the new dynamic array or I am supposed to do something else. Also remember that I must use arrays for this. Also when deleting a dynamic array am I supposed to make the former array equal to zero after deleting or is that something else?
When you have a function with a type valueName[] array parameter then you just pass the address of that array parameter to the function. The calling function has the ownership of that array. Besides the function signature you always have to consider a contract between the caller and the called function that defines the ownership of the data passed by pointer.
Your function AddInfo gets an array passed by pointer and the calling function expects that the data is available after the function call. So the function violates the contract when you delete []in.
Your function uses a parameter in as (local) variable when you assign a new value with in=temp;. That's legal. But you can't expect that the changed local variable has any effect to the caller. With the current function signature is possible to call the function in this way:
Info infos[5];
Addinfo(&info[3], 2);
Obviously it makes no sense to modify &info[3]. When your contract shall allow adding some data to the array you need a signature that allows changing a pointer. One example would be:
void Addinfo(Info*& in, int& size, string newname, double newmoney)
{
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
delete []in;
in = temp;
size=size+1;
}
void Addinfo(Info*& in, int& size)
{
string newname;
double newmoney;
// input data
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
// TODO: data validation.
// add data to array
Addinfo(in, size, newname, newmoney);
}
I have factored out the change of the array from the input. This allows a more simple testing of that function.

How to manipulate the Global Variable in C

I have multiple void functions that relies on the each individual output of the functions since there are multiple variables (that are the same throughout the code), where each functions' output will be "stored" to them and be passed to another.
So, I decided to make those variables into global variables by making them static .... right after all the necessary #include... codes.
I was able to utilize all functions (14 functions in total,all void) by only calling four of them (Each functions, after processing its own function, passes the result into another function and after series of passing, only four of them are needed to be called in int main())
Now, I created another void function that requires the global variables as its parameter since that void function relies on the data that all the other functions "copied and put" into the global variables declared earlier. (Which I found is not working, since I heard that storing data into global variables is not possible.)
Can anyone teach me if there is any other way to create series of functions which requires output of each individual functions?
I checked if the variables were stored properly, so I tried using printf method right after the #3 process. I found out nothing gets printed when I expected a value from the struct data to be printed.
Ex:
typedef struct database{
//... variables
}data;
typedef struct itembase{
//... variables
}item;
static data user1;
static data user2;
static data *pointer[10000];
static item *pointer2[10000];
static item current[10000]; //Shares same value of the bracket with *pointer2
static data sectionA[1][10000];
static data sub_section[3][10000];
static int datacounter = 0; //..will be put inside the bracket of *pointer
static int itemcounter = 0; //..will be put inside the bracket of *pointer2
static int typenum = 0; ..will be put inside the first bracket of all the sections and subsections
static int section_count = 0; //..will be put inside the second bracket of all sections
static int sub_section_count[3] = {0}; //..will be put inside the second bracket of all sub_sections. The [3] will be the value of the typenum.
void load_data() // Accepts User's input and store them into struct data's variable using singly-linked list
{
//.... All data will be stored to *pointer[datacounter]
binarycheck(pointer[datacounter]->encoding,*pointer,datacounter);
//.... The `typedef struct` of data contains 12 variables. After storing 12 variables, datacounter will be ++ and the program will still continue to accept input from the user
}
void load_item()
{
//.... All item will be stored to *pointer2[itemcounter]
memcpy(&current[itemcounter],pointer2[itemcounter],sizeof(item));
}
void binarycheck(data encoding,data *pointer,int datacounter)
{
if ((encoding&128)==128){
typenum = 3;
memcpy(&sectionA[typenum][section_count],pointer,sizeof(data));
sub_sectionA[typenum][sub_section_count[typenum]] = sectionA[typenum[section_count];
section_count++;
sub_section_count++;
}
}
void askitem(data user)
{
// Tried putting `printf(" %s User1 Data#1",user1.firstdata);` and it works perfectly fine.
// Ask for user's selection on item
// If the item is found, then the content of that item will modify the data of the variable of `user`
}
void askinput(data user)
{
int whattype = 0;
int whatsub = 0;
printf("What type do you want?: \n);
scanf("%d",&whattype);
if (whattype == 1)
{typenum = 1;}
printf("What Sub type do you want?: \n);
scanf("%d",&whatsub);
if (whatsub == 1)
{ user = sub_sectionA[typenum][sub_section_count[typenum]];}
askitem(user);
}
void final_print(data user, data user2)
{
printf("%d\n",user.Adata);
printf("%d\n",user2.Adata);
}
int main()
{
load_data();
load_item();
askinput(user1);
//Tried putting `printf(" %s User1 Data#1",user1.firstdata);` but nothing shows.
askinput(user2);
//Nothing shows
final_print(user1,user2); //Nothing shows
}
Take a look at this function:
void askinput(data user)
Here you pass user by value to the function. When you pass by value, the function receives a copy of the variable. Changes that you make inside the body of that function only affect the copy. They are not visible to the caller's variable.
Instead you need to pass a reference. In C that means passing a pointer to a variable:
void askinput(data *user)
Inside the body of the function you need to de-reference the pointer to access members. So you use -> rather than . to refer to members.
And when you call the function you need to pass a pointer to the variable. So the call becomes:
askinput(&user1);
Frankly I do not understand why you are using global variables here at all. It's generally preferable to pass parameters otherwise you do find yourself struggling to keep track of which different version of the variable you are meant to be working on.
Finally, you have written your entire program and trying to debug this specific problem in the context of the entire program is confusing you. You really should have cut this down to a 10 or 20 line simple reproduction. Being able to do that in the future will make life much easier for you.

MQL4 - Multidimensional Array as Parameter in Function where is inserted a one-dimensional array

I supposed it would be much easier, but I cant use a two-dimensional array as parameter in a simple mql4 function and insert elements in it. I don't know where the problem is.
I have a function declared like this:
void insert_array_in_multi(double simple_array[], double &multi_array[][]){
...
ArrayResize(multi_array,1);
ArrayCopy(multi_array[x][0],simple_array); // Here I want to copy the one-dimension array into the multidimensional one, in "x" position. And here is where I get the ERROR when executing.
// I use "multi_array[x][0]" because is the way I don't get errors when compiling; if I use "multi_array[x]", meaning I want the one-dim array to be copied in the x pos of the multi-dim array, I get the error message "wrong dimension"
...
}
The other function calling this one, is like:
double bidiarray[0][10];
... as I put new elements, I resize the array to an array with 10 or more (primary) elements
... create a one-dimensional array like this:
double simple_array[10] = ...
... and then call to the previous function:
insert_array_in_multi(simple_array,bidiarray);
...
}
The error message I get is "1 parameter for ArrayCopy function must be array"... But, it is... Isn't it?
Somebody knows how to do it?
Thanks in advance.
PD: It fails when executing, not when compiling
I tried testing function with following signature and it compiles, so I think it will work. Give it a try:
int foo(int something[][])
{
return (0);
}
int somenumber[5][5];
somenumber[0][0]=7;
foo (somenumber);

Rationale for Passing Pointer as Function Parameter and Returning it in C

I'm examining the source code (written in C) of bkhive -- a utility for dumping the SysKey bootkey from a Windows NT/2K/XP system hive -- and would like to know if there is any rationale for something the original author did: passing a pointer to a struct into a function and then returning the same pointer. Here is the relevant source code:
In main() there is a call that looks like this:
struct hive h;
char *root_key;
// Do some stuff to init
_RegGetRootKey(&h, &root_key)
Which calls:
int _RegGetRootKey(struct hive *h, char **root_key)
{
nk_hdr *n;
n = (nk_hdr*) malloc(sizeof(nk_hdr));
/* ************************************************
* RELEVANT FUNCTION CALL
* Why pass n as a parameter and use return value?
* ************************************************/
n = read_nk(n, h, 0x1020);
if (n->id == NK_ID && n->type == NK_ROOT)
{
*root_key = (char *) malloc(n->name_len + 1);
strncpy(*root_key, n->key_name, n->name_len);
(*root_key)[n->name_len] = 0;
free(n);
return 0;
}
free(n);
return -1;
}
Which calls:
nk_hdr* read_nk(nk_hdr *nk, struct hive *h, int offset)
{
memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
nk->key_name = (h->base + offset + 4 + 76);
return nk;
}
So, what is the purpose of passing the struct pointer and then returning it? Couldn't the function return nothing and use n after the function call?
The main benefit of this convention is to allow for simpler concatenation of function calls. If you want to use the return of one function as a parameter to another function, having it return the pointer can enable you to write the statement in a single line. Thus, instead of writing something like this:
foo(myPtr);
bar(myPtr);
You can do this:
bar(foo(myPtr));
The specific code you show doesn't use this, but this is a convention used in many C functions, and I guess the author of the code is used to this by now.
In this exact case, there doesn't appear to be much use for it. But in general, there are two reasons I've done the same thing in the past:
One is where the function might reallocate the item pointed at, in which case the return could be the same pointer that was passed, or could be a replacement for it with a different value.
Another, even when the pointer won't change, is that it allows the return from the function to be used immediately to access the pointed-to item, in constructs like somefunc(item)->member = 5; among others. It lets you drop the function call into another expression that needs the same pointer afterward.
It could also be just to make the function's use consistent with others in the API, some of which may have a reason to do this.
This allows you to pass the object by reference, and then get a handle (i.e., pointer) to the updated value on return ... it also allows you to pass back a NULL if something goes wrong, so that you know the state of the object that you passed in by reference is not good anymore. For instance:
struct my_struct* pass_by_ref = malloc(sizeof(my_struct));
//...some more code
if (foo(pass_by_ref) == NULL)
{
free(pass_by_ref); //pass_by_ref is no longer any good ...
perror();
}

Resources