我正在尝试对姓氏和公司名称进行排序。用户必须输入姓氏或公司名称(仅一个)。这是我现在的代码:
struct store {
unsigned long phone_num;
char *first_name;
char *last_name;
char *company_name;
char *email;
};
typedef struct store store;
void findContact(FILE *fp, long fileEnd)
{
/*variables*/
char fName [100];
char lName [100];
char cName [100];
char email [100];
int i, length;
int count = 1;
int size = sizeof(long);
int usize = sizeof(unsigned long);
unsigned long phone;
long nextPosition = 0;
long fNamePosition = 0;
long lNamePosition = 0;
long cNamePosition = 0;
long emailPosition = 0;
store *list;
list = malloc(sizeof(store));
/*Search for Contact position in file*/
fseek(fp, 0, SEEK_SET); /*Seeks to beginning of file*/
do {
i = count - 1;
fread(&phone, usize, 1, fp); /*reads phonenumber of contact*/
fread(&fNamePosition, size , 1, fp);
fread(&lNamePosition, size, 1, fp);
fread(&cNamePosition, size, 1, fp);
fread(&emailPosition, size, 1, fp);
fread(&nextPosition, size, 1, fp);
if(fNamePosition != 0) {
fseek(fp,fNamePosition,SEEK_SET);
if(lNamePosition == 0) {
length = cNamePosition - fNamePosition;
} else {
length = lNamePosition - fNamePosition;
}
fread(fName,sizeof(char),length,fp);
} else {
strcpy(fName," ");
}
if(lNamePosition != 0) {
fseek(fp,lNamePosition,SEEK_SET);
if (cNamePosition == 0) {
length = emailPosition - lNamePosition;
} else {
length = cNamePosition - lNamePosition;
}
fread(lName,sizeof(char), length,fp);
} else {
strcpy(lName," ");
}
if(cNamePosition != 0) {
fseek(fp,cNamePosition,SEEK_SET);
length = emailPosition-cNamePosition;
fread(cName,sizeof(char), length,fp);
} else {
strcpy(cName," ");
}
fseek(fp,emailPosition,SEEK_SET);
length = nextPosition - emailPosition;
fread(email,sizeof(char),length,fp);
list = realloc(list, count * sizeof(store));
list[i].phone_num = phone;
list[i].first_name = (char *) malloc(strlen(fName) + 1);
strcpy(list[i].first_name, fName);
list[i].last_name = (char *) malloc(strlen(lName) + 1);
strcpy(list[i].last_name, lName);
list[i].company_name = (char *) malloc(strlen(cName) + 1);
strcpy(list[i].company_name, cName);
list[i].email = (char *) malloc(strlen(email) + 1);
strcpy(list[i].email, email);
count++;
} while (ftell(fp) != fileEnd);
count--;
qsort(list, count, sizeof(store), compareStore);
/*Prints output*/
for(i=0;i<count;i++) {
printf("First Name: %s\n", list[i].first_name);
printf("Last Name: %s\n", list[i].last_name);
printf("Company Name: %s\n", list[i].company_name);
printf("Phone Number (enter only numbers): %ld\n", list[i].phone_num);
printf("Email: %s\n", list[i].email);
free(list[i].first_name);
free(list[i].last_name);
free(list[i].company_name);
free(list[i].email);
}
free(list);
return;
}
int compareStore (const void*a, const void *b)
{
const store *aa = a;
const store *bb = b;
return (strcmp(bb->last_name, aa->last_name));
}
这是我现在的输出。它应该将姓氏和公司名称视为相同的参数,然后对它们进行排序:
First Name: Andre
Last Name: D'Souza
Company Name:
Phone Number (enter only numbers): 6474000964
Email: adsouz03@mail.com
First Name:
Last Name:
Company Name: University of Guelph
Phone Number (enter only numbers): 5192137299
Email: uog@mail.com
First Name: Raf
Last Name:
Company Name: Raffy Taffy
Phone Number (enter only numbers): 1234567
Email: raf@mail.com
答案 0 :(得分:2)
您的比较功能看起来不对。您将传递指向两个记录a和b的指针。这些是指向商店结构的指针,但出于某种原因,您将它们作为商店**进行投射,然后尝试将其取消引用为商店*。这具有将数据用作指针的效果,这肯定会导致分段错误。
我建议:
int compareStore (const void*a, const void *b)
{
const store *aa = a;
const store *bb = b;
return (strcmp(aa->last_name, bb->last_name));
}
请注意,strcmp
完全返回qsort
所期望的int类型。只需返回qsort
strcmp
返回的值{。}}。
要概括compareStore
以检查姓氏或公司名称,假设其中一个包含字符串,另一个是NullPtr或Null字符串,那么完整的解决方案是:
int compareStore (const void*a, const void *b)
{
const store *aa = a;
const store *bb = b;
// This MACRO retrieve ptr to last_name or company_name based
// on whether last_name is a NULL ptr or a null "" string.
// If last_name is either, use company_name insteadof last_name
#define getKey(x) ((((x)->last_name==NULL)||((x)->last_name[0]==0)) ? (x)->company_name : (x)->last_name)
// Use the Macro getKey to point to appropriate sort key for each record
const char* keyA = getKey(aa);
const char* keyB = getKey(bb);
return (strcmp(keyA, keyB));
}
在您对qsort
本身的调用中发现了另一个错误,您可以在其中传递列表的大小,但是您应该传递列表中每个记录的大小以进行排序:
qsort (list, count, sizeof(store), compareStore);
答案 1 :(得分:0)
不是一个完整的答案,因为这看起来像家庭作业,但是:如果您的compareStore()
需要 姓氏或公司名称,无论哪个设置后,它应该包含一个条件。
在您的情况下,您需要一种方法来判断是否设置了last_name
或company_name
。您可以将未使用的指针设置为NULL
并测试if (a->last_name)
。您还可以添加enum
字段。
如果您可以更改struct
的定义,则实际上不需要两个char *
字段,这些字段将以相同的方式使用,一次只能使用一个。你可以有一个字段,解释不同。
最后,(抱歉无端的批评。)你通常不应该像使用void*
参数那样禁止静态类型检查。它可以阻止你在脚下射击自己。但是,在这种情况下,函数是qsort()
的输入,因此是罕见的不可避免的例外之一。