I am basically done with this program, but now my only problem sorting the students GPA from lowest to highest.

this is the .dat file (its the ways its suppose to look like when printed out):

ANNA A ADAMS 11 A STREET ALLENTOWN PA 11111 11 5.50
BOB B BRADBURY 22 B ROAD BOSTON MA 22222 22 2.22
CARLA C COTTRELL 33 C AVENUE CHICAGO IL 33333 33 3.33
DENNIS D DODD 44 D SQUARE DETROIT MI 44444 44 4.44
ERICA E EVANS 55 E STREET EUGENE OR 55555 55 9.99
FRANK F FIELDS 66 F ROAD FLAGSTAFF AZ 66666 66 6.66
GLENDA G GROGAN 77 G AVENUE GREAT FALLS MT 77777 77 7.77
HARRY H HALL 88 H WAY HONOLULU HI 88888 88 8.88
IDA I IFIELD 99 I STREET INDIANAPOLI IN 99999 99 1.11

The function i need help with is at the very bottom.
(void sortIntArray(StudFile sRec[], int num))
i have some of it started but im not sure how to finish it correctly.
i then need to print it out

i also need to sort the students by last name.
i will also need some help with this too.

//Patrick Gutierrez
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//Defines go here:
#define FIRST 7
#define MIDDLE 1
#define LAST 9
#define STREET 16
#define CITY 12
#define STATE 2
#define ZIP 5
#define AGE 3
#define GPA 5
#define MAX 81
#define CLASS 9

//student's address info (added +1 to make room for null char)
typedef struct
{
    char streetAddress[STREET + 1];
    char cityName[CITY + 1];
    char stateAbb[STATE + 1];
    char zipCode[ZIP + 1];
} Address;

//student's personal info (added +1 to make room for null char)
typedef struct
{
    char firstName[FIRST + 1];
    char middleInitial[MIDDLE + 1];
    char lastName[LAST + 1];
    Address address;
    int studentAge;
    double studentGPA;
} StudFile;

//Protypes go here:
void readFile(StudFile sRec[]);
void strsub(char s1[],char s2[], int start, int length);
void printClass(StudFile sRec[]);
void highestGPA(StudFile sRec[]);
double averageGPA(StudFile sRec[]);
void aboveGPA(StudFile sRec[], double average);
void youngBelowGPA(StudFile sRec[], double average);
void sortIntArray(StudFile sRec[], int num);
//void printSort(StudFile sRec[], int num);

void main(void)
{
    double average_gpa = 0;

    StudFile student[CLASS];
    readFile(student);
    printClass(student);
	highestGPA(student);
    average_gpa = averageGPA(student);
    aboveGPA(student,average_gpa);
	youngBelowGPA(student, average_gpa);
	sortIntArray(student, 9);
	//printSort(student, 9);
}

void readFile(StudFile s[])
{
    char line[MAX];
    char tempAGE[AGE];
    char tempGPA[GPA];
    int i = 0;

	FILE *fp;
    errno_t err;
    err = fopen_s(&fp, "Students.dat", "r");
    if(err){
        printf("File cannot be found!\n");
        exit(1);
    }
    while(!feof(fp)){
        fgets(line, MAX, fp);
        strsub(line, s[i].firstName, 0, FIRST);
        strsub(line, s[i].middleInitial, 8, MIDDLE);
        strsub(line, s[i].lastName, 10, LAST);
        strsub(line, s[i].address.streetAddress, 20, STREET);
        strsub(line, s[i].address.cityName, 37, CITY);
        strsub(line, s[i].address.stateAbb, 49, STATE);
        strsub(line, s[i].address.zipCode, 52, ZIP);
        strsub(line, tempAGE, 58, AGE - 1);
        strsub(line, tempGPA, 61, GPA - 1);
        s[i].studentAge = atoi(tempAGE);
        s[i].studentGPA = atof(tempGPA);
        i++;
    }
    fclose(fp);
}

void strsub(char s1[],char s2[], int start, int length)
{
    int i;

    for(i = start; i < (start + length); ++i){
        s2[i - start] = s1[i];
    }
    s2[i - start] = '\0';
}

//Prints the class .dat file
void printClass(StudFile sRec[])
{
    int i;

    printf("Students in class:\n\n");
    for(i=0;i<CLASS;++i){
		printf("%s %s %s ", sRec[i].firstName, sRec[i].middleInitial, sRec[i].lastName);
		printf("%s %s ", sRec[i].address.streetAddress, sRec[i].address.cityName);
		printf("%s %s ", sRec[i].address.stateAbb, sRec[i].address.zipCode);
		printf("%i, %.2f\n", sRec[i].studentAge, sRec[i].studentGPA);
    }
    printf("\n\n");
}

void highestGPA(StudFile sRec[])
{
    int i, x = 0;

    for(i = 0; i < CLASS; ++i){
        if(sRec[i].studentGPA > sRec[x].studentGPA)
            x = i;
    }
	printf("Student with Highest GPA: \n");
	printf("%s %s %s GPA is: %.2f.\n\n", sRec[x].firstName, sRec[x].middleInitial,
        sRec[x].lastName, sRec[x].studentGPA);
}

double averageGPA(StudFile sRec[])
{
    int i;
    double sum = 0;

    for(i = 0; i < CLASS; ++i){
        sum+= sRec[i].studentGPA;
    }
    printf("Average GPA: %.2f\n\n", sum / i);
    return (sum / i);
}


void aboveGPA(StudFile sRec[],double average)
{
    int i;

    printf("Students with higher than average GPA:\n");
    for(i = 0; i < CLASS; i++){
        if(sRec[i].studentGPA >= average){
			printf("%s %s %s GPA is: %.2f.\n", sRec[i].firstName, sRec[i].middleInitial, 
				sRec[i].lastName, sRec[i].studentGPA);
        }
    }
	printf("\n");
}

void youngBelowGPA(StudFile sRec[], double average)
{
	int i, x = 0;

	printf("Youngest student with GPA below average: \n");
	for(i = 0; i < CLASS; ++i){
		 if((sRec[i].studentGPA < average) && (sRec[i].studentAge <= sRec[x].studentAge))
			 x = i;
	}
		printf("%s %s %s GPA is: %.2f.\n\n", sRec[x].firstName, sRec[x].middleInitial,
        sRec[x].lastName, sRec[x].studentGPA);
}

void sortIntArray(StudFile sRec[], int num)
{
	int i, j; // indexes into unsorted and sorted partitions
	int temp; // temporarily holds an element from the array
	
	for (i = 1; i < num; ++i) {
		temp = sRec[i].studentGPA;
		j = i - 1;
		while (j >= 0 && temp < sRec[j].studentGPA) {
			sRec[j + 1].studentGPA = sRec[j].studentGPA;
			j = j - 1;
		}
		sRec[j + 1].studentGPA = temp;
	}

}

Do you really have to do this using C? There are some beautiful Linux command line tools to accomplish such chores.

yes i do. it's an assignment. any help would be appreciated.

also i forgot to mention:

compiler: visual studio
os: microsoft

Edited 5 Years Ago by tastyTreeHUGGER: n/a

The best way to sort structs, is to NOT sort the structs. ;) Sort an index array of simple int's, instead.

This is an example of "sorting" by the index. No data is moved in the process (the original order is retained). All the data can be written or displayed, in sorted order.

/* A small example of sorting through an index 
on an array of structs. The key is a string array member

status: ok 
*/

#include <stdio.h>

#define NumItems 4
#define StringLen 30

typedef struct {  //a simple struct with a string member
  char fname[30];
}name;           //and it's name is "name"

int main() {

   int i, j, temp; 

   //thanks, I'll take 4 of each:
   int Index[NumItems];
   name names[NumItems] = { {"Denise"},{"Barbara"},{"Abbey"},{"Cynthia"} };

   //initialize the index array
   for(i = 0; i < NumItems; i++)
      Index[i] = i;

   //now do a simple sort, using the initialized index array 

   for(i = 0; i < NumItems - 1; i++)  {
      for(j = i + 1; j < NumItems; j++)  {
         //only strcmp() compares strings! ;)
         if(strcmp(names[Index[i]].fname, names[Index[j]].fname) > 0) {
            //string i > string j, so it's out of sorted order
            temp = Index[i];      
            Index[i] = Index[j];  //so swap the indeces
            Index[j] = temp;
         }
      }
   }

   //Now to see the sorted data, use the Index array 
   printf("\n\n\n char array struct member, sorted by the Index[] :\n\n");
   for(i = 0; i < NumItems; i++)  
      printf("%s \n", names[Index[i]].fname);

   printf("\n\n\n Original data:\n\n");
   //to see the unsorted data
   for(i = 0; i < NumItems; i++)
      printf("%s \n", names[i].fname);


   printf("\n\n\t\t\t     press enter when ready");
   i = getchar();
   return 0;
}

There's nothing wrong with using the command line tools for this, but your assignment is undoubtedly to use C, and C has some nice tricks of it's own.

ok this is what i have now, but now it's saying:
warning C4244: 'initializing' : conversion from 'double' to 'char', possible loss of data
error C2440: 'function' : cannot convert from 'double' to 'const char *
warning C4024: 'strcmp' : different types for formal and actual parameter 1
'function' : cannot convert from 'double' to 'const char *'
warning C4024: 'strcmp' : different types for formal and actual parameter 2

void sortIntArray(StudFile sRec[], int num)
{
	int i, j, temp;
	int index[CLASS];

	StudFile gpa[CLASS] = {5.50, 2.22, 3.33, 4.44, 9.99, 6.66, 7.77, 8.88, 1.11};
	for (i = 0; i < CLASS; i++)
		index[i] = i;
	for (j = i + 1; j < CLASS; j++) {
		if(strcmp(gpa[index[i]].studentGPA, gpa[index[j]].studentGPA) > 0) {
				temp = index[i];
				index[i] = index[j];
				index[j] = temp;
		}
	}
	for(i = 0; i < CLASS; i++)
		printf("%s \n", gpa[index[i]].studentGPA);
}

Edited 5 Years Ago by tastyTreeHUGGER: n/a

Ok, some touch up needed for your function:

Note that I sorted the strings in my example, because strings are harder for new C coder's to sort than numbers. Numbers compare directly, but strings have to be compared using strcmp() function.

void sortIntArray(StudFile sRec[], int num)
{
	int i, j, temp;
	int index[CLASS];

	StudFile gpa[CLASS] = {5.50, 2.22, 3.33, 4.44, 9.99, 6.66, 7.77, 8.88, 1.11};
	for (i = 0; i < CLASS; i++)
		index[i] = i;

/* the above for loop, initalizes the index[] array. It is NOT a part of the sort code, so you've left off the outer loop of the sorting code.
*/
        for(i=0;i<CLASS;i++) {
	for (j = i + 1; j < CLASS; j++) {

/* use strcmp() when you have strings to be compared - not for numbers */
             if(gpa[index[i]].studentGPA > gpa[index[j]].studentGPA) {
               //if(strcmp(gpa[index[i]].studentGPA, gpa[index[j]].studentGPA) > 0) {
		temp = index[i];
		index[i] = index[j];
		index[j] = temp;
	     }
	}
      }

      for(i = 0; i < CLASS; i++)
	 printf("%s \n", gpa[index[i]].studentGPA);
}

More like that.

ok. Well now it compiles, but i get 9 (null)'s.
i think is because im using gpa[index[j]].studentGPA
should i use something another name? i thought it didnt matter

Changing the name of the array might confuse humans a bit, but the compiler just needs the address as a parameter. You can change the name in the parameter, and that's fine. But you can't change the struct member name, or the size of the member, etc.

If you want to do something like this:

StudFile gpa[CLASS] = {5.50, 2.22, 3.33, 4.44, 9.99, 6.66, 7.77, 8.88, 1.11};

You need to fill in all the other member values, for the struct, or specifically denote which member you're changing. Again, it's all a matter of being specific about which value, goes to which struct member.

If you want to assign just one member, use a for loop:

for(i=0;i<Somenumber;i++) {
  if(i==0) 
    arrayOfStruct[i].member = 5.50;
  
  //etc.
}

No need to go through the index, for this assignment. Just do
your sorting, later.

Edited 5 Years Ago by Adak: n/a

This article has been dead for over six months. Start a new discussion instead.