passing structures to functions - c

How do you pass structures to a function? is it the same way as with variables (i.e. &var1 to pass it, and *ptr_to_var from function).
Suppose in the following code I wanted to send agencies[i].emps[j].SB and agencies[i].emps[j].ANC to a function which does some calculations on them and then returns a value and store it in agencies[i].emps[j].SNET
how do I go about that?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char mat[20];
double SB;
int ANC;
double RCNSS;
double SNET;
} employee;
typedef struct {
char name[20];
employee* emps;
int emps_count;
} agency;
int main(void)
{
int num_ag, num_emps, i, j;
printf("enter number of agencies\n");
scanf("%d", &num_ag);
agency* agencies = malloc(sizeof(agency) * num_ag);
for (i = 0; i < num_ag; i++) {
sprintf(agencies[i].name, "agency %d", i+1);
printf("enter num of employees for agency %d\n", i+1);
scanf("%d", &num_emps);
agencies[i].emps = malloc(sizeof(employee) * num_emps);
agencies[i].emps_count = num_emps;
for (j = 0; j < num_emps; ++j) {
scanf("%s", &agencies[i].emps[j].mat);
}
}
for (i = 0; i < num_ag; i++) {
printf("agency name: %s\n", agencies[i].name);
printf("num of employees: %d\n", agencies[i].emps_count);
}
for (i = 0; i < num_ag; ++i) {
free(agencies[i].emps);
}
free(agencies);
return 0;
}

You can simple pass a structure pointer to your function:
// Void of a type void function, which saves result of the calculation
void modify_employee(employee * emp) {
emp->SNET = emp->SB * emp->ANC;
}
// Example of type double function, which returns result
// of of the calculation (withuot saving it)
double modify_employee2(employee * emp) {
return emp->SB * emp->ANC;
}
Use it like this:
employee* emp = malloc(sizeof(employee));
emp->SB = 20.5;
emp->ANC = 15;
printf("SNET: %f\n", emp->SNET);
modify_employee(emp);
printf("SNET: %f\n", emp->SNET);

Related

problem passing dynamic array via function c

I have this kind of code
typedef struct {
int x;
int y;
} Test;
Test* getTest(int *length) {
Test *toReturn = malloc(sizeof(Test));
// Some operations with realloc
return toReturn;
}
void printTest(Test *arrTest, int length) {
for(int i = 0; i < length; i++) {
// Some operations
}
}
int main() {
int testlength = 0;
Test *myTest = getTest(&testlength);
printTest(myTest, testLength) // Gives random numbers
}
Don't know why it gives random numbers, when I'm in the main tho (the whole code) it does not give these kinds of errors
Made minor changes to the code, see below:
#include <stdio.h>
typedef struct {
int x;
int y;
} Test;
Test* getTest(int *length) {
Test *toReturn = (Test *)malloc(sizeof(Test));
// Some operations with realloc
return toReturn;
}
void printTest(Test *arrTest, int length) {
printf("%d ", length);
for(int i = 0; i < length; i++) {
// Some operations
}
}
int main() {
int tlen = 0;
Test *myTest = getTest(&tlen);
printTest(myTest, tlen); // Gives random numbers
printf("....Exit....");
return 0;
}

C Code doesn't run after Scanf. There's an error code stating : Exception Unhandled

I'm using a function to create a dynamic array using MALLOC.
getting user input with the use of SCANF.
for some reason I get this Error statement:
**
Unhandled exception at 0x00007FFEE518D646 (ucrtbased.dll) in Project4STRUCTS.exe: 0xC0000005: Access violation writing location 0xFFFFFFFFCD7AE350.**
THE CODE
THE PROBLEM IS IN THE FUNCTION CALLED INPUT_DATA
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 3
#include<stdio.h>
typedef struct student_init_data {
int ID;
int* StudentGradeArray;
int NumOfExams;
}Student_init_data;
typedef struct student_processed_data {
int ID;
int StudentAvg;
}Student_processed_data;
typedef struct statistics {
Student_processed_data* HIGH;
Student_processed_data* LOW;
int SizeofHIGH;
int SizeofLOW;
int Tavg;
}Statistics;
int* Input_Data(int Exams) {
int i;
int* arr = (int*)malloc(Exams * sizeof(int));
for (i = 0;i < Exams;i++)
{
printf("enter Grade: ");
scanf("%d", &arr[i]);
}
return arr;
}
int Student_Average(int* GradeArray,int NumofExams) {
int i;
int avg=0;
for (i = 0;i < NumofExams;i++)
avg = avg + GradeArray[i];
avg = avg / NumofExams;
return avg;
}
int Total_Average(Student_processed_data StudentAVG[SIZE], int NumofStudents) {
int i;
int avg = 0;
for (i = 0;i < NumofStudents;i++)
avg = avg + StudentAVG[i].StudentAvg;
avg = avg / NumofStudents;
return avg;
}
void Classification(Student_init_data InitStudentData[SIZE],Statistics *pStats) {
int i;
Student_processed_data StudentAVG[SIZE];
pStats->SizeofHIGH = 0;
pStats->SizeofLOW = 0;
for (i = 0;i < SIZE;i++)
StudentAVG[i].ID = InitStudentData[i].ID;
for (i = 0;i < SIZE;i++)
{
StudentAVG[i].StudentAvg = Student_Average(InitStudentData[i].StudentGradeArray, InitStudentData[i].NumOfExams);
}
pStats->Tavg = Total_Average(StudentAVG, SIZE);
for (i = 0;i < SIZE;i++)
{
if (StudentAVG[i].StudentAvg >= pStats->Tavg)
(pStats->SizeofHIGH)++;
else
(pStats->SizeofLOW)++;
}
pStats->HIGH = (Student_processed_data*)malloc((pStats->SizeofHIGH) * sizeof(Student_processed_data));
pStats->LOW = (Student_processed_data*)malloc((pStats->SizeofLOW) * sizeof(Student_processed_data));
for (i = 0;i < SIZE;i++)
{
if (StudentAVG[i].StudentAvg >= pStats->Tavg)
(pStats->HIGH)[i] = StudentAVG[i];// High=pointer||same as High[i]
else
(pStats->LOW)[i] = StudentAVG[i];// HIGH={ID,AVG}, StudentAVG={ID,AVG}
}
}
void Print_Tab(Statistics Stats) {
int i;
printf("Total Average is:%d ", Stats.Tavg);
printf("\n %d number of students had AVG higher than TAVG:\n", Stats.SizeofHIGH);
for (i = 0;i < Stats.SizeofHIGH;i++)
{
printf("ID:%d , AVG:%d | ", (Stats.HIGH)[i].ID, (Stats.HIGH)[i].StudentAvg);
}
printf("\n %d number of students had AVG lower than TAVG:\n", Stats.SizeofLOW);
for (i = 0;i < Stats.SizeofLOW;i++)
{
printf("ID:%d , AVG:%d | ", (Stats.LOW)[i].ID, (Stats.LOW)[i].StudentAvg);
}
}
void Free_Mem(Statistics* Pfreestat, Student_init_data* PfreeStudentData) {
free(Pfreestat->LOW);
free(PfreeStudentData->StudentGradeArray);
free(Pfreestat->HIGH);
}
void main() {
int i;
Student_init_data StudentData[SIZE];
Statistics Stats;
for (i = 0;i < SIZE;i++)
{
printf("\nEnter Stundent Num %d ID and Number of Exams:\n", i + 1);
scanf("%d", &StudentData[i].ID);
scanf("%d", &StudentData[i].NumOfExams);
StudentData[i].StudentGradeArray = Input_Data(StudentData[i].NumOfExams);
}
Classification(StudentData ,&Stats);
Print_Tab(Stats);
Free_Mem(&Stats,&StudentData);
}
ERROR MESSAGE
Thank you all,
Eyal
I tried debugging to see the problem, and couldn't get more than the understanding that the problem falls with the SCANF.
I tried looking into this certain exception online, couldn't find something with the same issue.
Some problems:
You should include #include <stdlib.h> for the memory management functions.
Change Free_Mem(&Stats,&StudentData); to Free_Mem(&Stats,StudentData); because StudentData is an array of structs.
Change free(PfreeStudentData->StudentGradeArray); to for (int i = 0; i < SIZE; i++) free(PfreeStudentData[i].StudentGradeArray);
void main() is non-standard C. Better to use int main() and return 0 at completion.
Try with these changes.

Sort struct array in lexicographical order

I need to sort students according to their surname or if their surname is the same according to their name in lexicographical order.
#include <stdio.h>
struct Student {
char name[20], surname[20];
};
void sort(struct Student students[], int n) {
int i, j, temp;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (students[j].surname > students[i].surname ||
students[j].name > students[i].name) {
temp = i;
students[i] = students[j];
students[j] = students[temp];
}
}
void main() {
struct Student students[6] = {
{"Mujo", "Mujic"},
{"Meho", "Mujic"},
{"Pero", "Peric"},
{"Beba", "Bebic"},
{"Mujo", "Mujic"},
{"Fata", "Fatic"},
};
sort(students, 6);
int i;
for (i = 0; i < 6; i++)
printf("%s %s\n", students[i].surname, students[i].name);
}
This prints only one student six times. Could you help me to fix this?
Note: using auxiliary arrays is not allowed
Your swap code is dubious — broken, I believe. A big warning bell is the type of temp — it needs to be a struct Student.
You have:
temp = i;
students[i] = students[j];
students[j] = students[temp];
You need:
struct Student temp = students[i];
students[i] = students[j];
students[j] = temp;
Obviously, remove the definition int temp; as well.
However, there are other problems too (as ever). You can't usefully compare strings using relational operators — use strcmp(). And your ordering test is wrong too, even when revised to use strcmp().
This code does the job, sorting names in descending order:
#include <stdio.h>
#include <string.h>
struct Student
{
char name[20];
char surname[20];
};
static void sort(struct Student students[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
int rc = strcmp(students[j].surname, students[i].surname);
if (rc > 0 ||
(rc == 0 && strcmp(students[j].name, students[i].name) > 0))
{
struct Student temp = students[i];
students[i] = students[j];
students[j] = temp;
}
}
}
}
static void dump_array(const char *tag, size_t size, const struct Student *students)
{
printf("%s (%zu):\n", tag, size);
for (size_t i = 0; i < size; i++)
printf("%s %s\n", students[i].surname, students[i].name);
}
int main(void)
{
struct Student students[] =
{
{"Mujo", "Mujic"},
{"Meho", "Mujic"},
{"Pero", "Peric"},
{"Zebra", "Elephant"},
{"Beba", "Bebic"},
{"Mujo", "Mujic"},
{"Abelone", "Shells"},
{"Fata", "Fatic"},
};
enum { NUM_STUDENTS = sizeof(students) / sizeof(students[0]) };
dump_array("Before", NUM_STUDENTS, students);
sort(students, NUM_STUDENTS);
dump_array("After", NUM_STUDENTS, students);
return 0;
}
Output:
Before (8):
Mujic Mujo
Mujic Meho
Peric Pero
Elephant Zebra
Bebic Beba
Mujic Mujo
Shells Abelone
Fatic Fata
After (8):
Shells Abelone
Peric Pero
Mujic Mujo
Mujic Mujo
Mujic Meho
Fatic Fata
Elephant Zebra
Bebic Beba

Reading of a char contained in a struct results in access violation exception

i am trying to implement a linked-list in C with the aim to do a BFS on it.
The input for the list should look like this:
a-bc
b-a
c-a
which represents a list looking like this:
a
/ \
b c
now, my problem is that I cannot read the variable name defined in my Vertex struct. My program segfaults with Access Reading Violation. While printf("%s", s) takes a char *, casting the name to a char* doesn't help. The error takes place before the char is even accessed?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Vertex Vertex;
typedef struct Vertex
{
char name;
int visited;
int distance;
Vertex* next;
} Vertex;
struct Vertex* AddVertex(Vertex* head, char newVertexName)
{
Vertex* newHead = malloc(sizeof(Vertex));
newHead->name = newVertexName;
printf("added vertex named: %s", newHead->name); // causing the error
newHead->next = head;
newHead->visited = 0;
newHead->distance = 0;
return newHead;
}
int main()
{
// BFS
char s[100];
int l = 0;
const int nNrOfVerts = 27;
Vertex* adjList[28];
// initialise array of pointers
for(int i = 0; i <= nNrOfVerts; ++i)
{
adjList[i] = NULL;
}
// fill vertices with user data
for(int i = 1; i <= nNrOfVerts; ++i)
{
printf("enter %d vert: ", i);
if(scanf("%s", &s) != 1)
{
break;
}
l = strlen(s);
if(l > 2)
{
for(int k = 0; k < l; ++k)
{
// increment to accustom for the - seperator
if(1 == k)
{
k = 2;
}
adjList[i] = AddVertex(adjList[i], s[k]);
}
}
for(int k = 0; k < 100; ++k)
{
s[k] = NULL;
}
}
bfs(adjList);
// printing the list
for(int i = 1; i <= l; ++i)
{
for(int j = 0; j <= nNrOfVerts; ++j)
{
if(adjList[j]->distance == i)
{
printf("Level: %d is: %s", i, adjList[j]->name);
}
printf("No node for dist: %d", i);
}
}
return 0;
}
How can I access the value of newHead->name or adjList[i]->name for that matter? The interesting thing is, if I try to access adjList[i]->distance the correct integer is returned...
You declared name as a char but then you try to print it as a character :
printf("added vertex named: %s", newHead->name);
Change the %s to %c :
printf("added vertex named: %c", newHead->name);
or change your name to a char *.

assigned value to dynamic array created in void function doesnt return the same value in main()

I have a problem with dynamic arrays in C. My program was working perfectly, but I was asked to put the creation of dynamic array into a seperate void. I did it, and it still worked great, but then I had to assign a value to a certain point of the created array in void, and make it return the said value, however, what I get is a random value. The function works by sending a pointer and the lenght of required array into void, and then makes the pointer into a dynamic array.
#include <stdio.h>
#include <stdlib.h>
#define MAX 255
void ieskom (int skaiciai[],int n, int *de, int *me, int *n1, int *n2)
{
int i = 0;
int j = 0;
int nr1 = 0;
int nr2 = 0;
int temp = 0;
int temp1 = 0;
int eile = 0;
int eile1 = 0;
int *did;
did = (int*)calloc(n,sizeof(int));
if (did==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
int *maz;
maz = (int*)calloc(n,sizeof(int));
if (maz==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
i = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] < skaiciai[i+1])
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
}
else
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
j = j + 1;
}
}
j = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] > skaiciai[i+1])
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
}
else
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
j = j + 1;
}
}
*de = did[eile];
*me = maz[eile1];
*n1 = nr1;
*n2 = nr2;
free(did);
free(maz);
}
/*int masyvas(x)
{
int y;
y = (int*)malloc(x*sizeof(int));
return y;
}*/
void *masyvas (int *skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
skaiciai[2] = 5;
return skaiciai;
}
int main()
{
int n1 = 0;
int n2 = 0;
int de = 0;
int me = 0;
int i = 0;
int n = 0;
int *skaiciai;
scanf("%d", &n);
// skaiciai = masyvas(n); // naudojant int
masyvas(&skaiciai, n);
printf("2 = %d", skaiciai[2]);
if (skaiciai==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
for (;i < n; i++)
{
scanf("%d", &skaiciai[i]);
}
ieskom (skaiciai, n, &de, &me, &n1, &n2);
if (de > me)
{
printf("Elementu numeriai:");
printf(" %d", n1-de+1);
printf(" %d\n", n1);
printf("\nAtstumas tarp ju: %d", de-2);
}
else
{
printf("Elementu numeriai:");
printf(" %d", n2-me+1);
printf(" %d\n", n2);
printf("\nAtstumas tarp ju: %d", me-2);
}
free(skaiciai);
getchar();
getchar();
return 0;
}
The problem is in void masyvas and printf skaicia[2] - I assign a certain value to skaiciai[2], yet it prints a random one. How do I fix it?
EDIT: Thank you for your answers and explanations, it really helped me a lot! I know have solved my problem, and most importantly, I know why it was a problem in the first place.
First of all, you should translate variables and texts to english (your code lack of comments, this should apply to them too).
Next your masyvas() function returns a pointer to the allocated array (why void* ?!) but when you call it you don't get the returned value.
You have to choose: either you pass a pointer to your function (an array is a pointer, to if you want an array to be allocated from a function you have to pass a pointer to the pointer, so a int **), or you use the returned value.
Allocating with returned value:
// this function allocates a int* tab of size n and set one value
int *allocate_tab(int n) {
int *tmp;
tmp = malloc(n*sizeof(int));
if (tmp == NULL) {
return(NULL); // failed
}
tmp[2] = 5;
return(tmp);
}
// in main (or other function)
int *mytab;
mytab = alloc_tab(45);
Allocating by passing a pointer to the array:
void alloc_tab(int **tab, int n) {
*tab = malloc(n*sizeof(int));
if (*tab == NULL) {
return;
}
(*tab)[2] = 5;
}
// in main (or other)
int *mytab;
alloc_tab(&mytab, 45);
If you can't understand this stuff I guess you should read more about memory, allocation and pointers.
You need to pass a pointer-to-pointer here and do not need to return anything.
void masyvas (int **skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
(*skaiciai)[2] = 5;
}
When you declare int *skaiciai, the variable is a pointer to type int. skaiciai holds the address that points to an int. When you pass &skaiciai, you're passing the address of the address that points to an int. So because this is an address of an address, its a double pointer.

Resources