Reputation: 19
I'm writing a program that sorts a list of students by name and grade. I'm receiving the following errors when I attempt to compile:
ex11.c: In function 'compareByGrade': ex11.c:46: error: request for member 'grade' in something not a structure or union ex11.c:47: error: request for member 'grade' in something not a structure or union ex11.c: In function 'compareByName': ex11.c:56: error: request for member 'name' in something not a structure or union ex11.c:57: error: request for member 'name' in something not a structure or union
This is the header file:
#define CLASS_SIZE 10
struct student {
char *name;
int idnumber;
char grade;
};
This is the main file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ex11.h"
int main(void)
{
int c, i;
FILE *data;
struct student tmp, class[CLASS_SIZE];
void *nameArray[CLASS_SIZE], *gradeArray[CLASS_SIZE];
static int compareByGrade(const void *first, const void *second);
static int compareByName(const void *first, const void *second);
data = fopen("data", "r"); /* open data file */
/* Move data into struct */
for (i = 0; i < CLASS_SIZE; ++i) {
fscanf(data, "%s%d%c", tmp.name, tmp.idnumber, tmp.grade);
class[i].name = tmp.name;
class[i].idnumber = tmp.idnumber;
class[i].grade = tmp.grade;
}
fclose(data); /* close data file */
qsort(nameArray, CLASS_SIZE, sizeof(*nameArray), &compareByName);
qsort(gradeArray, CLASS_SIZE, sizeof(*gradeArray), &compareByGrade);
}
/* Function to sorty by grade */
static int compareByGrade(const void *first, const void *second)
{
const char *firstGrade = (*(const char **) first) -> grade; /* line 46 */
const char *secondGrade = (*(const char **) second) -> grade; /* line 47 */
return strcmp(firstGrade, secondGrade);
}
/* Function to sort by name */
static int compareByName(const void *first, const void *second)
{
const char *firstName = (*(const char **) first) -> name; /* line 56 */
const char *secondName = (*(const char **) second) -> name; /* line 57 */
return strcmp(firstName, secondName);
}
What am I doing wrong?
Upvotes: 0
Views: 4533
Reputation: 754590
There are many things that you're doing wrong. These include:
const struct student *
disguised as a const void *
.fopen()
or fscanf()
worked correctly.Here is working code based (loosely) on what you wrote.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CLASS_SIZE 10
struct student
{
char name[20];
int idnumber;
char grade;
};
static int compareByGrade(const void *first, const void *second);
static int compareByName(const void *first, const void *second);
static void print_students(const char *tag, const struct student *class, size_t size);
int main(void)
{
FILE *data;
if ((data = fopen("data", "r")) == 0)
{
fprintf(stderr, "failed to open file data\n");
exit(1);
}
struct student class[CLASS_SIZE];
for (int i = 0; i < CLASS_SIZE; ++i)
{
char name[20];
int idnumber;
char grade;
if (fscanf(data, "%19s %d %c", name, &idnumber, &grade) != 3)
{
fprintf(stderr, "failed to read student %d\n", i);
exit(1);
}
strcpy(class[i].name, name);
class[i].idnumber = idnumber;
class[i].grade = grade;
}
fclose(data);
qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByName);
print_students("By name", class, CLASS_SIZE);
qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByGrade);
print_students("By grade", class, CLASS_SIZE);
return 0;
}
static int compareByGrade(const void *p1, const void *p2)
{
const struct student *s1 = (const struct student *)p1;
const struct student *s2 = (const struct student *)p2;
if (s1->grade > s2->grade)
return +1;
else if (s1->grade < s2->grade)
return -1;
else
return strcmp(s1->name, s2->name);
}
static int compareByName(const void *p1, const void *p2)
{
const struct student *s1 = (const struct student *)p1;
const struct student *s2 = (const struct student *)p2;
return strcmp(s1->name, s2->name);
}
static void print_students(const char *tag, const struct student *class, size_t size)
{
printf("%s (%zu students):\n", tag, size);
for (size_t i = 0; i < size; i++)
printf("%2zu: %-20s %4d %c\n", i, class[i].name, class[i].idnumber, class[i].grade);
}
Note how the compareByName()
function determines first the grade rank and then compares by name.
student1 1234 A
student2 2345 B
junior03 3456 C
junior04 4356 D
sophomore12 5234 F
sophomore13 6345 B
senior19 3419 C
senior99 4399 D
fresher29 7456 C
fresher31 8356 A
By name (10 students):
0: fresher29 7456 C
1: fresher31 8356 A
2: junior03 3456 C
3: junior04 4356 D
4: senior19 3419 C
5: senior99 4399 D
6: sophomore12 5234 F
7: sophomore13 6345 B
8: student1 1234 A
9: student2 2345 B
By grade (10 students):
0: fresher31 8356 A
1: student1 1234 A
2: sophomore13 6345 B
3: student2 2345 B
4: fresher29 7456 C
5: junior03 3456 C
6: senior19 3419 C
7: junior04 4356 D
8: senior99 4399 D
9: sophomore12 5234 F
Upvotes: 0
Reputation: 2073
Agreed with xaxxon. The program processes the struct student class, nameArray and gradeArray are never initialized.
BTW,I suppose not to use a struct named class, it's confused with a C++'s keyword.
grade is char, but strcmp() need string to compare.
Suggestion: In main(),
qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByName);
qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByGrade);
and outside,
int compareByGrade(const void *first, const void *second)
{
const char firstGrade = ((struct student *)first) -> grade;
const char secondGrade = ((struct student *)second) -> grade;
return firstGrade<secondGrade?-1:(firstGrade==secondGrade?0:1);
}
/* Function to sort by name */
int compareByName(const void *first, const void *second)
{
const char *firstName = ((struct student *)first) -> name;
const char *secondName = ((struct student *)second) -> name;
return strcmp(firstName, secondName);
}
the expression of return value of compareByGrade() would act in the same way of compareByName()
Upvotes: 1
Reputation: 19771
const char *firstGrade = (*(const char **) first) -> grade;
const char *secondGrade = (*(const char **) second) -> grade;
'first' is cast to a double pointer to char, which is then dereferenced, so you have a char *. You then dereference that with the -> to a char, and char isn't a struct or union and doesn't have a member grade (because it can't).
Same problem lower for name.
That said, I don't see where you are populating nameArray or gradeArray, so even if you fix the compilation errors, you're going to have numerous runtime errors.
Upvotes: 0