Reputation: 328
I am attempting to sort a structure by last names alphabetically. I have got most of my code to work correctly, but I have not been able to get it to sort alphabetically. I attempted to use a swapper method, where you have a temp holder, swap the temp with the [s], and swap the [s] with the [s+1], but I could not get it to swap correctly. I attempted to make a function and transfer the structure to the function, but I could not get that to function correctly either. I am new to C and my syntax isn't that great. I have gotten decent at sorting arrays full of numbers, but I haven't been able to find any examples of sorting structures to go by. Any help would be greatly appreciated. Here is my code so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student{
char f_name[20];
char l_name[20];
char temp[20];
int id_num;
float test1;
float test2;
float test3;
}s[10];
int main(void)
{
char grade;
float average;
int i, j, b;
for(i=0;i<10;i++)
{
printf("Enter first name(ZZ to quit): ");
scanf("%s", &s[i].f_name);
if(strcmp(s[i].f_name, "ZZ")==0)
break;
else
{
printf("Enter students last name: ");
scanf("%s", &s[i].l_name);
printf("Enter Student ID: ");
scanf("%d", s[i].id_num);
printf("Enter 3 test scores: ");
scanf("%f %f %f", &s[i].test1, &s[i].test2, &s[i].test3);
b++;
}
}
i--;
printf("Student\t\tStudent Id\tFinal Grade\n");
for(i;i>=0;i--)
{
average = (s[i].test1 + s[i].test2 + s[i].test3) / 3;
if(average >= 90)
grade = 'A';
else if(average >=80 || < 90)
grade = 'B';
else if(average >= 70 || < 80)
grade = 'C';
else if(average >= 60 || < 70)
grade = 'D';
else
grade = 'F';
printf("%s, %s\t%d\t\t%.2f \t%c\n", s[i].l_name, s[i].f_name, s[i].id_num, average, grade);
}
return 0;
}
Upvotes: 4
Views: 1962
Reputation: 61
Since you are new to C, I inserted sorting code into your own code and made a few minor, but necessary corrections.
Your code isn't too long, so I pasted the complete program below with comments explaining the added code.
This is not an optimal or efficient solution, but I wanted to get your own code working, without altering it much, so that you could understand the solution, and without introducing many new concepts that you might not understand.
As you learn more, and if you move on to C++, you'll find that there are much more elegant and efficient ways to solve this problem (especially with C++ and its sorting algorithms).
I also sorted by first name, if last names are the same, and included commented out hard code, so you can test it more quickly, as I hope that you will continue to refactor and improve your code on your own.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student{
char f_name[20];
char l_name[20];
char temp[20];
int id_num;
float test1;
float test2;
float test3;
}s[10];
int main(void)
{
char grade;
float average;
int i, j = 0, b = 0; //CORRECTION
////hard code for testing. UNCOMMENT, THEN COMMENT OUT INPUT 'FOR LOOP' FOR HARD CODE TESTING
//strcpy(s[4].f_name, "Rob");
//strcpy(s[4].l_name, "Zenf");
//s[4].id_num = 5;
//s[4].test1 = 60, s[4].test2 = 65, s[4].test3 = 70;
//strcpy(s[3].f_name, "Red");
//strcpy(s[3].l_name, "Zenf");
//s[3].id_num = 4;
//s[3].test1 = 80, s[3].test2 = 70, s[3].test3 = 75;
//strcpy(s[2].f_name, "Adam");
//strcpy(s[2].l_name, "Ant");
//s[2].id_num = 3;
//s[2].test1 = 100, s[2].test2 = 100, s[2].test3 = 100;
//strcpy(s[1].f_name, "Zac");
//strcpy(s[1].l_name, "Miller");
//s[1].id_num = 2;
//s[1].test1 = 60, s[1].test2 = 50, s[1].test3 = 40;
//strcpy(s[0].f_name, "Ed");
//strcpy(s[0].l_name, "George");
//s[0].id_num = 1;
//s[0].test1 = 90, s[0].test2 = 80, s[0].test3 = 70;
//i = 5; // 1 more than index number of last hard-coded student
////end hard code
//COMMENT OUT THIS 'FOR LOOP' FOR HARD CODE TESTING
for (i = 0; i<10; i++)
{
printf("Enter first name(ZZ to quit): ");
scanf("%s", &s[i].f_name);
if (strcmp(s[i].f_name, "ZZ") == 0)
break;
else
{
printf("Enter students last name: ");
scanf("%s", &s[i].l_name);
printf("Enter Student ID: ");
scanf("%d", &s[i].id_num); //CORRECTION
printf("Enter 3 test scores: ");
scanf("%f %f %f", &s[i].test1, &s[i].test2, &s[i].test3);
b++;
}
}
i--;
//BEGINNING OF INSERTED SORT CODE. SHOULD BE REFACTORED INTO A FUNCTION
int least;
//Nested for loops. For every Student (except the first; this
//algorithm sorts in reverse alphabetical order, because
//your output 'for loop' prints in descending order), will
//compare with every remaining student name in second (nested)
//for loop, and swap with student name that comes first
//alphabetically in the second for loop, if any.
for (int counter = i; counter > 0; --counter) {
least = counter;
for (int k = counter - 1; k > -1; --k) {
// Compare last names. If same, compare first name
if ( (strcmp(s[k].l_name, s[least].l_name) < 0) ||
( (strcmp(s[k].l_name, s[least].l_name) == 0) &&
(strcmp(s[k].f_name, s[least].f_name) < 0) ) )
least = k;
}
// Very manual swap of values.
// Swaps take this format: temp = a; a = b; b = temp;
char temp_f_name[20]; strcpy(temp_f_name, s[least].f_name);
char temp_l_name[20]; strcpy(temp_l_name, s[least].l_name);
char temp_temp[20]; strcpy(temp_temp, s[least].temp);
int temp_id_num = s[least].id_num;
float temp_test1 = s[least].test1;
float temp_test2 = s[least].test2;
float temp_test3 = s[least].test3;
strcpy(s[least].f_name, s[counter].f_name);
strcpy(s[least].l_name, s[counter].l_name);
strcpy(s[least].temp, s[counter].temp);
s[least].id_num = s[counter].id_num;
s[least].test1 = s[counter].test1;
s[least].test2 = s[counter].test2;
s[least].test3 = s[counter].test3;
strcpy(s[counter].f_name, temp_f_name);
strcpy(s[counter].l_name, temp_l_name);
strcpy(s[counter].temp, temp_temp);
s[counter].id_num = temp_id_num;
s[counter].test1 = temp_test1;
s[counter].test2 = temp_test2;
s[counter].test3 = temp_test3;
} //END OF INSERTED SORT CODE
printf("Student\t\tStudent Id\tFinal Grade\n");
for (i; i >= 0; i--)
{
average = (s[i].test1 + s[i].test2 + s[i].test3) / 3;
if (average >= 90)
grade = 'A';
else if (average >= 80 && average < 90) //CORRECTION. Use && not ||. Needed "average" again
grade = 'B';
else if (average >= 70 && average < 80) //CORRECTION
grade = 'C';
else if (average >= 60 && average < 70) //CORRECTION
grade = 'D';
else
grade = 'F';
printf("%s, %s\t%d\t\t%.2f \t%c\n", s[i].l_name, s[i].f_name, s[i].id_num, average, grade);
}
return 0;
}
Upvotes: 1