Hello,
Your chief problem causing linker errors is that, as Ian Collins
pointed out, your declaration of pcheck() in the file where you define
main() does not match the definition of pcheck() in the file where it
is defined.
Below I add some other tips:
On Apr 17, 4:50*pm, Joey Bork Dugan <jborkdu...@gmail.com> wrote:
> I'm a beginner C++ programmer and I'm having an issue with a Linker
> Error. *I keep getting the following:
>
> [Linker error] undefined reference to `pcheck(int, int)'
> ld returned 1 exit status
>
> I've been staring at it for HOURS and I can't figure it out! Help
> please?
>
> Below is my code:
Below you are declaring a whole bunch of variables as globals ... this
is generally a bad practice, it's better to declare them inside a
function (main(), in this case).
> int batch9[20][4]={0};
> long double volumes[20]={0};
Here, and in the rest of the program, you are using "magic
numbers" ... there is no indication of why you are multiplying
3.14*10*10*10, addding Vhats*.12 to Vhats below, etc. Consider using
const variables with evocative names.
The use of variables with the type 'long double' is unusual and
probably not necessary in your code, given that you are only using a
precision of three decimal places otherwise. Generally a simple
'double' is the best choice for numeric operations (an IEEE 8-byte
double has a precision of 1 part in 10^16, which will certainly more
than suffice for you). Be aware that in some compilers, Microsoft's
among them, 'long double' does not even have any more additional
precision than 'double'.
> double Vhats=(3.14*(10*10)*10),Vboots=(8*10*1
,Vcanes=(. 5*7*7*12);
> long double TVhats,TVboots,TVcanes,x;
> int set;
> bool fcheck, fits[20];
> bool filecheck();
> bool fitcheck(long double);
> bool pcheck(int,int);
As mentioned, the above declaration should be:
bool pcheck(int, int [20][4]);
>
> int main(){ * * * * * * * * * * //beginning program
>
> cout<<"Integrated Project Console"<<endl;
>
> fcheck=filecheck();
>
> if (fcheck==false){ * * * * * * * * * * * * * * //Tests to see if file
> was open
> * * *cout<<"File not opened!"<<endl<<endl; * * *//Returned iffile is
> not opened
> * * *system("pause");
> * * *return 0;
> * * *}//end if
> else {
> * * *cout<<"File opened successfully!"<<endl<<endl; //Returned if file
> is opened
> * * *}//end else
>
> Vhats=Vhats+(Vhats*.12);
> Vboots+=(Vboots*.12);
> Vcanes+=(Vcanes*.12);
Easier to multiply by 1.12, e.g.,
Vhats *= 1.12;
>
> ifstream infile;
> infile.open("Batch_09.txt");
The need for the function filecheck() isn't really clear to me. You
have to open the file here, anyway, so the small amount of code in
filecheck() might as well be here in main(). As it stands, your code
risks getting out of sync because you need to make sure to use the
same filename "Batch_09.txt" both in main() and in filecheck(). If
you had to change it in one place, there would be a risk of forgetting
to do so in the other. If filecheck() is needed, it would be best for
it to take a string parameter to specify the filename.
>
> for (int a=0;a<20;a++){
> * * for (int b=0;b<4;b++){
> * * * * infile>>batch9[a][b]; * * * * * * *//Creates 2D Matrix from
> the file
> * * * * }//end loop b
> * * }//end loop a
>
> cout<<fixed<<setprecision(2);
> cout<<setw(10)<<"Set #"<<setw(6)<<"Hats"<<setw(6)<<"Boots";
> cout<<setw(14)<<"Shillelaghs"<<endl;
>
> for (int c=0;c<20;c++){
> * * for (int d=0;d<4;d++){
> * * * * cout<<setw(6)<<batch9[c][d]<<" ";
> * * * * }//end loop d
> * * * * cout<<endl;
> * * }//end loop c
>
> for (set=0;set<20;set++){
> * * if (pcheck(set,batch9[20][4])==false){
Above, I think you intended to pass the entire 20x4 matrix into
pcheck():
if (pcheck(set, batch9) == false)) {
Also, explicit comparisons to a boolean constant are generally non-
idiomatic, although some folks will defend them in some cases. But
most people would write the above as:
if (! pcheck(set, batch9)) {
> * * * *volumes[set]=3000000;
> * * * *}//end if
> * * else {
> * * TVhats = batch9[set][1]*Vhats;
> * * TVboots = batch9[set][2]*Vboots;
> * * TVcanes = batch9[set][3]*Vcanes;
> * * volumes[set]=TVhats+TVboots+TVcanes;
> * * }//end else
>
> }//end for
>
> for (set=0;set<20;set++){
> * * x=volumes[set];
> * * if (fitcheck(x)==true){
> * * * *fits[set]=true;
> * * }
> * * else {
> * * * *fits[set]=false;
> * * }
The above code block is pretty redundant, you could condense it as:
for (set = 0; set < 20; set++) {
fits[set] = fitcheck(volumes[set]);
}
>
> }
>
> for (int a=0;a<20;a++){
> * * if (fits[a]==true){
> * * * * cout<<"Set "<<a+1<<" fits"<<endl;
> * * }
> * * else if (fits[a]==false){
> * * * * *cout<<"Set "<<a+1<<" does not fit"<<endl;
> * * }
Again, above it is not idiomatic to test for equality to a boolean
constant. And the "else if" is better as an "else", since there is no
possible value for fits[a] other than true or false:
for (int a = 0; a < 20; a++) {
if (fits[a])
cout << "Set " << a + 1 << " fits" << endl;
else
cout << "Set " << a + 1 << " does not fit" << endl;
}
>
> }
>
> * * cout<<endl;
> * * system("pause");
Be aware that any use of system() is a sign of platform-dependent
code, since the argument passed into system() is by definition
platform-dependent. This code would fail on most systems other than
Windows. This isn't necessarily bad in all cases; most likely you
have no intention of trying to do so, and sometimes platform-dependent
code is the best way to accomplish something; but you should know of
it.
> * * return 0;
>
> }//end main()
>
> //
> ================================PERCENTCHECK====== ============================
> bool pcheck(int set,int batch9[20][4]){
>
> int x=batch9[set][1];
> int y=batch9[set][2];
> int z=batch9[set][3];
>
> int items=x+y+z;
> int Pitems = items/10;
> if (x<Pitems||y<Pitems||z<Pitems){
> * *return false;
> * *}//end if
> else{
> * *return true;
> * *}//end else
Above, rather than having the if block, you can just return the
inverse of the value of what the if condition is testing:
return ! (x < Pitems || y < Pitems || z < Pitems);
although it's more legible to apply the ! sign through the || [recall
from basic boolean logic that !(a || b) is the same as (!a && !b)], to
better illustrate the actual requirement of the code:
return x >= Pitems && y >= Pitems && z >= Pitems;
>
> }//end percentcheck()
>
> //
> ================================FITCHECK========== ============================
>
> bool fitcheck(long double x){
> * * *long double container=(1320*(12*12*12));
Another magic number here!
>
> * * *if (x<=container){
> * * * * return true;
> * * * * }//end if
> * * *else {
> * * * * return false;
> * * * * }//end else}//end fitcheck()
Again, the above if/else can be rewritten in a much simpler format:
return x <= container;
Because this fitcheck() function, too, is very simple, it would
probably make your code more easily readable if you just wrote the
above in the place where fitcheck() is used. Above, I had rewritten
that part of main() as:
for (set = 0; set < 20; set++) {
fits[set] = fitcheck(volumes[set]);
}
so that code in main() would instead become
const long double container = (1320*(12*12*12));
for (set = 0; set < 20; set++) {
fits[set] = (volumes[set] <= container);
}
I hope that at least some of the suggestions above are useful for you.
Best regards,
- Kevin B. McCarty