我正在尝试用我的比较器调用qsort,使用一系列结构'学生' 它具有以下属性:
typedef struct
{
int ID; // 4 bytes = 164 [+ int]
char firstname[NAME_LENGTH]; // 1 bytes * length (80) = 160 [2 * NAME_LENGTH]
char lastname[NAME_LENGTH]; // 1 bytes * length (80)
} Student;
我的代码试图从函数中调用qsort 3次:按ID排序,然后是名字,然后是姓氏。主要功能涉及调用其他函数进行读写。在一个中找到错误应该让我能够将它应用到另一个函数,对吧?但是涉及排序的功能是:
#ifdef TEST_SORTID
void StudentSortbyID(Student * stu, int numelem)
{
qsort(&(stu-> ID), numelem, sizeof(stu), compareInts);
}
#endif
#ifdef TEST_SORTFIRSTNAME
void StudentSortbyFirstName(Student * stu, int numelem)
{
qsort(&(stu-> firstname), numelem, sizeof(stu), compareStrings);
}
#endif
#ifdef TEST_SORTLASTNAME
void StudentSortbyLastName(Student * stu, int numelem)
{
qsort(&(stu-> lastname), numelem, sizeof(stu), compareStrings);
}
#endif
#ifdef TEST_COMPAREINTS
int compareInts(const void * argu1, const void * argu2)
{
const int * iptr1 = (const int *) argu1; //convert void to integer pointer
const int * iptr2 = (const int *) argu2;
int ival1 = * iptr1; //convert pointer to value
int ival2 = * iptr2;
if(ival1 < ival2) { return -1; } //return -1 if first value is less
if(ival1 > ival2) { return 1; } //return 1 if previous value is greater
if(ival1 == ival2) { return 0; } //return 0 if the adjacent values are equal
}
#endif
#ifdef TEST_COMPARESTRINGS
int compareStrings(const void * argu1, const void * argu1)
{
//String is an array of characters (string = char*) -> pointing to string
const char * const * sptr1 = (const char * *) argu1; //converting empty pointers to strings which point to characters [**]
const char * const * sptr2 = (const char * *) argu2;
const char * string1 = * sptr1; // a string is a character pointer
const char * string2 = * sptr2;
return strcmp(string1,string2);
}
#endif
运行gcc时遇到的错误是:
student.c:120: error: too few arguments to function ‘compareInts’
我认为qsort的比较对手没有参与?当我尝试放入数组的前两个元素时,它也会出错。有什么想法吗?
答案 0 :(得分:0)
我建议先解决一件事,即从ID开始,提供一个特定的“sortStudentById” - 比较器函数,并从没有任何#ifdef
的代码开始(这些通常会调试和理解编译器错误更复杂)。
我想有一个原因是你的比较函数在qsort
使用之前没有被声明。
一旦解决了这个问题,您肯定会遇到qsort
使用中的下一个问题。如果要对学生对象进行排序,则比较函数需要指向学生对象(而qsort将重复交换学生对象作为整体,而不是指向它们的指针)。将指向成员的指针传递给qsort(如&(stu-firstname)
)将让qsort以一种肯定无意的方式交换东西。
尝试以下代码作为起点,并根据需要进行调整:
int compareStudentsByID(const void* s1, const void *s2) {
return ((Student *)s1)->ID - ((Student*)s2)->ID;
}
void sortByID(Student *s) {
qsort(s,100,sizeof(Student),compareStudentsByID);
}
int main() {
Student students[100];
for (int i=0; i<100; i++) {
students[i].ID = rand()%1000;
}
sortByID (students);
return 0;
}
答案 1 :(得分:0)
// Do not remove #ifdef ... #endif before and after each function.
//
// They are used to test different functions in your program and give
// partial credits, in case your program does not work completely.
#include "student.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void StudentPrint(Student * stu, int num)
{
printf("There are %d students\n", num);
for (int ind = 0; ind < num; ind ++)
{
printf("ID = %d, First Name = %s, Last Name = %s\n",
stu[ind].ID, stu[ind].firstname, stu[ind].lastname);
}
}
#ifdef TEST_READ
// return false if anything is wrong
// return true if reading the file successfully and the data is save in
// the allocated memory
// input: filename, the name of the input file
// output: address of the allocated memory
// output: number of students
bool StudentRead(char * filename, Student * * stu, int * numelem)
{
int id;
char first[NAME_LENGTH];
char last[NAME_LENGTH];
// open the file to read
FILE * inputPtr = fopen(filename, "r");
// if fopen fails, return false
// do not use fclose since fopen already fails
if (inputPtr == NULL)
{
fprintf(stderr, "File Opening failed; Evaluate read function\n");
return false;
}
// count the number of lines to determine the number of students
while( 0 != fscanf(inputPtr, "\n")) { numelem++; }
// return to the beginning of the file
// you can use fseek or
// fclose followed by fopen
// You need to check whether fseek or fopen fails
// Do not use rewind because it does not report whether it fails
fclose(inputPtr);
inputPtr = fopen(filename, "r"); // reading starts from 0
// allocate memory for the data
stu = malloc(((sizeof(*(stu))) * (*numelem)));
// check whether memory allocation fails
if (stu == NULL)
{
fprintf(stderr, "Memory allocation failed; evaluate malloc\n");
return false;
}
// read the data from the file and store the data in the allocated memory
for (int count = 0; count < *numelem; count++)
{
fscanf(inputPtr, "%i %s %s\n", &id, &first[NAME_LENGTH], &last[NAME_LENGTH]);
stu[count] -> ID = id;
stu[count] -> firstname[NAME_LENGTH] = first[NAME_LENGTH];
stu[count] -> lastname[NAME_LENGTH] = last[NAME_LENGTH];
}
if (stu[0] == NULL)
{
fprintf(stderr, "Inputting file values to variable failed; evluate read function\n");
return false;
}
// close the file
fclose(inputPtr);
return true;
}
#endif
#ifdef TEST_WRITE
// return false if anything is wrong
// return true if writing the file successfully
// input: filename, the name of the output file
// input: address of the student array
// input: number of students
bool StudentWrite(char * filename, Student * stu, int numelem)
{
// open the file to write
FILE * outputFile = fopen(filename, "w");
// if fopen fails, return false
// do not use fclose since fopen already fails
if (outputFile == NULL)
{
fprintf(stderr, "Opening file failed; evaluate Write function\n");
return false;
}
// write the students to the output file
for (int count = 0; count < numelem; count++)
{
fprintf(outputFile, "%i %s %s\n", (stu[count]).ID, (stu[count]).firstname, (stu[count]).lastname);
}
return true;
}
#endif
#ifdef TEST_SORTID
void StudentSortbyID(Student * stu, int numelem)
{
qsort(stu, numelem, sizeof(Student), compareInts);
}
#endif
#ifdef TEST_SORTFIRSTNAME
void StudentSortbyFirstName(Student * stu, int numelem)
{
qsort(stu -> firstname, numelem, sizeof(stu), compareStrings);
}
#endif
#ifdef TEST_SORTLASTNAME
void StudentSortbyLastName(Student * stu, int numelem)
{
qsort(stu -> lastname, numelem, sizeof(stu), compareStrings);
}
#endif
int compareInts(const void * argu1, const void * argu2)
{
const Student * iptr1 = (const Student *) argu1; //convert void to integer pointer
const Student * iptr2 = (const Student *) argu2;
return iptr1 ->ID - iptr2 -> ID;
}
int compareStrings(const void * argu1, const void * argu2)
{
//String is an array of characters (string = char*) -> pointing to string
const Student * sptr1 = (const char *) argu1; //converting empty pointers to strings which point to characters [**]
const Student * sptr2 = (const char *) argu2;
const char string1 = sptr1 -> firstname; // a string is a character pointer
const char string2 = sptr2 -> firstname;
return strcmp(string1,string2);
}
这是这些功能的完整代码。另一个.c包含主