【问题标题】:comparator not calling in qsort [Error: expected expression before comparator]比较器未调用 qsort [错误:比较器之前的预期表达式]
【发布时间】:2017-02-11 21:48:20
【问题描述】:

我正在尝试使用结构数组“学生”通过比较器调用 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 的比较器没有参数?当我尝试放入数组的第一个两个元素时,它也会出错。有什么想法吗?

【问题讨论】:

  • 而且我们不应该理清错误消息可能与哪些行有关?抱歉,我们不是调试服务。
  • 你在调用 qsort 之前声明了比较函数吗?
  • 抱歉错误出现在第4行@Olaf
  • 函数声明在一个包含@dromtrund的头文件中

标签: c arrays structure comparator qsort


【解决方案1】:

我建议一个接一个地解决,即从按 ID 排序开始,提供特定的“sortStudentById”-比较器函数,并从没有任何#ifdef 的代码开始(这些通常使调试和理解编译器错误更复杂)。

我想一个原因是您的比较函数在 qsort 中使用之前没有声明。

一旦你解决了这个问题,你肯定会在qsort的使用中遇到下一个问题。如果要对学生对象进行排序,则比较函数需要获取指向学生对象的指针(而 qsort 将作为一个整体反复交换学生对象,而不是指向它们的指针)。将指向成员的指针传递给 qsort(如 &amp;(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;
}

【讨论】:

  • 不幸的是,我无法删除 ifdef 语句,因为它们用于部分信用评级。该函数在头文件中声明为: int compareInts(const void * argu1, const void * argu2); int compareStrings(const void * argu1, const void * argu2);但是,我正在进行 qsort 调整,我会告诉你它是如何工作的!谢谢!
  • 我在排序函数之前移动了函数并修改了 qsort,但我遇到了另一个熟悉的错误。未定义的引用
  • 我修改了更多代码,现在 intereger 调用成功(我稍后会检查输出),但比较字符串不起作用,说我重新定义了参数 argu1。我应该能够修补并解决其余的问题
【解决方案2】:
// 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 包含 main

【讨论】:

  • 这样我在比较字符串函数时遇到了错误。从不兼容的指针类型等初始化。我正在尝试修复它们
  • 代码现在编译。制作我的 makefile 时遇到问题,但那是另一个话题
猜你喜欢
  • 2016-09-08
  • 2015-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 2013-12-29
相关资源
最近更新 更多