Welcome to Dream.In.Code
Getting C++ Help is Easy!

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!




Programming help with testing a library

 
Reply to this topicStart new topic

Programming help with testing a library

bcasanov
6 May, 2008 - 10:16 AM
Post #1

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

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>

ostream& operator<<(ostream& os, StatPac& s) {
        os<<s.mean();
        return os;
}
void main(){
    
    StatPac a;
    a.addValue(1);
    a.addValue(2);
    a.addValue(3);
    a.addValue(4);
    a.addValue(5);

    cout<<a;
}


I would appreciate any help you could give me.

This post has been edited by bcasanov: 6 May, 2008 - 10:34 AM


Attached File(s)
Attached File  statPac.pdf ( 21.3k ) Number of downloads: 14
User is offlineProfile CardPM
+Quote Post

Cerolobo
RE: Programming Help With Testing A Library
6 May, 2008 - 10:41 AM
Post #2

D.I.C Regular
Group Icon

Joined: 5 Apr, 2008
Posts: 440



Thanked: 31 times
My Contributions
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.
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 11:12 AM
Post #3

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

QUOTE(Cerolobo @ 6 May, 2008 - 11:41 AM) *

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
User is offlineProfile CardPM
+Quote Post

Cerolobo
RE: Programming Help With Testing A Library
6 May, 2008 - 11:18 AM
Post #4

D.I.C Regular
Group Icon

Joined: 5 Apr, 2008
Posts: 440



Thanked: 31 times
My Contributions
Ah, sorry but I forgot to mention this

#include <iostream.h>

should be

#include <iostream>

If you change that, then you will have to add the line

using namespace std;

iostream.h is the old version of iostream, without the namespace, which isn't really supported anymore.
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 11:40 AM
Post #5

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

QUOTE(Cerolobo @ 6 May, 2008 - 12:18 PM) *

Ah, sorry but I forgot to mention this

#include <iostream.h>

should be

#include <iostream>

If you change that, then you will have to add the line

using namespace std;

iostream.h is the old version of iostream, without the namespace, which isn't really supported anymore.



Thank you, Cerolobo!
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 12:09 PM
Post #6

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

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:
CODE
#include "/home/~/Myprograms/statpac project/statpac.H"
#include <iostream.h>

ostream& operator<<(ostream& os, StatPac& s) {
        os<<s;
        return os;
}
int main(){
    
    StatPac a;
    a.addValue(1);
    a.addValue(2);
    a.addValue(3);
    a.addValue(4);
    a.addValue(5);
    a.addValue(5);
    a.addValue(6);
    a.addValue(6);
    a.addValue(3);
    
    
    cout<<"Mean: "<<a.mean()<<" Median: "<<a.median()<<" Mid-range: "<<a.midRange()<<" Mode: "<<a.mode()<<" Range: "<<a.range()
        <<" Standard Deviation: "<<a.std();
    cout<<endl;
    
    a.clearAll();
    a.addValue(1);
    a.addValue(2);
    a.addValue(3);

    cout<<"Mean: "<<a.mean()<<" Median: "<<a.median()<<" Mid-range: "<<a.midRange()<<" Mode: "<<a.mode()<<" Range: "<<a.range()
        <<" Standard Deviation: "<<a.std();
    cout<<endl;
    return 0;
}









and got the following output, which indicates that the functions do work:
QUOTE
Mean: 3.88889 Median: 5 Mid-range: 3.5 Mode: 3 Range: 5 Standard Deviation:
296
Mean: 2 Median: 3 Mid-range: 2 Mode: 1 Range: 2 Standard Deviation: 0.816497


However, when I add: a.removeValue() to both of the tests, like this:
CODE

    
    StatPac a;
    a.addValue(1);
    a.addValue(2);
    a.addValue(3);
    a.addValue(4);
    a.addValue(5);
    a.addValue(5);
    a.addValue(6);
    a.addValue(6);
    a.addValue(3);
    a.removeValue(1);
    
    
    cout<<"Mean: "<<a.mean()<<" Median: "<<a.median()<<" Mid-range: "<<a.midRange()<<" Mode: "<<a.mode()<<" Range: "<<a.range()
        <<" Standard Deviation: "<<a.std();
    cout<<endl;
    
    a.clearAll();
    a.addValue(1);
    a.addValue(2);
    a.addValue(3);
    a.removeValue(2);

    cout<<"Mean: "<<a.mean()<<" Median: "<<a.median()<<" Mid-range: "<<a.midRange()<<" Mode: "<<a.mode()<<" Range: "<<a.range()
        <<" Standard Deviation: "<<a.std();
    cout<<endl;
    return 0;
}


I get the following weird output, indicating that there is something wrong with the removeValue() function:
QUOTE
Mean: -5.39503e+007 Median: 5 Mid-range: -2.15801e+008 Mode: 5 Range: 4.31602e+0
08 Standard Deviation: 1.42739e+008
Mean: -2.15801e+008 Median: -2.11008e+037 Mid-range: -2.15801e+008 Mode: -4.3160
2e+008 Range: 4.31602e+008 Standard Deviation: 2.15801e+008


What do you think could be the problem with the removeValue() function such that it causes this weird result?

This post has been edited by bcasanov: 6 May, 2008 - 12:13 PM
User is offlineProfile CardPM
+Quote Post

Cerolobo
RE: Programming Help With Testing A Library
6 May, 2008 - 03:11 PM
Post #7

D.I.C Regular
Group Icon

Joined: 5 Apr, 2008
Posts: 440



Thanked: 31 times
My Contributions
Lets walk through
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;
}


with

a.addValue(1);
a.addValue(2);
a.addValue(3);
a.removeValue(2);

So, the array look like this 1, 2, 3

CODE

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

newArray[i]=statValue[i];

to

newArray[changedNumOfElements]=statValue[i];
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 04:21 PM
Post #8

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8


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:
QUOTE
Mean: 4.25 Median: 5 Mid-range: 4 Mode: 3 Range: 4 Standard Deviation: 1.39194
Mean: 2 Median: -2.11008e+037 Mid-range: 2 Mode: 1 Range: 2 Standard Deviation:
1
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
User is offlineProfile CardPM
+Quote Post

Cerolobo
RE: Programming Help With Testing A Library
6 May, 2008 - 04:36 PM
Post #9

D.I.C Regular
Group Icon

Joined: 5 Apr, 2008
Posts: 440



Thanked: 31 times
My Contributions
The problem is here

CODE

    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

NumOfElements == 2;

NumOfElements / 2 = 2 / 2 = 1
(NumOfElements / 2) + 1 = 2 / 2 + 1 = 1 + 1 = 2

So, you are accessing index 1 and index 2. Since you only have two elements in the array, only indexes 0 and 1 are valid.

You should be able to figure out a way to correct both if statements.
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 04:55 PM
Post #10

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

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
User is offlineProfile CardPM
+Quote Post

Cerolobo
RE: Programming Help With Testing A Library
6 May, 2008 - 05:04 PM
Post #11

D.I.C Regular
Group Icon

Joined: 5 Apr, 2008
Posts: 440



Thanked: 31 times
My Contributions
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;


NumOfElements == 10

10 % 2 = 0

So, the second if statement executes.

NumOfElements / 2 = 10 / 2 = 5
NumOfElements / 2 + 1 = 10 / 2 + 1 = 6

So, you are access index 5 and 6.

The aviable indexs are

CODE

0 1 2 3 4 5 6 7 8 9
| Left  | | Right |


You want to be compairing index 4 and 5. Not 5 and 6.




Now, lets look at NumOfElements == 11

NumOfElements == 11

11 % 2 = 1

So, the first if statement executes.

(NumOfElements + 1) / 2 = 12 / 2 = 6

Again, the availableindex
CODE

0 1 2 3 4 5 6 7 8 9 10
          |
       Middle




In other words, actually THINK ABOUT THE MATH AND LOGIC. Do you just try to preform a quick patch.
User is offlineProfile CardPM
+Quote Post

bcasanov
RE: Programming Help With Testing A Library
6 May, 2008 - 05:24 PM
Post #12

New D.I.C Head
*

Joined: 6 May, 2008
Posts: 8

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!

Regards,

bcasanov
User is offlineProfile CardPM
+Quote Post

Reply to this topicStart new topic
Time is now: 12/2/08 11:30PM

Live C++ Help!

C++ Tutorials

Reference Sheets

C++ Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month