g++ -Wall -o "3bV2" "3bV2.cpp" (in directory: /home/dylan/Desktop/3b/Done)
/tmp/ccA8cFDY.o: In function `main':
3bV2.cpp:(.text+0x9ca): undefined reference to `struct_cmp_by_product(void const*, void const*)'
collect2: error: ld returned 1 exit status
Compilation failed.
编译时出现此错误。注意:它工作正常,直到我将我的功能外部化。
的main.cpp
#include <stdio.h>
#include <string.h> //reqd for strncat
#include <stdlib.h> // reqd for exit()
#include "./TAXRATES.h"
#include "./EmployeeRecord.h"
#define HEADERLINE1 " Employee's Pay RegHours Gross Fed SSI Net\n"
#define HEADERLINE2 " Name Rate OvtHours Worked State Defr\n"
#define HEADERLINE3 " ******************* ***** ******** ******* ****** ****** ******\n"
#define REPLNEFORMT1 " %-22s%6.2f%12.2f%10.2f%8.2f%8.2f%10.2f\n"//Main Header Line 1 (Thank you Dixon)
#define REPLNEFORMT2 " %40.2f%18.2f%8.2f\n\n"//Main Header Line 2 (Thank you Dixon)
#define REPLNEFORMT3 " %-21s%7.2f%12.2f%10.2f%8.2f%8.2f%10.2f\n"//Totals Line 1
#define MAX_SIZE 5
void EmptyFileError(void);//3.01
void InitializeAccumulators(float *totreg, float *totovt,float *totpayrate, float
*totgross, float *totfed, float *totstate, float *totssi, float
*totdefr, float *totnet); //3.02
void PrintReportHeadings(FILE * reportfile); //3.03
void NumberOfEmployees(int *NumEmployees); //3.04
void InputEmployeeData(char Ln[],char Fn[], float *Hours,float *Payrate, float
*defr, float *ovt); // 3.05
float CalculateGross(float Hours,float Payrate);//3.06
void computeTaxes(float g,float d,float * fed,float *state,float *ssi); //3.07
void PrintUserData(float p,float Hours,float g,float fed,float ssi,float n,char str1[30],float ovt,
float state,float d, FILE *reportfile);//3.09
void AddDetailToAccumulators(float *totpayrate, float p, float Hours, float *totreg,
float g, float *totgross, float fed, float *totfed, float ssi,
float *totssi, float n, float *totnet,
float *totovt,float ovt, float state, float *totstate, float
defr, float *totdefr);//3.10
void CalcAverage(float totpayrate, float *avgtotpayrate,float totreg, float
*avgtotreg,float totgross, float *avgtotgross, float *avgtotfed, float totfed,
float *avgtotssi, float totssi, float *avgtotnet, float totnet,
float *avgtotovt, float totovt, float *avgtotstate, float totstate,
float *avgtotdefr, float totdefr);//3.11
void PrintSummaryReport(float totpayrate, float totreg, float totgross,float totfed,
float totssi, float totnet, float totovt,float totstate,float
totdefr,float avgtotpayrate,float avgtotreg,float avgtotgross,float
avgtotfed, float avgtotssi,float avgtotnet,float avgtotovt,float
avgtotstate,float avgtotdefr, FILE *reportfile);//3.12
void CalculateOT(float *Hours, float *ovt);//*3..11
void computeTaxes(float g,float d,float * fed,float *state,float *ssi); //3.07
float cFed(float g,float d); // 3.8.1
float cState(float ft); // 3.8.2
float cSSI(float g,float d); // 3.8.3
extern int struct_cmp_by_product(const void *a, const void *b);
void computeTaxes(float g,float d,float * ft,float *st,float *ssit)
{ // 3.5
*ft = cFed(g,d); // vs ft = cFed(g,d)
*st = cState(*ft); // call 3.5.2
*ssit = cSSI(g,d); // call 3.5.3
}
float cFed(float g,float d) // 3.5.1
{
return (g-d) * FEDTAXRATE;
}
float cState(float ft) // 3.5.2
{
return ft * STATETAXRATE;
}
float cSSI(float g,float d) // 3.5.3
{
return (g-d) * SSITAXRATE;
}
int main(void)
{
EmployeeRecord MyAssociate[MAX_SIZE];
float totpayrate, totreg, totovt, totgross, totfed, totstate, totssi,
totdefr,totnet,avgtotpayrate,avgtotreg, avgtotgross,avgtotfed,
avgtotssi, avgtotnet, avgtotovt, avgtotstate, avgtotdefr,
ovt;
// step 1: declare a report "file" variable
FILE * reportfile;
reportfile = fopen("./report.txt","wt");
// step 2: open the "file" for "write-text" access
if (reportfile == NULL)
{
EmptyFileError();
}
InitializeAccumulators(&totpayrate,&totreg,&totovt,&totgross,&totfed,&totstate,
&totssi,&totdefr,&totnet);
PrintReportHeadings(reportfile);
for (int EmpCounter = 0; EmpCounter < MAX_SIZE; EmpCounter++)
{
InputEmployeeData(MyAssociate[EmpCounter].Lastname,MyAssociate[EmpCounter].Firstname,&MyAssociate[EmpCounter].Hours,&MyAssociate[EmpCounter].Payrate,&MyAssociate[EmpCounter].Defr,&ovt);// call 3.3
strcpy(MyAssociate[EmpCounter].FullName, MyAssociate[EmpCounter].Lastname);
strcat(MyAssociate[EmpCounter].FullName, ", ");
strcat(MyAssociate[EmpCounter].FullName, MyAssociate[EmpCounter].Firstname);
CalculateOT(&MyAssociate[EmpCounter].Hours, &ovt);
MyAssociate[EmpCounter].Gross = CalculateGross(MyAssociate[EmpCounter].Hours,MyAssociate[EmpCounter].Payrate); // call 3.4
computeTaxes(MyAssociate[EmpCounter].Gross,MyAssociate[EmpCounter].Defr,&MyAssociate[EmpCounter].FedTax,&MyAssociate[EmpCounter].StateTax,&MyAssociate[EmpCounter].SsiTax); // call 3.5
MyAssociate[EmpCounter].NetPay = MyAssociate[EmpCounter].Gross-MyAssociate[EmpCounter].FedTax-MyAssociate[EmpCounter].StateTax-MyAssociate[EmpCounter].SsiTax-MyAssociate[EmpCounter].Defr;
PrintUserData(MyAssociate[EmpCounter].Payrate,MyAssociate[EmpCounter].Hours,MyAssociate[EmpCounter].Gross,
MyAssociate[EmpCounter].FedTax,MyAssociate[EmpCounter].SsiTax,MyAssociate[EmpCounter].NetPay,MyAssociate[EmpCounter].FullName,ovt,
MyAssociate[EmpCounter].StateTax,MyAssociate[EmpCounter].Defr,reportfile);
AddDetailToAccumulators(&totpayrate, MyAssociate[EmpCounter].Payrate, MyAssociate[EmpCounter].Hours, &totreg,
MyAssociate[EmpCounter].Gross, &totgross, MyAssociate[EmpCounter].FedTax, &totfed, MyAssociate[EmpCounter].SsiTax, &totssi, MyAssociate[EmpCounter].NetPay, &totnet,
&totovt, ovt, MyAssociate[EmpCounter].StateTax, &totstate, MyAssociate[EmpCounter].Defr, &totdefr);
while(getchar() != '\n'); // flush(stdin)
}
CalcAverage(totpayrate, &avgtotpayrate,totreg,&avgtotreg, totgross,
&avgtotgross, &avgtotfed, totfed, &avgtotssi, totssi,&avgtotnet, totnet,
&avgtotovt, totovt, &avgtotstate, totstate,&avgtotdefr, totdefr);
qsort(MyAssociate, MAX_SIZE, sizeof(struct EmployeeRecord), struct_cmp_by_product);//sort
fclose(reportfile); // step 4: close the report file
getchar();
while (getchar() != '\n');
return 0;
}
void EmptyFileError(void) //3.01
{
printf(" Report file open failed ...\n");
printf(" Press key to exit ...\n");
while (getchar() != '\n'); // same as fflush(stdin)
exit(-10); // reqs <stdlib.h>
}
void InitializeAccumulators(float *totpayrate, float *totreg,float *totovt,float
*totgross,float *totfed,float *totstate,
float *totssi, float *totdefr, float *totnet) //3.02
{
*totpayrate = 0;
*totreg = 0;
*totovt = 0;
*totgross = 0;
*totfed = 0;
*totstate = 0;
*totssi = 0;
*totdefr = 0;
*totnet = 0;
}
void PrintReportHeadings(FILE * reportfile)//3.03
{
fprintf(stdout,HEADERLINE1);
fprintf(stdout,HEADERLINE2);
fprintf(stdout,HEADERLINE3);
fprintf(reportfile,HEADERLINE1);
fprintf(reportfile,HEADERLINE2);
fprintf(reportfile,HEADERLINE3);
}
void InputEmployeeData(char Ln[],char Fn[],
float Hours[],float *Payrate, float *defr, float *ovt)//3.05
{
printf(" Enter the name ==> ");
scanf("%s%s",Fn,Ln);
printf(" Enter the hours and payrate ==> ");
scanf("%f%f",Hours,Payrate);
printf(" Enter the deferred earning amount ==> ");
scanf("%f",defr);
}
void CalculateOT(float *Hours, float *ovt)//3.06 FLOWCHART!!!!
{
if (*Hours > 40){
*ovt = *Hours - 40;
*Hours = *Hours - *ovt;
}
else
{
*ovt = 0.00;
}
}
float CalculateGross(float Hours,float Payrate)//3.7
{
if (Hours <= 40)
return Hours * Payrate;
else
return 40* Payrate + 1.5 * Payrate * (Hours-40);
}
void PrintUserData(float p,float h,float g,float fed,float ssi,float n,char str1[30],
float ovt, float state,float d,FILE * reportfile)//3.09
{
fprintf(stdout,REPLNEFORMT1,str1,p,h<=40?h:40,g,fed,ssi,n);
fprintf(stdout,REPLNEFORMT2,ovt,state,d);
fprintf(reportfile,REPLNEFORMT1,str1,p,h<=40?h:40,g,fed,ssi,n);
fprintf(reportfile,REPLNEFORMT2,ovt,state,d);
}
void AddDetailToAccumulators(float *totpayrate, float p, float h, float *totreg,
float g, float *totgross, float fed, float *totfed, float ssi,
float *totssi, float n, float *totnet, float *totovt,
float ovt, float state, float *totstate, float defr, float *totdefr)//3.10
{
*totpayrate = p + *totpayrate;
*totreg = h + *totreg;
*totgross = g + *totgross;
*totfed = fed + *totfed;
*totssi = ssi + *totssi;
*totnet = n + *totnet;
*totovt = ovt + *totovt;
*totstate = state + *totstate;
*totdefr = defr + *totdefr;
}
void CalcAverage(float totpayrate, float *avgtotpayrate, float totreg, float *avgtotreg, float totgross, float *avgtotgross, float *avgtotfed, float totfed, float *avgtotssi, float totssi,float *avgtotnet, float totnet,
float *avgtotovt, float totovt, float *avgtotstate, float totstate, float *avgtotdefr, float totdefr)//3.11
{
*avgtotpayrate = totpayrate / MAX_SIZE;
*avgtotreg = totreg / MAX_SIZE;
*avgtotgross = totgross / MAX_SIZE;
*avgtotfed = totfed / MAX_SIZE;
*avgtotssi = totssi / MAX_SIZE;
*avgtotnet = totnet / MAX_SIZE;
*avgtotovt = totovt / MAX_SIZE;
*avgtotstate = totstate / MAX_SIZE;
*avgtotdefr = totdefr / MAX_SIZE;
}
Qsort.cpp
#include <stdio.h>
#include "./EmployeeRecord.h"
#include <string.h>
#define REPLNEFORMT1 " %-22s%6.2f%12.2f%10.2f%8.2f%8.2f%10.2f\n"//Main Header Line 1 (Thank you Dixon)
#define REPLNEFORMT2 " %40.2f%18.2f%8.2f\n\n"//Main Header Line 2 (Thank you Dixon)
#define MAX_SIZE 5
int struct_cmp_by_product(const void *a, const void *b);
void print_struct_array_pre(EmployeeRecord MyAssociate[]);
void print_struct_array_post(EmployeeRecord MyAssociate[]);
void print_struct_array_pre(EmployeeRecord MyAssociate[])
{
int i;
printf(" ***********ARRAY BEFORE NOT BEEN SORTED YET***************\n");
for(i=0; i<MAX_SIZE; i++)
{
//printf("%s %s]\n", MyAssociate[i].Lastname, MyAssociate[i].Firstname);
fprintf(stdout,REPLNEFORMT1,MyAssociate[i].FullName,MyAssociate[i].Payrate,
MyAssociate[i].Hours<=40?MyAssociate[i].Hours:40,MyAssociate[i].Gross,MyAssociate[i].FedTax,
MyAssociate[i].SsiTax,MyAssociate[i].NetPay);
fprintf(stdout,REPLNEFORMT2,MyAssociate[i].OVT,MyAssociate[i].StateTax,MyAssociate[i].Defr);
}
}
int struct_cmp_by_product(const void *a, const void *b)
{
struct EmployeeRecord *ia = (struct EmployeeRecord *)a;
struct EmployeeRecord *ib = (struct EmployeeRecord *)b;
return strcmp(ia->FullName, ib->FullName);
/* strcmp functions works exactly as expected from
comparison function */
}
void print_struct_array_post(EmployeeRecord MyAssociate[])
{
int i;
printf(" ***********ARRAY HAS BEEN SORTED VIA QUICK-SORT***************\n");
for(i=0; i<MAX_SIZE; i++)
{
//printf("%s %s]\n", MyAssociate[i].Lastname, MyAssociate[i].Firstname);
fprintf(stdout,REPLNEFORMT1,MyAssociate[i].FullName,MyAssociate[i].Payrate,
MyAssociate[i].Hours<=40?MyAssociate[i].Hours:40,MyAssociate[i].Gross,MyAssociate[i].FedTax,
MyAssociate[i].SsiTax,MyAssociate[i].NetPay);
fprintf(stdout,REPLNEFORMT2,MyAssociate[i].OVT,MyAssociate[i].StateTax,MyAssociate[i].Defr);
}
}
答案 0 :(得分:0)
如果compare函数与调用qsort()的源文件位于不同的源文件中,则在调用qsort()的源文件中将compare函数声明为external。 qsort()在stdlib.h中声明为外部。所以没有问题。如果这是c ++,你也可以使用std :: sort()或std :: stable_sort(),但你已经将它标记为c?
所以在main.c中,添加以下行:
extern int struct_cmp_by_product(const void *a, const void *b);
答案 1 :(得分:0)
以下是您似乎正在做的事情的自包含示例。虽然它没有给我编译为vanilla c ++的visual studio上的任何编译器错误。
main.cpp中:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern int cmp_char(const void *a, const void *b);
int main(void)
{
char arr[13] = "cbacbacbacba";
qsort(arr, sizeof(arr) - 1, sizeof(char), cmp_char);
printf("arr = %s\n", arr);
getchar();
return 0;
}
other.cpp:
#include <stdio.h>
#include <string.h>
int cmp_char(const void *a, const void *b);
int cmp_char(const void *a, const void *b)
{
char *pa = (char*)a;
char *pb = (char*)b;
return *pa - *pb;
}
注意:您的示例已经在main.cpp中对另一个文件中的函数进行了extern引用,因此我不明白为什么您会收到错误。难道你在编译器命令行上需要两个c ++文件吗? (所以它知道编译并将两个文件链接在一起吗?)