I am creating a project and I encountered behavior that is not supposed to happen (at least as far as I know). I am trying to change values in a struct array inside of a function addOrder. in main() I give struct's address to a function addOrder (and this is the first warning). Then I try to change its contents in the named function. I should only be able to change using ->, however, I get errors this way and I can only change using data[0].someName
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MENU_TITLE "----Welcome to order manager!---" // menu title
#define MENU_SIZE 4 //change based on menu options
#define INPUT_MSG "Please choose one of the following options" //enter input message (range is added later automatically)
#define SIZE 25 //size of option message array
#define STREET_NAME_SIZE 50 //size of street name array
#define BUILDING_NUMBER_SIZE 10 //size of building number array
#define EMAIL_SIZE 40 //size of email array
#define INPUT_PHONE_MAX 12
typedef struct Data{
char streetName[STREET_NAME_SIZE];
char buildingNumber[BUILDING_NUMBER_SIZE];
unsigned long long phoneNumber;
char email[EMAIL_SIZE];
}Data;
void loadOrderAmount(int *orderAmount);
void showMenu(char *menuTitle, int menuSize, char *inputMsg);
int getChoise();
void addOrder(Data *data, int *orderAmount);
void getEmail(char *email);
unsigned long long getPhoneNumber();
int main(){
int orderAmount = 0;
loadOrderAmount(&orderAmount);
Data data[orderAmount + 1];
int choise = 0;
showMenu(MENU_TITLE, MENU_SIZE, INPUT_MSG);
while(!choise){
choise = getChoise();
}
printf("\n");
switch(choise){
case 1:
addOrder(&data,&orderAmount); // This gives first warning
break;
case 2:
//removeOrder(data);
break;
case 3:
//editOrder(data);
break;
case 4:
printf("Have a nice day\n");
return 0;
}
printf("in main data %d\n",&data);
//printf("%s %s ",data[0].streetName,data[0].buildingNumber);
//printf("+%llu ",data[0].phoneNumber);
printf("in main %s %llu\n",data[0].email,data[0].phoneNumber);
return 0;
}
void addOrder(Data *data,int *orderAmount){
int amount = *orderAmount; //it is equal to 0
char email[41];
char street[51];
char buildingNumber[11];
printf("Adding an order...\n\n");
//++orderAmount;
// getStreetName(data, &orderAmount);
// getBuildingNumber(data,&orderAmount);
data[amount]->phoneNumber = getPhoneNumber(); //why this does not work?
getEmail(email);
strcpy(data[0].email,email); // why this works? its a function....
printf("In function data %d\n", data);
printf("in struct %s %llu\n",data[0].email, data[0].phoneNumber);
}
}
This is only a part of a code that is relevant and most functions are missing. Can anyone help me with this?
The function addOrder is declared like
void addOrder(Data *data, int *orderAmount);
But you are calling it passing the first argument of the type Data ( * )[orderAmount + 1]
addOrder(&data,&orderAmount);
You need to call it like
addOrder( data, &orderAmount );
Instead of this statement
data[amount]->phoneNumber = getPhoneNumber();
you have to write
data[amount].phoneNumber = getPhoneNumber();
And instead of this call
printf("In function data %d\n", data);
you have to write
printf("In function data %p\n", ( void * )data);
Pay attention to that within the function the expressions
data[amount]
and
data[0]
are not the same because amount is not equal to zero. The function is called with the argument orderAmount (passed by reference) that is assigned to amount.
This is how you solve this error:
Compiler points at the line addOrder(&data,&orderAmount); saying something strange "error passing argument 1 blablabla". We don't actually need to understand more than "error argument 1".
Could it be that the compiler is right and something is wrong with argument 1?
Hmm which one is argument 1, it must be &data.
Check the declaration of data, it is Data data[orderAmount + 1];. It's an array!
What did they teach us in beginner class? Ah, arrays decay to a pointer to the first element when passed to a function. So there is no need for &.
Change the call to addOrder(data,&orderAmount);
Compile again.
Related
The code uses a struct ( int x,y) to print message when c->x increase the value by 1,
but unlike c->x , ptr1 pointer "forgets" its address.
How can I create a pointer to string array without "forgetting" its address?
#include <stdio.h>
#define msgROW 5
#define msgLEN 16
struct cursxy{
unsigned int x;
unsigned int y;
};
void cursor(struct cursxy *c,char (*ptr1)[msgLEN])
{
c->x++;
printf("%s \n", *ptr1++);
}
int main()
{
struct cursxy cursxy = {0,0};
char messages[msgROW][msgLEN] =
{
"Set Duty Cycle",
"Set Frequency",
"Set Hours",
"Set Minutes",
"Set Current"
};
char (*ptrMsg)[msgLEN] = messages;
//c->x = 1 , prints first message
cursor(&cursxy,ptrMsg); //ptrMsg point to first message
//c->x = 2 , prints again the first message
cursor(&cursxy,ptrMsg); //ptrMsg Didn't point to second message <------------
// and so on
}
The difference between the expressions
c->x++
and
*ptr1++
is that the latter modifies a function argument, whereas the former does not.
In C, functions have their own copy of the values of the function arguments that were used to call the function. As a consequence, modifying these arguments inside the function will not modify the original variable.
Therefore, in the function cursor, any changes to the function argument ptr1 will not change the variable ptrMsg in the function main.
The simplest solution to your problem would be to increment ptrMsg inside the function main instead of inside cursor.
However, if you insist on changing ptrMsg from inside cursor, then you will have to pass the variable ptrMsg by reference instead of by value. This means that you will have to instead pass the address of ptrMsg to the function cursor, like this:
cursor(&cursxy,&ptrMsg);
You will also have to change the prototype of the function cursor, so that the second parameter has an additional layer of indirection. Additionally, you will have to add a * dereference operator in order to access the original variable via the pointer. Afterwards, your function will look like this:
void cursor(struct cursxy *c,char (**ptr1)[msgLEN])
{
c->x++;
printf("%s \n", *( (*ptr1)++ ) );
}
this is what you're looking for.
same as cursxy, use double pointer.
#include <stdio.h>
#define msgROW 5
#define msgLEN 16
struct cursxy{
unsigned int x;
unsigned int y;
};
void cursor(struct cursxy *c, char (**ptr1)[msgLEN])
{
c->x++;
printf("%s \n", *ptr1);
*ptr1 = ++*ptr1;
}
int main()
{
struct cursxy cursxy = {0,0};
char messages[msgROW][msgLEN] =
{
"Set Duty Cycle",
"Set Frequency",
"Set Hours",
"Set Minutes",
"Set Current"
};
char (*ptrMsg)[msgLEN] = messages;
char (**ptr)[msgLEN] = &ptrMsg;
//c->x = 1 , prints first message
cursor(&cursxy, ptr); //ptrMsg point to first message
//c->x = 2 , prints second message
cursor(&cursxy, ptr); //ptrMsg Didn't point to second message <------------
cursor(&cursxy, ptr); //ptrMsg Didn't point to second message <------------
// and so on
}
I'm having a headache here trying to solve this. The thing is, I'm trying to initialize a struct array by sending its address from the main() function to its specific function (in which initialize it). But when I run it, it just crashes all the time. But, the program goes until that flag over there! Please help me out
ps:
The error message says:
45 [Warning] passing argument 1 of 'initfunc' from incompatible pointer type [enabled by default]
typedef struct{
int code, year, rentstate;
char type[50];
float price;
}CAR;
void initfunc(CAR *car[]){
int i;
printf("flag ok");
for(i=0;i<50;i++)
{
car[i]->code = 0;
printf("initializing...");
}
getch();
}
int main(int argc, char const *argv[])
{
int opt, a=0;
CAR car[50];
initfunc(car);
CAR *car[]
means array of CAR pointers.
You want to send CAR car[] array of structure CAR.
Also as you pass the array of CAR you can access it like this car[i].code or car[i].year etc.
You would have to access code like it, if it was a CAR* not CAR.
For example:
CAR *car = malloc( sizeof *car);
...
(*car).code = //..
equivalently
car->code = //...
In your case the code would be
void initfunc(CAR car[]){ // void initfunc(CAR *car)
printf("flag ok");
for(size_t i = 0; i < 50; i++)
{
car[i].code = 0;
printf("initializing...");
}
getch();
}
OP asked why changing the array to the called function changes the array in main()?
Since we are actually passing pointer to the original array, change in the called function modifies the original array. In C, except for a few special cases, an array reference always "decays" to a pointer to the first element of the array.
In C everything is pass-by-value. So the pointer variable that we see in called function contains the copy of the address. Any changes made to the array elements (by de-referencing the pointer) do affect the original array, [since only the array address is copied (not the array elements themselves)].
Simply put, here you pass the address of the 0-th element of the array and then that is accessed. That's why the change is reflected because you are accessing the original elements via pointer, not the copies of them.
I just tried like this:
typedef struct{
int code, year, rentstate;
char type[50];
float price;
}CAR;
void initfunc(CAR car[]){
int i;
printf("flag ok");
for(i=0;i<50;i++)
{
car[i].code = 0;
printf("initializing...");
}
getch();
}
int main(int argc, char const *argv[])
{
int opt, a=0,i ;
CAR car[50];
for(i=0;i<50;i++){.
car[i].code = -1;
printf("%d", car[i].code);
}// RECEIVING -1 JUST TO TEST IF IT REALLY CHANGES AFTER I CALL THE FUNCTION TO INITIALIZE
printf("\n\n");
initfunc(car); //HERE WE'RE SUPPOSED TO INITIALIZE
printf("\n\n");
for(i=0;i<50;i++){
printf("%d", car[i].code);
}
printf("\n\n"); // OMG THIS CANT HAPPEN, WHY IS THIS EVEN HAPPENING? IM NOT EVEN USING POINTERS!
getch();
I'm trying to make a program that for a given int value keeps the amount of dividers:
int amount_of_dividers and a list of those dividers: int* dividers
This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
int amount;
int* dividers;
} Divide;
int main(){
Divide ** tt;
read_dividers(tt,5);
}
/* the functions "amount_of_dividers(int g)" and "dividers_of(int g, int amount)"
used in void read_divider are working properly, they are not needed for this question */
void read_divider(Divide *g){
scanf("%d",&(g->value));
g->amount = amount_of_dividers(g->value);
g->dividers = dividers_of(g->value,g->amount);
}
/* assuming that read_divider works, what causes read_dividerS to crash? */
void read_dividers(Divide ** t, int amount){
int i = 0;
t = malloc(amount*sizeof(Divide*));
for(i = 0;i<amount;i++){
read_divider(t[i]);
}
}
Read_dividers uses an array of pointers **t where i'm trying to fill each element of this array with a pointer to a Divide g variable.
EDIT: input in this case in main() : "read_dividers(tt,5)" means the user gives 5 int's, which get converted to 5 Divide structs.
What happens instead is the program crashes after I give in the second int
If any more information is missing, don't hesitate to ask!
You are passing an uninitialized t[i] to read_divider. t is supposed to be pointer to pointer to Divide, not pointer to Divide, you may have just got lucky on your first pass, but I suspect it failed on the very first call.
I am just starting to learn programming for a unit I am doing in my engineering course and I have come across pointers. I just wanted some reassurance that I actually understand the concept correctly in terms of using a pointer as an argument in a function. If I understand it correctly, you pass a pointer to an address of a variable you would like to be altered by a separate function called, even though it is a local variable within the scope of the calling function. Does that make sense? I have an example from my text book which I re-wrote. The only thing is they gave it in two incomplete parts and I put it together, filled in the blanks and added the final printf statement in the main function. I'll paste it here:
#include <stdio.h>
#include <stdlib.h>
#define READ_OK 0
#define READ_ERROR 1
int read_num(int lo, int hi, int *num);
int main(int argc, char *argv[])
{
int lo = 0, hi = 0, *num, val;
printf("Please enter a lower bound and an upper bound for your range,respectively\nLower: ");
scanf("%d", &lo);
printf("Upper: ");
scanf("%d", &hi);
num = &val;
if(read_num(lo,hi, &val) != READ_OK)
{
printf("Read error, program abort\n");
exit(EXIT_FAILURE);
}
else
{
printf("You entered %d, press any key to continue: \n", val);
getchar();
}
return 0;
}
int read_num(int lo, int hi, int *num)
{
int next;
printf("Enter a number between %d and %d: ", lo, hi);
while(scanf("%d", &next)==1)
{
if (lo<=next && next<=hi)
{
*num = next;
return READ_OK;
}
printf("%d is not between %d and %d\nTry again: ", next, lo, hi);
}
return READ_ERROR;
}
So is my understanding correct? "val" gets modified in read_num() by passing it's address in the form of pointer "*num", in which the the value for "next" is then written?
PS: is this syntax correct?
PPS: What would this process specifically be called?
Thanks a bunch for any help :)
The *num is not necessary inside the main() function. As you are passing the address of the val inside the read_num() , so any changes from the read_num() will also affect the value inside main() as you are working with the address.
In your program you have basically use two different pointers- one is inside main which is num, and another inside read_num() which is also num, for more understanding see the scope of a variable in c. As the val is inside main so you don't need to use pointer here, because you have the access of changing the value from the main as it is local to it. You will need pointer when you will be changing the value of val outside from the main, or from outside of the scope of the variable.
Please let me know how can I pass a pointer to the array of structures in C as a function argument.
Below is my code.
#include <stdio.h>
#include<strings.h>
typedef struct _Alert
{
char MerchantNo[21];
time_t last_update;
} Alert;
typedef Alert *PALERT;
int set(PALERT palertMerch[5], int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
int main()
{
Alert alert[5];
for(int i =0; i<5;i++)
{
memset(alert[i].MerchantNo, 0x00, 21);
alert[i].last_update = (time_t)0;
}
char *p = "SACHIN";
int index = 0;
set(alert[5], index, p);
}
Error message
"3.c", line 34: argument #1 is incompatible with prototype:
prototype: pointer to pointer to struct _Alert {array[21] of char MerchantNo, long last_update} : "3.c", line 14
argument : struct _Alert {array[21] of char MerchantNo, long last_update}
"3.c", line 34: warning: improper pointer/integer combination: arg #2
cc: acomp failed for 3.c
You just pass the array, it'll get decayed to the pointer to the first array element:
set( alert, &index, p );
Note that I also corrected your second error of passing integer as a pointer for the second argument.
Edit 0:
I missed the declaration of PALERT - your function definition is wrong, it should be something like:
int set( PALERT palertMerch, int* merchnoIndex, const char* txnMerchant )
{
assert( *merchnoIndex >= 0 && *merchnoIndex < 5 );
strcpy( palertMerch[*merchnoIndex].MerchantNo, txnMerchant );
...
}
I know, arrays and pointers are a bit confusing in C, and you were trying to jump to arrays of pointers already :)
You actually cannot pass an array to a function. What happens when you do, is that a pointer to the first element in an array is passed in instead. (That proccess is often described as "an array decays into a pointer").
That is,
set(alert, index, p);
Is just the same as:
set(&alert[0], index, p);
(Note that you called it as set(alert[5], index, p); , this just passes in the 6. element of your array , which btw is invalid, as your array only have room for 5 elements.)
So, what you do when you want to pass an array to a function is you
Pass a pointer to the first element in the array (which can be done by just writing name_of_array or &name_of_array[0]
Add another argument that is the length of the array. You might need this as if your array can have different sizes, and you cannot know how many elements an array have, if all you got is a pointer to its first element:
Let's skip item 2. above for now, you can just do:
//PALERT is already a pointer, otherwise specify the first argument as:
//ALERT *palertMerch
int set(PALERT palertMerch, int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
And call it like:
char *p = "SACHIN";
int index = 0;
set(alert, index, p);
btw, unless you have a good reason, try not to hide a pointer in a typedef as you do in typedef Alert *PALERT; doing so often gets confusing.
remove the array brackets and it should work.
The reason for this is that array notation is an easier way to represent sequences of items in memory. For example, in an array a[5], you can access the third element as a[3] or *(a+3).
Your function takes type PALERT *[5]. You are passing in Alert[5] instead. There are other problems with your code that need fixing before it will successfully run.