Zzz
Zzz

Reputation: 3025

Printing strange result

Why is the call to c2.view() printing out both the ID and name for the customer ID?

I have stared at this for a while and couldn't find a cause. I have either missed something really obvious or I don't understand how cstrings work :)

Customer.h

#ifndef CUSTOMER_H
#define CUSTOMER_H
 class Customer
 {
 private:
     char accountID[6];
     char name[30];
 public:
     Customer();
     Customer(char[], char[]);
     void view();
     Customer operator=(const Customer&);

 };
#endif

Customer.cpp

#include <string>
#include <iostream>
#include "Customer.h"
using namespace std;



Customer::Customer()
{
    strcpy(accountID, "");
    strcpy(name, "");
}

Customer::Customer(char acc[], char n[])
{
    strcpy(accountID, acc);
    strcpy(name, n);
}

void Customer::view()
{
    cout << "Customer name: " << name << endl;
    cout << "Customer ID: " << accountID <<endl;
}

Customer Customer::operator=(const Customer& right)
{
    strcpy(accountID, right.accountID);
    strcpy(name,  right.name);
    return* this;
}

Driver.cpp

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

int main()
{
    char id[] = "123456";
    char n[] = "Bob";
    Customer c1;
    Customer c2(id, n);
    c1.view();
    c2.view();
    system("pause");
    return 0;
}

Output:

Customer name:
Customer ID:
Customer name: Bob
Customer ID: 123456Bob
Press any key to continue . . .

Upvotes: 1

Views: 105

Answers (4)

evanmcdonnal
evanmcdonnal

Reputation: 48076

strcpy copies until it reaches a null terminator; \0 since you have none defined and you're running debug, name happens to occupy the memory adjacent to id and is also being copied into the buffer for id.

If you were to build release, you most likely would just have crap there. Either way, if you're using C strings you need null terminators at the end of all strings.

strcpy's implementation is something like;

while (*ptr2 != '\0')
{
    // copy string2 into string1's buffer until we reach it's null termintor
    *ptr1 = *ptr2
    ptr1++;
    ptr2++;
}
*(ptr1 + 1) = '\0'  // append null terminator

As you can see it relies on the null terminator and if it isn't there you're going to get a buffer overflow.

Upvotes: 1

chill
chill

Reputation: 16888

Use C++ std::string. You're writing past the bounds of the accountID member. This char id[] = "123456"; has seven elements.

What in this case happens is that the terminating null character first ends up at name[0] and then gets overwritten by the strcpy (name, n) and you get one contiguous sequence 123456Bob\0

Upvotes: 1

CapelliC
CapelliC

Reputation: 60014

because accoutID is delared of length 6, and when you strcpy in n, you overwrite the accountID' terminator, that overflowed to name[0]

Upvotes: 1

juanchopanza
juanchopanza

Reputation: 227390

You are passing a string with seven characters:

char id[] = "123456"; // one more character for null termination '\0'

but your array is of size 6. So when you print accountId, you go beyond the '6' character and print out whatever is next to it, which in this case happens to be the contents of name.

Save yourself a lot of trouble by using std::strings instead of character arrays.

Upvotes: 4

Related Questions