Join 136,558 C++ Programmers for FREE! Get instant access to thousands of C++ experts, tutorials, code snippets, and more! There are 1,927 people online right now. Registration is fast and FREE... Join Now!
I need some help with a computer programming problem in C++. Here's the problem:
I am doing an assignment that requires me to create a class called statpac that has functions for finding the mean, median, mode, mid-range, range, and standard deviation of numbers in an array. The professor stated that there cannot be any includes for iostream and no I/O in the class. The professor also said that he will be grading the assignment using MFC. I am not very familiar with MFC. I have compiled the source code and built the library with the .cpp and .h files, with MFC support added. I am using Microsoft Visual C++ 6.0, so in the dialog for creating the static library, I checked the option for MFC support. The problem I'm having is that I don't understand how I can test the library and output the results. To clarify the problem, I have included the instructions for the assignment as a pdf attachment. I'm basically having trouble executing code to the output in the testing code. That is, once I execute the testing code, no output is shown in the console screen. I have included the code for the .cpp and .h files here, as well as the code for testing the library created from the previous two files:
statpac.h, the header file for the library:
CODE
//STATPAC #ifndef STATPAC_H #define STATPAC_H
class StatPac{ int NumOfElements; float *statValue; public: int addValue(float); void clearAll(); int removeValue(float); float mean(); float median(); float mode(); float midRange(); float range(); float std(); };
#endif //STATPAC_H
statpac.cpp, the source code file for the library:
CODE
// STATPAC #include "statpac.H" #include <math.h> int StatPac:: addValue(float a){ float *newArray=new float[NumOfElements+1]; for (int i=0; i<NumOfElements; i++) newArray[i]=statValue[i];//copying old array to new if (NumOfElements!=0) delete []statValue;//deleting old storage statValue=newArray;//pointing to new array statValue[NumOfElements]=a; NumOfElements++; return NumOfElements; } void StatPac:: clearAll(){ delete []statValue; NumOfElements=0; } int StatPac:: removeValue(float a){ float *newArray=new float[NumOfElements]; int changedNumOfElements=0; //finding the value in the array: for (int i=0;i<NumOfElements; i++){ if (statValue[i]!=a){ newArray[i]=statValue[i];//copying to new array all the other values besides the value of argument changedNumOfElements++; } } delete []statValue;//releasing storage float *copyArray=new float[changedNumOfElements]; for (i=0; i<changedNumOfElements; i++) copyArray[i]=newArray[i]; delete []newArray;//releasing storage statValue=copyArray;//pointing to changed array NumOfElements=changedNumOfElements; return NumOfElements; } float StatPac:: mean(){ float result, sum=0; for (int i=0; i<NumOfElements; i++) sum+=statValue[i]; result=sum/NumOfElements; return result; } float StatPac:: median(){ //sorting the array in ascending order: float temp; for (int i=0; i<NumOfElements; i++){ for (int j=0; j<(NumOfElements-1); j++){ if (statValue[j]>statValue[j+1]){ temp=statValue[j]; statValue[j]=statValue[j+1]; statValue[j+1]=temp;} } } float result; if (NumOfElements%2!=0) result=statValue[(NumOfElements+1)/2]; if (NumOfElements%2==0) result=(statValue[NumOfElements/2] + statValue[(NumOfElements/2)+1])/2; return result; } float StatPac:: mode(){ int *freqs=new int[NumOfElements], index=0, freqcounter=1, big, holder=0; for (int i=0; i<NumOfElements; i++){ //finding the frequency of each of the elements for (int j=i+1; j<NumOfElements; j++){ if (statValue[i]==statValue[j]) freqcounter++;} freqs[index]=freqcounter; index++; freqcounter=1;//resetting the frequency counter to 1 } big=freqs[0]; for (i=1; i<NumOfElements; i++){ //comparing the frequencies of each of the elements if (big<freqs[i]){ big=freqs[i]; holder=i;} } float result=statValue[holder]; delete []freqs; return result; } float StatPac:: midRange(){ //sorting the array in ascending order: float temp; for (int i=0; i<NumOfElements; i++){ for (int j=0; j<(NumOfElements-1); j++){ if (statValue[j]>statValue[j+1]){ temp=statValue[j]; statValue[j]=statValue[j+1]; statValue[j+1]=temp;} } } float result=(statValue[NumOfElements-1] + statValue[0])/2; return result; } float StatPac:: range(){ //sorting the array in ascending order: float temp; for (int i=0; i<NumOfElements; i++){ for (int j=0; j<(NumOfElements-1); j++){ if (statValue[j]>statValue[j+1]){ temp=statValue[j]; statValue[j]=statValue[j+1]; statValue[j+1]=temp;} } } float result=statValue[NumOfElements-1] - statValue[0]; return result; } float StatPac:: std(){ float *deviations=new float[NumOfElements], *squares=new float[NumOfElements]; float sum=0, average; for (int i=0; i<NumOfElements; i++){ deviations[i]=mean()-statValue[i];//Finding the deviation of each array number from the mean squares[i]=deviations[i]*deviations[i];//Squaring each of the deviations sum+=squares[i];}//First step toward finding the average of the squares average=sum/NumOfElements;//Finding the average of squares float result=sqrtf(average); //Finding the square root of the average delete []deviations; delete []squares; return result; }
the code for testing the library:
CODE
#include "/home/~/Myprograms/statpac project/statpac.H" //the directory of the library header file (I'm using Ubuntu Linux and running Visual C++ under Wine) #include <iostream.h>
Issue Number 1: First off, you've got some scope errors that you really should fix.
Namely
CODE
int StatPac:: removeValue(float a){ float *newArray=new float[NumOfElements]; int changedNumOfElements=0; //finding the value in the array: for (int i=0;i<NumOfElements; i++){ if (statValue[i]!=a){ newArray[i]=statValue[i];//copying to new array all the other values besides the value of argument changedNumOfElements++; } } delete []statValue;//releasing storage float *copyArray=new float[changedNumOfElements]; for (i=0; i<changedNumOfElements; i++) copyArray[i]=newArray[i]; ...
In the above code, you declared the variable i in the first for loop. Following the standard C++ scope rules (which Visual C++ 6 doesn't actually follow...), this variable can only be used inside the for loop that it was declared in.
So, you can either declare i outside the for loop, or declare it again in the second for loop (I don't know how VC++ 6 will react to this method though).
You did the same thing in float StatPac:: mode()
Issue Number 2: You also didn't correctly declare main().
void main(){
the correct forms are
int main(){ or int main(int argc, char *argv[])
You most likely want to use int main(), since you arn't dealing with command prompt parameters. Once that is done, you have to return a value from main. Generally, a return 0; will work.
Issue Number 3: You are accessing functions from the namespace std, without specifying it.
The easy way to fix this, is to just add
using namespace std;
at the top of file that has main(), but below the includes.
Issue Number 4: You don't have a constructor for the class StatPac, so when ever you call a function, you are dealing with uninitilized data. For example, in addValue, you access NumOfElements. Since NumOfElements was not initilized, it could be pretty much anything.
Issue Number 1: First off, you've got some scope errors that you really should fix.
Namely
CODE
int StatPac:: removeValue(float a){ float *newArray=new float[NumOfElements]; int changedNumOfElements=0; //finding the value in the array: for (int i=0;i<NumOfElements; i++){ if (statValue[i]!=a){ newArray[i]=statValue[i];//copying to new array all the other values besides the value of argument changedNumOfElements++; } } delete []statValue;//releasing storage float *copyArray=new float[changedNumOfElements]; for (i=0; i<changedNumOfElements; i++) copyArray[i]=newArray[i]; ...
In the above code, you declared the variable i in the first for loop. Following the standard C++ scope rules (which Visual C++ 6 doesn't actually follow...), this variable can only be used inside the for loop that it was declared in.
So, you can either declare i outside the for loop, or declare it again in the second for loop (I don't know how VC++ 6 will react to this method though).
You did the same thing in float StatPac:: mode()
Issue Number 2: You also didn't correctly declare main().
void main(){
the correct forms are
int main(){ or int main(int argc, char *argv[])
You most likely want to use int main(), since you arn't dealing with command prompt parameters. Once that is done, you have to return a value from main. Generally, a return 0; will work.
Issue Number 3: You are accessing functions from the namespace std, without specifying it.
The easy way to fix this, is to just add
using namespace std;
at the top of file that has main(), but below the includes.
Issue Number 4: You don't have a constructor for the class StatPac, so when ever you call a function, you are dealing with uninitilized data. For example, in addValue, you access NumOfElements. Since NumOfElements was not initilized, it could be pretty much anything.
Thank you for your prompt reply!
I went through each of your suggestions.
For the first one, when I redeclared i in the second for loops for StatPac::removeValue(float) and for StatPac::mode(), I got the following error: C2374: 'i' : redefinition; multiple initialization. I decided to just declare j instead of i for the second for loop.
I implemented your second suggestion without problem.
When I carried out your third suggestion, I was given this error upon compilation: error C2871: 'std' : does not exist or is not a namespace. When I removed the "using namespace std;", I got no errors.
In response to your fourth suggestion, I added a constructor for the class StatPac, initializing NumOfElements to 0:
CODE
StatPac::StatPac() {NumOfElements=0;};
Now, when I execute the testing program, I have the result of the mean on the screen!!!
Thank you for your help!
This post has been edited by bcasanov: 6 May, 2008 - 11:14 AM
I tried your suggestion, but I get a warning: LINK : warning LNK4098: defaultlib "MSVCRTD" conflicts with use of other libs; use /NODEFAULTLIB:library. I decided then to just keep the code as it was, and then I tested the library using the following modified code:
int StatPac:: removeValue(float a){ float *newArray=new float[NumOfElements]; int changedNumOfElements=0; //finding the value in the array: for (int i=0;i<NumOfElements; i++){ if (statValue[i]!=a){ newArray[i]=statValue[i];//copying to new array all the other values besides the value of argument changedNumOfElements++; } } delete []statValue;//releasing storage float *copyArray=new float[changedNumOfElements]; for (i=0; i<changedNumOfElements; i++) copyArray[i]=newArray[i]; delete []newArray;//releasing storage statValue=copyArray;//pointing to changed array NumOfElements=changedNumOfElements; return NumOfElements; }
float *newArray=new float[NumOfElements]; int changedNumOfElements=0;
The above is correct
CODE
for (int i=0;i<NumOfElements; i++){ if (statValue[i]!=a){ newArray[i]=statValue[i];//copying to new array all the other values besides the value of argument changedNumOfElements++; } }
Loop 1: i = 0. You check to see if statValue[0] != 2, which is ture (1 != 2). So, you copy the old value into the new array. newArray[0] = statValue[0];
Loop 2: i = 1 You check to see if statValue[1] != 2, which is false (2 != 2) So now you don't copy over the old data
Loop 3: i = 2 You check to see if statValue[2] != 2, which is true (3 != 2) So, you copy the old value into the new array newArray[2] = statValue[2];
Look at Loop 1, and Loop 3. You did copy over the old data to the new array, but you didn't do anything to newArray[1], which means it's full of garbage.
So, you need to keep track of your location in newArray, as well as you location in statValue. You are already doing this, so you just need to change
Thank you so much, Cerolobo, for walking through the execution of the code and pointing out the problem!! I am very grateful to you in helping me see what I did wrong.
I have now tested the program with the solution you have suggested, and it works, but there is one problem in the output:
The median in the last test has a strange output. I tested the program with any two numbers in the array, and again, the strange output happens. It seems that something is wrong with the median() function when only 2 numbers are in the array. I'm very sorry to have to burden you with another problem, but I do want to say that I'm very thankful for your help!
This post has been edited by bcasanov: 6 May, 2008 - 04:22 PM
if (NumOfElements%2!=0) result=statValue[(NumOfElements+1)/2]; if (NumOfElements%2==0) result=(statValue[NumOfElements/2] + statValue[(NumOfElements/2)+1])/2;
If you have two elements in the array, then NumOfElements == 2.
So, lets calculate NumOfElements % 2
2 / 2 = 1 2 - 2 * 1 = 0 <- Result of 2 % 2
So, we have
CODE
if (0 != 0) result=statValue[(NumOfElements+1)/2]; if (0 == 0) result=(statValue[NumOfElements/2] + statValue[(NumOfElements/2)+1])/2;
Thus, the second if statement is executed.
So, lets see what index you are actually trying to access
Thank you so much Cerolobo for pointing me in the right direction! I have added a new if statement:
CODE
if (NumOfElements==2) result=(statValue[0]+statValue[1])/2;
This additional if statement is just for the case of the array having only 2 numbers. In case the array has any other even number, the other if statement
CODE
if (NumOfElements%2==0) result=(statValue[NumOfElements/2] + statValue[(NumOfElements/2)+1])/2;
would work. The output is now correct, as expected. I am deeply indebted to you for your helpful advice and kindness!
Regards,
bcasanov
This post has been edited by bcasanov: 6 May, 2008 - 04:55 PM
That's won't fix your issues... It will only fix the issue, if NumOfElements==2.
You should actually look at the math, and work it out.
Take 10, for example.
CODE
if (NumOfElements%2!=0) result=statValue[(NumOfElements+1)/2]; if (NumOfElements%2==0) result=(statValue[NumOfElements/2] + statValue[(NumOfElements/2)+1])/2;
I realize now my mistake! I haven't been taking into account the fact that the array index number is 1 less than the actual number of elements! So, now I have modified the code like this:
CODE
if (NumOfElements%2!=0) result=statValue[((NumOfElements+1)/2)-1]; if (NumOfElements%2==0) result=(statValue[(NumOfElements/2)-1] + statValue[NumOfElements/2])/2;
I don't need to add the other if statement, as the if statement dealing with even NumOfElements deals with 2 numbers in the array just fine, as I have tested. Thank you so much for making me really think about it and not come up with a quick-fix solution that doesn't really work!