You are not logged in.

#1 2009-02-26 03:28:08

luft
Member
Registered: 2009-01-11
Posts: 14

Visual C++ bug??

I was writing code for my class today, and I encountered an irregularity with the compiler. When I use a for loop and an array of pointers, the for loop and any other use of the array will only access the last member of the array. I encountered the same problem on a test today, and when using vectors. This does not manifest in g++. I was hoping you good people would help me determine if it is an error in my coding that g++ glosses over, or if it's a true bug with visual C++.

employee.h:

#ifndef EMPLOYEE
#define EMPLOYEE

class Employee
{
private:
    const static int NAME_SIZE = 10;
    unsigned int id;
    char name[NAME_SIZE];
    double payRate;
    double hours;
public:
    Employee();
    Employee(char *n, unsigned int i, double p, double h);

    //mutators

    virtual void setData(char *n, unsigned int i, double p, double h);

    //effectors

    virtual void showData() const;
    virtual double calcSalary() const;
    double calcCombinedSalary(Employee &e2) const;
    void makeStringFit(char *n);
};
#endif

employee.cpp:

#include "Employee.h"
#include <iostream>
#include <cstring>
#include <iomanip>

using namespace std;

Employee::Employee() : id(0), payRate(0), hours(0) 
{
    makeStringFit("");
}

Employee::Employee(char *n, unsigned int i, double p, double h) : id(i), payRate(p), hours(h)
{
    makeStringFit(n);
}

//mutators

void Employee::setData(char *n, unsigned int i, double p, double h)
{
    id = i;
    payRate = p;
    hours = h;
    makeStringFit(n);
}

//Effectors

double Employee::calcSalary() const
{ return hours * payRate; }

void Employee::showData() const
{
    cout << '\n' << setw(7) << left << id <<
        setw(NAME_SIZE+1) << right << name << ' ';
    cout << showpoint << fixed << setprecision(2);
    cout << setw(9) << left << payRate << 
        setw(9) << left << calcSalary() << flush;
}

double Employee::calcCombinedSalary(Employee &e2) const
{
    return (hours * payRate) + (e2.hours * e2.payRate);
}


void Employee::makeStringFit(char *n)
{
    bool stringFits = false;

    for(int i = 0; i != NAME_SIZE; i++)
        if(n[i] == '\0')
        {
            strncpy(name, n, i+1); //copies the length of n into name;
            stringFits = true;
        }
    if(stringFits == false)
    {
        strncpy(name, n, NAME_SIZE); // copies NAME_SIZE-1 characters into name;
        name[9] = '\0';    
    }
}

OverTimeEmployee.h:

#ifndef OVERTIMEEMPLOYEE
#define OVERTIMEEMPLOYEE

#include "Employee.h"

class OverTimeEmployee : public Employee
{
private:
    double overtimePayRate;
public:
    OverTimeEmployee();
    OverTimeEmployee(char *n, unsigned int i, double p, double h, double o);

    //mutators

    void setData(char *n, unsigned int i, double p, double h, double o);
    
    //effectors
    double calcSalary() const;
    void showData() const;
};
#endif

OverTimeEmployee.cpp:

#include "OverTimeEmployee.h"
#include "Employee.h"
#include <iostream>
#include <iomanip>

using namespace std;

OverTimeEmployee::OverTimeEmployee(): Employee(), overtimePayRate(0) {}
OverTimeEmployee::OverTimeEmployee(char *n, unsigned int i, double p, double h, double o): Employee(n,i,p,h), overtimePayRate(o){}

void OverTimeEmployee::setData(char *n, unsigned int i, double p, double h, double o)
{
    Employee::setData(n,i,p,h);
    overtimePayRate = o;
}

double OverTimeEmployee::calcSalary() const
{
    return 20;
}

void OverTimeEmployee::showData() const
{
    Employee::showData();
    cout << showpoint << fixed << setprecision(2);
    cout << left << setw(9) << overtimePayRate;
}

MyEmployeeClient.cpp

//
//Rename this file: MyEmployeeClient.cpp
//
//Written by: Mark Hammons_____________  key in your name

//add the line you will need to access your class 

#include "Employee.h"
#include "OverTimeEmployee.h"
#include <iostream>
using namespace std;

int main()
{

    //create a constant for the size of an array with 3 elements
    const unsigned int size = 3;

    //create an Employee object e1 using the constructor with no arguments
    Employee e1;
    
    // create an Employee object e2 using an implicit constructor call with all arguments
    // e2 will be for Joe who is employee 111 who worked 40 hours and makes 5.00 an hour
    Employee e2("Joe", 111, 30,6.00);
    
    
    // create an object e3 using an explicit constructor call with all arguments
    // e3 will be for Sam who is employee 222 who worked 30 hours and makes 6.00 an hour
    Employee e3 = Employee("Sam", 222, 30, 6.00);

    // create an object e4 using a copy constructor
    // e4 will have Joe's data
    Employee e4 = e2;

    // create an object e5 using a different version of a copy constructor
    // e5 will have Sam's data
    Employee e5(e3);

    //use the setData() method to assign values to the e1 data members
    e1.setData("Jackolante", 333, 23, 8.32);

    // create an array called employeeList which will hold three employees
    // assign the array one Employee and two OvertimeEmployees
    Employee* employeeList[3] = {&Employee("Nick", 444, 45, 1.00),
                                &OverTimeEmployee("Jake", 555, 50, 2.00, 40.00),
                                &OverTimeEmployee("Damien", 666, 9999, 9999, 9999)};
    //Modify this line to print out your name

    cout << "Mark Hammons" << endl;

    double twoSalaries = e1.calcCombinedSalary(e2);
    // use the method that adds the salaries  of two Employees together using e1 and e2 
    // and store the answer in twoSalaries


    cout << "The Joe and Sam together make $" << twoSalaries << endl;

    // display the data for the three employees in the array

    employeeList[0]->showData(); 
    employeeList[1]->showData();
    employeeList[2]->showData();

    for(int i = 0; i != 3; i++) //will cause improper input
        employeeList[i]->showData();
        
        //for(int i = 0; i != 0; i++)   //also will cause erroneus output
        //      employeeList[i]->showData();

    return 0;
}

With the for loop in the code (even if it fails it's first test) the output comes to:

666         Damien 9999.00  20.00    9999.00
666         Damien 9999.00  20.00    9999.00
666         Damien 9999.00  20.00    9999.00
666         Damien 9999.00  20.00    9999.00
666         Damien 9999.00  20.00    9999.00
666         Damien 9999.00  20.00    9999.00

With the for-loop commented out, the following output is produced:

444           Nick 45.00    45.00
555           Jake 50.00    20.00    40.00
666         Damien 9999.00  20.00    9999.00

And in g++, the unmodified code produces:

444           Nick 45.00    45.00
555           Jake 50.00    20.00    40.00
666         Damien 9999.00  20.00    9999.00
444           Nick 45.00    45.00
555           Jake 50.00    20.00    40.00
666         Damien 9999.00  20.00    9999.00

Any ideas what's causing this?

Added examples of the output.

Last edited by luft (2009-02-26 11:04:30)

Offline

#2 2009-02-26 10:52:47

Envil
Member
Registered: 2008-11-18
Posts: 52

Re: Visual C++ bug??

luft wrote:
    for(int i = 0; i != 3; i++) //will cause improper input
        employeeList->showData();
       
        //for(int i = 0; i != 0; i++)   //also will cause erroneus output
        //      employeeList[i]->showData();

The first loop kinda lacks the [] for the array while the 2nd one shouldnt do anything at all? ^^
Try writing the loop this way and see if that changes anything.

unsigned int i_Temp;

for ( i_Temp = 0; i_Temp < 3; i_Temp++ )
{
         employeeList[i_Temp]->showData();
}

Offline

#3 2009-02-26 11:03:32

luft
Member
Registered: 2009-01-11
Posts: 14

Re: Visual C++ bug??

Envil wrote:
luft wrote:
    for(int i = 0; i != 3; i++) //will cause improper input
        employeeList->showData();
       
        //for(int i = 0; i != 0; i++)   //also will cause erroneus output
        //      employeeList[i]->showData();

The first loop kinda lacks the [] for the array while the 2nd one shouldnt do anything at all? ^^
Try writing the loop this way and see if that changes anything.

unsigned int i_Temp;

for ( i_Temp = 0; i_Temp < 3; i_Temp++ )
{
         employeeList[i_Temp]->showData();
}

Actually, the first loop had the [] operator, but since I accidently used the quote flags instead of code flags to post that snippet of code, the forum interpreted it as the italics flag and hid it. I've fixed it by changing to the code tags on that snippet.

The second loop I included but commented as an example of another for loop that would cause the same problem to manifest.

Last edited by luft (2009-02-26 11:06:12)

Offline

#4 2009-02-26 14:35:59

Envil
Member
Registered: 2008-11-18
Posts: 52

Re: Visual C++ bug??

    // create an array called employeeList which will hold three employees
    // assign the array one Employee and two OvertimeEmployees
    Employee* employeeList[3] = {&Employee("Nick", 444, 45, 1.00),
                                &OverTimeEmployee("Jake", 555, 50, 2.00, 40.00),
                                &OverTimeEmployee("Damien", 666, 9999, 9999, 9999)};

EmployeeClient.cpp:49: warning: taking address of temporary
EmployeeClient.cpp:50: warning: deprecated conversion from string constant to 'char*'
EmployeeClient.cpp:50: warning: taking address of temporary
EmployeeClient.cpp:51: warning: deprecated conversion from string constant to 'char*'
EmployeeClient.cpp:51: warning: taking address of temporary

Maybe this is related to it, you should assign your classes to some variables and then pass the pointers of those variables or use the new keyword.
The way you do it now basically creates a class which goes poof right after its call since you arent storing it anywhere unless im missing something somewhere ^^

Try something like this instead.
I dont have visual c++ so i cant test that ^^

        
    Employee E1     = Employee("Nick", 444, 45, 1.00);
    Employee E2     = OverTimeEmployee("Jake", 555, 50, 2.00, 40.00);
    Employee E3     = OverTimeEmployee("Damien", 666, 9999, 9999, 9999);

    Employee* employeeList[3] = {&E1,
                                &E2,
                                &E3};

Last edited by Envil (2009-02-26 14:45:38)

Offline

#5 2009-02-26 18:45:49

luft
Member
Registered: 2009-01-11
Posts: 14

Re: Visual C++ bug??

Yeah, that or using new to allocate the members would have done it. I don't know why I thought assigning the address of a temporary object to a pointer was valid code. Thanks for your help.

Offline

Board footer

Powered by FluxBB