Building a struct with a function - c

Hello i'm trying to build a function to search a car for a client by client demand.
The structure contains: model,year,price.
the client is asked to enter his demands and then the code calls a function that check if there is a car in the structure that is suitable for him.
I get error for "access violation reading error"
thanks!
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define SIZE 10
typedef struct
{
char model[10];
float price;
int year;
}car;
void findCar(car *arr[], int minYear, float maxPrice, char modelWanted, int carAmount);
int main()
{
int carAmount;
car* arr;
puts("How many cars?");
scanf("%d", &carAmount);
arr = (car*)malloc(carAmount * sizeof(car));
if (arr == NULL)
return -1;
for (int i = 0; i < carAmount; i++)
{
puts("Enter car details, Model, Price,Year");
scanf("%s%f%d",arr[i].model,&arr[i].price,&arr[i].year);
}
char modelWanted[SIZE];
float maxPrice;
int minYear;
puts("Enter wanted model,maximum price and minimum year!");
scanf("%s%f%d", modelWanted, &maxPrice, &minYear);
for (int i = 0; i < carAmount; i++)
printf("Model is: %s, Price is: %.2f, Year is: %d\n", arr[i].model, arr[i].price, arr[i].year);
findCar(&arr, minYear, maxPrice, modelWanted, carAmount);
free(arr);
return 1;
}
void findCar(car *arr[], int minYear, float maxPrice, char modelWanted,int carAmount)
{
int i, counter = 0;
for (i = 0; i < carAmount; i++)
if (((strcmp(arr[i]->model, modelWanted)) == 0) && (arr[i]->year >= minYear) && (arr[i]->price <= maxPrice))
{
printf("Model is: %s, Price is: %.2f, Year is: %d\n", arr[i]->model, arr[i]->price, arr[i]->year);
++counter;
}
printf("We found %d cars for you!", counter);
}

You are passing pointer to array of struct
car *arr[]
so instead of accessing elements by arr[i]->model like you do, you should access them using (*arr)[i].model. The method you uses is for accessing the array of pointers to struct element, but you have pointer to array of struct.
Of course already commented char instead of char* will also cause run time error, but you should have received compiler warning for this.

Related

Using structures in C with user defined functions

I had came across a problem that I have tried so many times with different ways but still not able to obtain the required solution please do help me.
PROBLEM: Define a structure to store students’ details. Pass them to a function where the student with HIGHEST CGPA is calculated from a set of 5 students. And display the result.(Here we have to store name, age and CGPA obtained of each student)
Here is my try at the problem:
#include <stdio.h>
void highCGPA(float b,struct detst D[4]);
struct detst
{
int age;
float CGPA;
char name[30];
};
int main()
{
struct detst D[4];
int i;
float h;
for(i=0;i<=4;i++)
{
printf("Enter the name of student %d:\n",i+1);
scanf("%s",&D[i].name);
printf("Enter the age of student %d:\n",i+1);
scanf("%d",&D[i].age);
printf("Enter the CGPA obtined by student %d:\n",i+1);
scanf("%f",&D[i].CGPA);
}
highCGPA(h,D);
}
void highCGPA(float b,struct detst D[4])
{
int i,max;
max = D[0].CGPA;
for(i=0;i<=4;i++)
{
if(D[i].CGPA > max)
{
max = D[i].CGPA;
}
}
printf("Highest CGPA obtained is:\n%f",max);
}
There is more than one problem. You're trying to store the data of 5 students in an array of struct with size 4. So:
struct detst D[5]; // fixed size
int i;
float h;
for(i=0;i<5;i++) { // EDIT (comments suggestion): for loop fix following standard convetions
/* take input */
}
Lastly, if you declare max as an int, you can't try to print it with a format specifier for float. So:
printf("Highest CGPA obtained is: %d\n",max); // format specifier for int is %d (not %f)
There are couple of other problems.
your declaration of funtion highCGPA is above your struct detst definition
you should have got error
error: array type has incomplete element type ‘struct detst’
declare your function after the structure definition.
your max variable is int in the function highCGPA , but you are trying to store a float value in it.
With a sligth change to program functionallity can be improved:
#include <float.h> // FLT_MAX
#include <stdio.h>
struct detst
{
int age;
float CGPA;
char name[30];
};
// Return offset of student with highest CGPA
int highCGPA(struct detst const (*D)[5]); // Using pointer to array
// to avoid degeneration
int main()
{
struct detst D[5];
int i;
for(i = 0; i < 5; i++)
{
printf("Enter the name of student %d:\n", i + 1);
scanf("%29s", D[i].name); // Make sure we don't overwrite the buffer
printf("Enter the age of student %d:\n", i + 1);
scanf("%d", &D[i].age);
printf("Enter the CGPA obtained by student %d:\n", i + 1);
scanf("%f", &D[i].CGPA);
}
int bestStudentOffset = highCGPA(&D); // By asking for best student
// we can obtain a lot more
printf(
"Best student is %d year old %s with\n",
D[bestStudentOffset].age,
D[bestStudentOffset].name);
printf("Highest CGPA obtained is:\n%f\n", D[bestStudentOffset].CGPA);
}
// Return offset of student with highest CGPA
int highCGPA(struct detst const (*D)[5])
{
int i, maxOffset = -1;
float max = -FLT_MAX;
for(i = 0; i < 5; i++)
{
if((*D)[i].CGPA > max)
{
max = (*D)[i].CGPA;
maxOffset = i;
}
}
return maxOffset;
}

Proper use of structures and pointers

I have to declare a vector with the "struct" type which, for every n students, it creates a value for the group that student belongs to (which is like a counter), their names and their grades.
The program has to output the name of the students with the highest grade found in these groups. I have to allocate the vector on the heap (I only know the theoretical explanation for heap, but I have no idea how to apply it) and I have to go through the vector using pointers.
For example if I give n the value 4, there will be 4 students and the program will output the maximum grade together with their names as shown here.
This will output Ana 10 and Eva 10.
I gave it a try, but I have no idea how to expand it or fix it so I appreciate all the help I can get with explanations if possible on the practical application of heap and pointers in this type of problem.
#include <stdio.h>
#include <stdlib.h>
struct students {
int group;
char name[20];
int grade;
};
int main()
{
int v[100], n, i;
scanf("%d", n);
for (i = 0; i < n; i++) {
v[i].group = i;
scanf("%s", v[i].name);
scanf("%d", v[i].grade);
}
for (i = 0; i < n; i++) {
printf("%d", v[i].group);
printf("%s", v[i].name);
printf("%d", v[i].grade);
}
return 0;
}
Here I was just trying to create the vector, nothing works though..
It appears, int v[100]; is not quite what you want. Remove that.
You can follow either of two ways.
Use a VLA. After scanning the value of n from user, define the array like struct students v[n]; and carry on.
Define a fixed size array, like struct students v[100];, and use the size to limit the loop conditions.
That said,
scanf("%d", n); should be scanf("%d", &n);, as %d expects a pointer to integer type argument for scanf(). Same goes for other cases, too.
scanf("%s", v[i].name); should better be scanf("%19s", v[i].name); to avoid the possibility of buffer overflow by overly-long inputs.
Even though you are asking for the number of students (groups) using scanf, you hardcoded the upper bound of this value using v[100]. So, I passed your input variable n (the number of students) to malloc in order to allocate the space you need for creating an array of n students.
Also, I used qsort to sort the input array v where the last element would be the max value. Here qsort accepts an array of structs and deference the pointers passed to the comp function to calculate the difference of the comparison.
Finally, I printed the sorted array of structs in the last loop.
#include <stdio.h>
#include <stdlib.h>
struct students {
int group;
char name[20];
int grade;
};
int comp(const void *a, const void *b)
{
return ((((struct students *)a)->grade > ((struct students *)b)->grade) -
(((struct students *)a)->grade < ((struct students *)b)->grade));
}
int main()
{
int n;
printf("Enter number of groups: ");
scanf("%d", &n);
printf("\n");
struct students *v = malloc(n * sizeof(struct students));
int i;
for(i = 0; i < n; i++)
{
v[i].group = i;
printf("\nName: ");
scanf("%s", v[i].name);
printf("Grade: ");
scanf("%d", &v[i].grade);
}
qsort(v, n, sizeof(*v), comp);
for(i = 0; i < n; i++)
{
printf("Group %d, Name %s, grade %d\n", v[i].group, v[i].name, v[i].grade);
}
return (0);
}
You need to replace the standalone array v[100], with an array of structs referencing your structure:
struct students v[100];
However, if you want to use malloc to allocate memory on the heap, you will need to do something like this:
struct students *students = malloc(n * sizeof(struct students));
/* Check void* return pointer from malloc(), just to be safe */
if (students == NULL) {
/* Exit program */
}
and free the requested memory from malloc() at the end, like this:
free(students);
students = NULL;
Additionally, adding to #Sourav Ghosh's answer, it is also good to check the return value of scanf(), especially when dealing with integers.
Instead of simply:
scanf("%d", &n);
A more safe way is this:
if (scanf("%d", &n) != 1) {
/* Exit program */
}
With all this said, your program could look something like this:
#include <stdio.h>
#include <stdlib.h>
#define NAMESTRLEN 20
typedef struct { /* you can use typedef to avoid writing 'struct student' everywhere */
int group;
char name[NAMESTRLEN+1];
int grade;
} student_t;
int
main(void) {
int n, i;
printf("Enter number of students: ");
if (scanf("%d", &n) != 1) {
printf("Invalid input.\n");
exit(EXIT_FAILURE);
}
student_t *students = malloc(n * sizeof(*students));
if (!students) {
printf("Cannot allocate memory for %d structs.\n", n);
exit(EXIT_FAILURE);
}
for (i = 0; i < n; i++) {
students[i].group = i;
printf("Enter student name: ");
scanf("%20s", students[i].name);
printf("Enter students grade: ");
if (scanf("%d", &(students[i].grade)) != 1) {
printf("Invalid grade entered.\n");
exit(EXIT_FAILURE);
}
}
printf("\nStudent Information:\n");
for (i = 0; i < n; i++) {
printf("Group: %d Name: %s Grade: %d\n",
students[i].group,
students[i].name,
students[i].grade);
}
free(students);
students = NULL;
return 0;
}

C - Passing structures through function arguments

I am asked to write a function that takes two values from the structure type and compare them. If they are equal, it wants me to add two other values from those structures and send this to another structure. It is also supposed to return a 1 or 0 through the functions name, so I defined the function as an int.
I have attempted to write a program that takes an employee's social security number and their wage, and then another employee's ssn and wage. If the socials are the same, it will combine the two wages and send them to another structure which contains that employees total wages.
I am getting errors every time I mention the function compare. This appears to be due to the arguments of the function. How can this be done properly?
#include <stdio.h>
#include <stdlib.h>
#define EMPLOYEE_COUNT 4
struct ewage
{
int ssn;
int wage;
}
struct record
{
int totalwage;
}
int compare(struct ewage s1, struct ewage s2, struct record *r);
int main (void)
{
struct ewage e[EMPLOYEE_COUNT];
struct record r[EMPLOYEE_COUNT];
int i, j;
for (i = 0; i < EMPLOYEE_COUNT; i ++)
{
for (j = i + 1; j < EMPLOYEE_COUNT; j ++)
{
int success = compare(e[i], e[j], &record[i]);
if (success == 1)
printf ("%d / %d | Record: %d \n", i, j, record[i]);
else
printf ("%d / %d | DOES NOT MATCH \n", i, j);
}
}
system ("PAUSE");
return 0;
}
int compare(struct ewage s1, struct ewage s2, struct record *r)
{
if (s1.ssn == s2.ssn)
{
r->totalwage = s1.wage + s2.wage;
return 1;
}
return 0;
}
You need semicolons after your struct defintion
struct ewage
{
int ssn;
int wage;
}; // here
struct record
{
int totalwage;
}; // here
record is not defined, I assume it's real name is r
int success = compare(e[i], e[j], &r[i]); // here
if (success == 1)
printf ("%d / %d | Record: %d \n", i, j, &r[i]); // here
Finally, you need something to print with the final %d, I assume total wage here:
printf ("%d / %d | Record: %d \n", i, j, r[i].totalwage); // here
Now you can start to debug it ...
there are a few mistakes:
1.there should be a ';' after the definition of a struct
2.you shouldn't pass a type 'record' to your function compare,instead you should pass &r[i]

Segmentation Error in C program When Run

I've tried malloc, and no malloc and it will build but not run or compile. When I run the code on codepad.org it gives me a segmentation error. I have an array of structures I'm inputting and I'm searching through them for a specific item. That's as far as I got and no compile. The code is as follows (I used netbeans, codeblocks, and visual basic 2012 programs):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 20
#define BLOODTYPESIZE 4
#define MAX 120000
typedef struct {
int month;
int day;
int year;
} dateT;
typedef struct {
int hour;
int minute;
} timeT;
typedef struct {
char name[SIZE];
char organname[SIZE];
char bloodtype[BLOODTYPESIZE];
dateT dateAdded;
timeT timeAdded;
int received;
} organT;
int main(void) {
int i, n, k, j;
int c;
int *ptr;
char organ[SIZE];
char bloodkind[BLOODTYPESIZE];
organT patient[MAX];
scanf("%d",&n);
ptr = (int *)malloc(n * sizeof(*ptr));
printf("Enter patient information\n");
for(i=1; i<=n; i++){
scanf("%s", patient[i].name[SIZE]);
scanf("%s", patient[i].organname[SIZE]);
scanf("%s", patient[i].bloodtype[BLOODTYPESIZE]);
scanf("%d %d %d", patient[i].dateAdded);
scanf("%d %d", patient[i].timeAdded);
patient[i].received = 0;
}
scanf("%d", &k);
for(j=0; j<k; j++) {
gets(organ);
printf("Organ received: %s", organ);
gets(bloodkind);
printf("Organ has blood type: %s", bloodkind);
}
for (c=0; c<n; c++){
if(patient[i].organname == organ){
if(patient[i].bloodtype == bloodkind){
if(patient[i].received == 0) {
printf("Patient(s) Found!\n");
printf("%s", patient[i].name[SIZE]);
printf("Organ received: %s", organ);
patient[i].received = 1;
}
if(patient[i].received == 1)
printf("Patient already received organ\n");
}
else("Not correct blood type\n");
}
else("No match found\n");
}
return (EXIT_SUCCESS);
}
Looks like you are not using the address correctly. For example, when you say
scanf("%s", &patient[i].name[SIZE]);
you are actually reading past the allocated space for patient[i].name. You should change the statement to
scanf("%s",patient[i].name);
and fix other statements similarly.
First check n compare to MAX
here you access to bloodtype[BLOODTYPESIZE] but the last item in this tab is bloodtype[BLOODTYPESIZE-1]
scanf("%s", &patient[i].bloodtype[BLOODTYPESIZE]);
The same problem is tru for other acces in the pararagraph.

Expression must have class type error

I'm working on a homework assignment and I've hit a brick wall. I think I have all of the code that I need, I just need to get the program to compile. The object of the assignment is
Create a structure to hold student names and averages. The structure should contain a first name, last name and an integer grade average.
Then:
Write a program that will do the following:
1.) Create an array of pointers to these student structures.
2.) Prompt the user for names and averages.
3.) After you get the student’s information use malloc to provide the memory to store the information.
4.) Place the address of the student, returned by malloc, into the pointer array.
5.) AFTER the user indicates there are no more students:
Search the data entered and find the highest and lowest grade
average.
a)Print the name and grade for the highest grade
b)Print the name and grade for the lowest grade
c)Print the average of all grades entered
Here is my code:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#define SIZE 25
int enterStudents (int ePointArray[SIZE]);
void searchData (int *sPointArray, int *sHigh, int *sLow);
int calculateAvg (int, int *avgPointArray);
void printData (int, int *pHigh, int *pLow);
struct student
{
char firstName[20];
char lastName[20];
int average;
};
int main()
{
int pointArray[SIZE], high[3], low[3];
int i = 0, studentCounter, avgGrade;
for (i = 0; i < SIZE; i++)
pointArray[i] = 0;
studentCounter = enterStudents(pointArray);
searchData(pointArray, high, low);
avgGrade = calculateAvg(studentCounter, pointArray);
printData(avgGrade, high, low);
return 0;
}
int enterStudents (int ePointArray[SIZE])
{
char tempFname[20], tempLname[20], yesNo[2] = "y";
int tempAvg, counter = 0;
int *studPtr;
struct student aStud={"\0", "\0", 0};
while( counter < SIZE && strcmp(yesNo, "y")==0)
{
printf(" Enter first name: ");
scanf("%s", tempFname);
printf(" Enter last name: ");
scanf("%s", tempLname);
printf(" Enter grade average:");
scanf("%d", tempAvg);
strcpy(aStud.firstName, tempFname);
strcpy(aStud.lastName, tempLname);
aStud.average = tempAvg;
studPtr = malloc(sizeof(struct student));
ePointArray[counter] = *studPtr;
counter++;
printf("/n");
printf(" Do you have more students? yes or no:");
scanf("%s", yesNo);
}
return counter;
}
void searchData (int sPointArray[SIZE], int sHigh[3], int sLow[3])
{
int searchCounter = 0;
while( searchCounter = 0)
{
if( *sPointArray[searchCounter].average > *sPointArray[searchCounter+1].average)
{
sHigh[0] = &sPointArray[searchCounter].firstName;
sHigh[1] = &sPointArray[searchCounter].lastName;
sHigh[2] = &sPointArray[searchCounter].average;
}
if( *sPointArray[searchCounter].average < *sPointArray[searchCounter+1].average)
{
sLow[0] = &sPointArray[searchCounter].firstName;
sLow[1] = &sPointArray[searchCounter].lastName;
sLow[3] = &sPointArray[searchCounter].average;
}
searchCounter++;
}
}
int calculateAvg( int totalStudents, int avgPointArray[SIZE])
{
int sum = 0;
int avgCounter;
double overallAvg;
for( avgCounter = 0; avgCounter < totalStudents; avgCounter++)
sum = sum + *avgPointArray[avgCounter].average;
overallAvg = sum/totalStudents;
return overallAvg;
}
void printData (int pAverage, int pHigh[3], int pLow[3])
{
printf(" Highest Grade: %s %s %d", pHigh[0], pHigh[1], pHigh[3]);
printf("/n");
printf(" Lowest Grade: %s %s %d", pLow[0], pLow[2], pLow[3]);
printf("/n");
printf(" Average Grade: %d",pAverage);
}
The main chunk of problems come from the searchData function. In the if statements, every occurrence of *sPointArray and &sPointArray is underlined in red and the error reads
"Error: expression must have class type"
The same thing also happens in the calculateAvg function with *avgPointArray in the for loop. I know that the error is a fairly common problem for noobie C programmers (i.e myself) and that it generally has to do with writing the code as a function instead of a statement or something like that, but I can't for the life of me find where I have went wrong. Any help would be highly appreciated. I've been working at this for so long my vision is blurring.
Also, for anyone who solves this in like two seconds and wants proof that I'm a true idiot, there is an error in the enterStudents function where it says StudPtr = malloc(sizeof...). The error shows under the assignment symbol and says
"Error: a value of type "void*" cannot be assigned to an entity of type "int*".
I understand this concept in theory, but some advice for how to fix it would be highly appreciated.
Thank you in advance for any help.
You declare the sPointArray as an array of integers, but use it as an array of structures.

Resources