Sort a structure in descending order - c

I have to sort this strucure in descending order, based on the "med" variable stored in this strucure, so if students 1 med > students 2 med, then the struct shall be printed as : * student 2 info * then * student 1 info *
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct om
{
char name[20];
int n1,n2,n3;
float med;
} a[3];
int main()
{
int i;
printf("Student's data");
for (i=0; i<3; i++)
{
printf("\nName:");
scanf("%s", a[i].name);
printf("\nGrade at maths:");
scanf("%d", &a[i].n1);
printf("\nGrade at programming:");
scanf("%d", &a[i].n2);
printf("\nGrade at english:");
scanf("%d", &a[i].n3);
a[i].med=(a[i].n1+a[i].n2+a[i].n3)/3;
}
}

Here is an example of how to do this, try to understand how the sorting function works based on some example inputs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_STUDENTS 3
struct student
{
char name[20];
int math, prog, engl;
double avg;
} students[NUM_STUDENTS];
static int compare_students(const void *s1, const void *s2)
{
double avg1 = ((struct student *)s1)->avg;
double avg2 = ((struct student *)s2)->avg;
return (avg1 > avg2) - (avg1 < avg2);
}
int main()
{
printf("Student data:\n");
for (int i=0; i<NUM_STUDENTS; i++)
{
printf("Name:");
scanf("%s", students[i].name);
printf("Grade at maths:");
scanf("%d", &students[i].math);
printf("Grade at programming:");
scanf("%d", &students[i].prog);
printf("Grade at english:");
scanf("%d", &students[i].engl);
students[i].avg = (double)students[i].math + students[i].prog + students[i].engl) / NUM_STUDENTS;
}
qsort(students, NUM_STUDENTS, sizeof(struct student), compare_students);
for (int i=0; i<NUM_STUDENTS; i++)
{
printf("Student %d: %s\n", i, students[i].name);
}
return 0;
}
I have also tried to make some general improvements, like adding a #define for the number of students, using more readable variable names and using double instead of float variables (using the latter almost never makes sense in practice). Also note that your average calculation was wrong before because the result was truncated.

man_d_sort(struct om a[])
{
if (a[0].med >= a[1].med)
{
if (a[0].med >= a[2].med)
printf("%.2lf", a[0].med);
else
printf("%.2lf", a[2].med);
}
else
{
if (a[1].med >= a[2].med)
printf("%.2lf ", a[1].med);
else
printf("%.2lf ", a[2].med);
}
}

Related

How to scanf() and printf() nested structs in C?

I created two structs, each of which I defined as a 3rd struct variable. I'm confused about calling those variables in the scanf() function and the printf() function. This is my code so far
#include <stdio.h>
#include <string.h>
#define MAX 5
typedef struct {
char namaJalan[30];
int noRumah;
char kota[30];
char provinsi[30];
} Alamat;
typedef struct {
int tanggal;
int bulan;
int tahun;
} tanggalLahir;
typedef struct {
int noDosen;
int nidn;
char nama[30];
char tempat[30];
Alamat alamat;
tanggalLahir tglLahir;
} dataDosen;
int main() {
Alamat a;
tanggalLahir t;
dataDosen d[MAX];
for (int i = 0; i < MAX; i++) {
printf("\nData dosen ke %d\n", i+1);
printf("No. Dosen: ");
scanf("%d", &d[i].noDosen);
printf("NIDN: ");
scanf("%d", &d[i].nidn);
printf("Nama: ");
scanf("%s", d[i].nama);
printf("Alamat (Jalan - No. - Kota - Provinsi ): ");
I'm confused to define this scanf
//how to define scanf variable made of struct?
scanf("%s%d%s%s", &d[i].alamat);
printf("Tempat lahir: ");
scanf("%s", d[i].tempat);
printf("Tanggal lahir (DD/MM/YYYY): ");
scanf("%d%d%d", &d[i].tglLahir);
}
printf("================ DATA DOSEN ==================\n");
printf("\n");
printf("NO\tNIDN\tNAMA\tALAMAT\tTEMPAT LAHIR\tTANGGAL LAHIR");
And how to define printf variable made of struct?
for (int i = 0; i < MAX; i++) {
printf("%d\t%d\t%s\t%s%d%s\t%s\t%d%d%d\n",
d[i].noDosen, d[i].nidn, d[i].nama, d[i].alamat, d[i].tempat, d[i].tglLahir);
}
return 0;
}

Structure Array Size in C

I am quite new to programming. Memory allocation also, still confuses me. And our professor asked us to make an array of structures wherein users will input the array size. This is to know how many entries will the users enter in the telephone directory.
Here is it so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct TelDirectory {
char name[50];
char address[100];
char tel[20];
};
int main() {
int num, add, del, prev = 0;
char ask;
*//asking for the number of entries*
printf("Number of entries: ");
scanf(" %i", &num);
struct TelDirectory *entry[num];
Input(entry, prev, num);
Display(entry, num);
//Input and Displaying
void Input(struct TelDirectory *entry[], int prev, int num) {
int i;
for (i = prev; i < num; i++) {
entry[i] = (struct TelDirectory *)malloc(sizeof(struct TelDirectory) * num);
printf("\nEnter name (last, first, middle): ");
scanf(" %[^\n]", entry[i]->name);
printf("Enter address: ");
scanf(" %[^\n]", entry[i]->address);
printf("Enter telephone number: ");
scanf(" %[^\n]", entry[i]->tel);
}
void Display(struct TelDirectory *entry[], int num) {
int i, j;
printf("%i\n", num);
struct TelDirectory *temp;
temp = (struct TelDirectory *) malloc(sizeof(struct TelDirectory) * num);
for (i = 0; i < num; i++) {
for (j = i+1; j < num; j++) {
if (strcasecmp(entry[i]->name, entry[j]->name) > 0) {
temp = entry[i];
entry[i] = entry[j];
entry[j] = temp;
}
}
}
printf("\n\t\t\t\t\tInformation\n");
printf("------------------------------------------------------------------------------------------------\n");
printf("Name\t\t\t\t\tAddress\t\t\t\t\tTelephone Number\n");
printf("------------------------------------------------------------------------------------------------\n");
for (i = 0; i < num; i++) {
printf("%-30s\t\t%-30s\t\t%-30s\n", entry[i]->name, entry[i]->address, entry[i]->tel);
}
printf("------------------------------------------------------------------------------------------------\n");
}
And, we will also be asking the users if they will update the directory through either INSERTING more entries or DELETING entries. Is it possible to change the structure array size on run time?

Having a fatal error code - corrupted heap

New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}
Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.

passing struct as argument in function

I want to pass a structure as an argument in my function but having some problems in passing it.
The code without functions is :
#include <stdio.h>
#include <stdlib.h>
struct student{
char name[100];
char roll[100];
int marks[5];
}a[3];
typedef struct student s;
void stuwise(s *a);
void subwise(s *a);
int i;
int j;
int m;
int main(int argc, char const *argv[])
{
for(i=0;i<3;i++)
{
printf("Enter Student %d Name \n",i+1);
fgets(a[i].name,100,stdin);
printf("Enter Student %d Roll Number \n",i+1);
fgets(a[i].roll,10,stdin);
for(m=0;m<5;m++)
{
printf("Enter Student %d Marks %d\n",i+1,m+1);
scanf("%d",&(a[i].marks[m]));
getchar();
}
}
printf("Student wise list :\n");
for(j=0;j<3;j++)
{
for(m=0;m<5;m++)
{
printf("Student %d Marks %d ",j+1,m+1);
printf("%d ",(a[j].marks[m]));
printf("\n");
}
printf("\n");
}
printf("Subject wise list :\n");
for(m=0;m<5;m++)
{
for(j=0;j<3;j++)
{
printf("Student %d Marks %d ",j+1,m+1);
printf("%d ",(a[j].marks[m]));
printf("\n");
}
printf("\n");
}
return 0;
}
My attempt at using functions :
#include <stdio.h>
#include <stdlib.h>
struct student{
char name[100];
char roll[100];
int marks[5];
}a[3];
typedef struct student s;
void stuwise(s *a);
void subwise(s *a);
int i;
int j;
int m;
int main(int argc, char const *argv[])
{
for(i=0;i<3;i++)
{
printf("Enter Student %d Name \n",i+1);
fgets(a[i].name,100,stdin);
printf("Enter Student %d Roll Number \n",i+1);
fgets(a[i].roll,10,stdin);
for(m=0;m<5;m++)
{
printf("Enter Student %d Marks %d\n",i+1,m+1);
scanf("%d",&(a[i].marks[m]));
getchar();
}
}
stuwise(s a);
return 0;
}
void stuwise(s *a)
{
printf("Subject wise list :\n");
for(m=0;m<5;m++)
{
for(j=0;j<3;j++)
{
printf("Student %d Marks %d ",j+1,m+1);
printf("%d ",(a[j].marks[m]));
printf("\n");
}
printf("\n");
}
}
void subwise(s *a)
{
printf("Student wise list :\n");
for(j=0;j<3;j++)
{
for(m=0;m<5;m++)
{
printf("Student %d Marks %d ",j+1,m+1);
printf("%d ",(a[j].marks[m]));
printf("\n");
}
printf("\n");
}
}
It isn't working properly as I am getting an error " expected expression before ā€˜sā€™ "
stuwise(s a); is the wrong way to call the function. You don't have to specify what type the variable is, since you already said so in the function definition.
Replace with:
stuwise(a);
or
stuwise(&a[0]);

conflicting types for allocArray

guys I'm trying to compile my program in c but I'm getting this error (conflicting types for allocArray)?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int number(int);
char *allocArray(int);
int main ()
{
printf("Enter a number: ");
int userNumber;
scanf("%d", &userNumber);
int m= number(userNumber);
printf("\nThe number is %d", m);
printf("\n");
printf("*****************************************************\n");
printf("The array is %s", alloArray(5));
}
int number(int n)
{
int num = n;
return num;
}
char *alloArray(int num)
{
char *addr;
addr = (char *) malloc(num);
//addr = char[num];
return addr;
}
You've misspelt allocArray as alloArray (twice, in fact).

Resources