Program crashing when sending struct array - c

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();

Related

Unclear behavior of structs in a function

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.

Passing a struct to a function

So I am trying to pass my struct to a function and I am also trying to assign my variable to the struct, which does not seem to work. I don't know what's wrong with it either.
This is how my code looks:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ACE 1;
#define CardSize 52
#define colors 4
struct MyCards {
int *cards;
char *color[4];
};
void count(struct MyCards record);
int main() {
struct MyCards record;
count(record);
system("pause");
return 0;
}
void count(struct MyCards record) {
int i, j, f;
// I actually want to put this variable and the values into the struct, how do i do it?
char *color[4] = { "Diamon", "Heart", "Spade", "Clubs" };
record.cards = malloc(CardSize * sizeof(int));
for (f = 0; f < 4; f++) {
for (i = 0; i < 13; i++) {
record.cards[i] = (i % 13) + 1;
printf("%d of %s\n", record.cards[i], color[f]);
}
}
}
As you might see, the thing I commented out, I also want to put that variable AND the values that I have assign to it, but I dont know how to do that, would love some help there as well.
C uses pass-by-value. record inside count is a different variable to record in main - a copy is made when you call the function.
If you want main to see the changes you either need to return the changed object (in which case you wouldn't pass it in in the first place, in this example), or use pass-by-reference which you implement by passing a pointer to the object.
Returning the object would look like:
struct MyCard count(void)
{
struct myCard record;
// ... do stuff with record ...
return record;
}
Passing by reference would look like:
void count(MyCard *p_record)
{
// ... do stuff with (*p_record)
}
Also you want record.color[f] = color[f]; as the first line of the f loop. And (as discussed last time you posted about this code) you should be using string or char const *, not char *.
You have to pass a pointer to the struct in order to edit it, or you will edit the variable only in the stack of the function, which will be deleted once the function returns. Try passing &record to your function.
Also change your prototype: you have to accept a pointer to the struct.
When you have a pointer, to resolve the struct you have to use the -> operator. Let's do an example:
records->cards[i] = ...

Using a function to alter typedef fields when individual structs are identified using an array

This seems to be a very specific question that I'm having trouble finding any sort of answer.
I'm attempting to use a typedef struct to store user information. Im using the format cust[x].firstName etc. to differentiate from one customer to another. Since I'm defining this struct in the header, it's my understanding that by altering the fields of the struct inside a function, these changes should be reflected in main. However, this doesn't seem to be the case.
typedef struct
{
char firstName[99];
char lastName[99];
int numOrders;
char orders[99][99];
float orderPrice[99][99];
float orderNum[99][99];
}Info;
int infoGet(FILE*,int);
int main()
{
int orderNum,i;
FILE*input = fopen("input.txt","r");
FILE*output = fopen("invoices.txt","w+");
fscanf(input,"%d",&orderNum);
Info cust[10];
infoGet(input,orderNum)
printf("%s %.2f %.2f\n",cust[0].orders,cust[0].orderPrice[1][0],cust[0].orderNum[1][0]);
}
int infoGet(FILE*input,int orderNum)
{
int i,j;
char space;
Info cust[10];
for(i = 0;i < orderNum;i++)
{
fscanf(input,"%s %s",cust[i].firstName,&cust[i].lastName);
printf("%s %s\n",cust[i].firstName,cust[i].lastName);
fscanf(input,"%d",&cust[i].numOrders);
printf("This person has %d items to order\n",cust[i].numOrders);
for(j=0;j < cust[i].numOrders;j++)
{
fscanf(input,"%s %f %f",cust[i].orders,&cust[i].orderPrice[1][j],&cust[i].orderNum[1][j]);
printf("%s %.2f %.2f\n",cust[i].orders,cust[i].orderPrice[1][j],cust[i].orderNum[1][j]);
}
}
}
The last printf statement in main should be printing what is scanned for in the last fscanf in the function, but it is not. Do I need to pass the struct into the function? or is their something else I need to do to keep this struct constant?
Since I'm defining this struct in the header, it's my understanding that by altering the fields of the struct inside a function, these changes should be reflected in main.
This is a misunderstanding. The definition in the header defines a type. This is not an object that can be modified, but a definition that is needed by all code that creates and uses instances of that type. That is what happens in main() and infoGet(), where you instantiate arrays of Info objects with these statements:
Info cust[10]; // instantiates an array of 10 Info objects
Now, as to the actual problem: Your function infoGet has its own, local array Info cust[10]. Modifying it in the function has no effect outside of the function. You need to pass the array into the function from main. For example,
int infoGet(FILE*input, Info* cust, int orderNum)
{
int i,j;
char space;
for(i = 0;i < orderNum;i++)
{
....
}
and
int main()
{
int orderNum,i;
FILE*input = fopen("input.txt","r");
FILE*output = fopen("invoices.txt","w+");
fscanf(input,"%d",&orderNum);
Info cust[10]; // Careful! What if orderNum is > 10?
infoGet(input, cust, orderNum)
Note that you should check that orderNum isn't more than 10, or allocate a variable length array:
Info cust[orderNum];

understanding how to dynamically create an array of structure and access its elements

I need to pass the address of a pointer to a structure to a function, which inturn will dynamically allocate the memory for an array of structures and fill in the values.
Now from my calling method, once i return from the func1, i should be able to iterate through the array of structure and display the value of the structure variables.
Can someone explain how to pass the address of the pointer to the structure, also iterating through the array of structures created dynamically ?
my sample code looks like this:
struct test {
int a;
int b;
};
void func1(int *n,struct test **testobj)
{
n=5;
*testobj = (struct test*) malloc(n*sizeof(struct test));
for(i=0;i<n;i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
struct test testobj;int n;
func1(&n,&testobj);
for(i=0;i<n;i++)
{
printf("%d %d",(*testobj)[i].a,*testobj)[i].b);
}
free(testobj);
}
In main() define a pointer to a test structure:
struct test *testPtr;
To take the address of that pointer use the & address-of operator:
&testPtr;
This returns the address of the pointer and has type struct test **
You can then pass this into your function func1, which does the correct allocation (although casting malloc() is generally considered bad practice - Do I cast the result of malloc?). Other than that func1() looks good... the line...
*testobj = malloc(n*sizeof(struct test));
... is correct. *testobj dereferences your double pointer that you got by doing &testPtr, and stores the address of the new memory in your pointer. You are also correct when you dereference your double-pointer using (*testobj)[i] because [] has higher precedence than * you needed to (as you've correctly done) surround the dereference with brackets to make sure that happens before you take the index.
Thus, when func1() returns the pointer testPtr should now point to the array of n test structures you allocated and can be accessed using testPtr[i].a etc.
EDIT: Your for loop should become
for(i=0;i<n;i++)
printf("%d %d", testobj[i].a, testobj[i].b);
Your original for loop should have given you compilation errors? In the original code testobj is not a pointer, therefore dereferencing it should not be possible.
So the summary answer is in main() declare testobj as a pointer and then access the array elements as testobj[n] :)
EDIT: As eric has pointed out, remove n=5; from func1(). I think you meant *n=5 perhaps as some kind of debugging step... You probably mean to use n as the input to the function to say how many objects you want in your structure array. Either initialise n or perhaps re-define func1() to be
void func1(int n,struct test **testobj) // n is no longer a poitner, just a number
create your array of pointers to structures in declaration step itself and simply pass it to the function
struct test *testobj[10];
func1(&n,testobj);
This passes the whole array of pointers to the function
It isn't entirely clear which version you're asking for, but one of these should cover it:
/* allocate some number of tests.
*
* out_n: out parameter with array count
* returns: an array of tests
*/
struct test* allocate_some_tests(int *out_n) {
int n = 5; /* hardcoded, random or otherwise unknown to caller */
*out_n = n
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
/* allocate a specific number of tests.
*
* n: in parameter with desired array count
* returns: an array of tests
*/
struct test* allocate_n_tests(int n) {
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
Note that you can just return the allocated array, you don't need a pointer-to-pointer here.
As for calling them, and iterating over the result:
void print_tests(struct test *t, int n) {
for (; n--; t++)
printf("{%d, %d}\n", t->a, t->b);
}
int main()
{
int count1; /* I don't know how many yet */
struct test *array1 = allocate_some_tests(&count1);
print_tests(array1, count1);
int count2 = 3; /* I choose the number */
struct test *array2 = allocate_n_tests(count2);
print_tests(array2, count2);
}
Your code appears pretty much ok to me.
only edit that should make it fine is--
in place of
struct test testobj;
put the following code
struct test *testobj;
and keep the remaining as it is..!
here's the working version of what's required, here the memory is allocated in the called function just as required
#include <stdlib.h>
#include <stdio.h>
struct tests {
int a;
int b;
};
void func1(int *n,struct tests **testobj)
{
int i;
*n=5;
*testobj = (struct tests*) malloc((*n)*sizeof(struct tests));
for(i=0;i<(*n);i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
int i;
struct tests *testobj;int n;
func1(&n,&testobj);
for(i=0;i<(n);i++)
{
printf("%d %d",(testobj)[i].a,testobj[i].b);
}
free(testobj);
}

Getting error when modifying MyType constructed using typedef in C

I create a type and try to change the int value in it.
But it keeps printing 240.
I don't know why, can anyone help me?
Here is my code:
typedef struct{
int i;
}MyType;
do(MyType mt, int ii){
mt.i = ii;
}
int main(int argc, char ** argv){
MyType mt;
do(mt, 5);
print("%d\n", mt.i);
}
Passing mt by value to function do(). Any changes made will be local to the function. Pass the address of mt:
void do_func(MtType* mt, int ii){
mt->i = ii;
}
MyType mt;
do_func(&mt, 5);
So first, your do function has some problems. You have failed to specify a return type, so int is assumed (pre-C99), but I see no reason to not just specify it. Second, do is a reserved keyword in C.
You are passing your struct by value, so a copy is made, passed to your do function, and that is modified. Everything is passed by value in C, period. Your mt variable declared in main is never touched.
Take a MyType* in your code if you need to modify one or more of its member variables, take a MyType** if you need to allocate memory for the structure itself (i.e., initialize a pointer).
// pass a pointer to the function to allow
// for changes to the member variables to be
// visible to callers of your code.
void init_mytype(MyType *mt, int ii){
if(mt)
mt->i = ii;
}
MyType mt;
init_mytype(&mt, 1);
// pass a pointer to pointer to initialize memory
// for the structure and return a valid pointer.
// remember, everything is passed by value (copy)
void init_mytype(MyType **mt, int ii) {
if(mt) {
*mt = malloc(sizeof(MyType));
if(*mt)
(*mt)->i = ii;
}
}
MyType *pmt;
init_mytype(&pmt, 1);

Resources