0

There is class

class Cow{
    char name[20];
    char* hobby;
    double weight;
public:
    [..]
    Cow & operator=(const Cow &c);
    [..]
};

and I'm wondering how to write definition of operator= method. I wrote definition that equal to -

Cow & Cow::operator=(const Cow &c){
    if(this==&c)
        return *this;
    delete [] hobby;
    hobby=new char [strlen(c.hobby)+1];
    weight=c.weight;
    strncpy(name,c.name,20);
    return *this;
}

but what if there is already created name[20] with like "Philip Maciejowsky" and I strncpy to it "Adam". After operator=(...) will name equal to "adamlip Maciejowsky"? How to fix it if it overwrites like that?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Filip Bartuzi
  • 5,711
  • 7
  • 54
  • 102

2 Answers2

1

Use strcpy() or add a null terminator after using strncpy(). strncpy() does not add the null terminator (\0), where as strcpy() does.

My advice: use std::string instead of c-styled null terminated string.

when in rome, do the romans!


From http://cplusplus.com

No null-character is implicitly appended at the end of destination if source is longer than >num (thus, in this case, destination may not be a null terminated C string).

Since Adam is lesser in length than Philip Maciejowsky - the strncpy() will NOT pad the remaining destination(that is Philip Maciejowsky) with \0. And hence the output looks like:

Adamip Maciejowsky - strcpy() or doing memset(destination, 0, lengthOfDestination) and then calling strncpy() will result in your output being Adam as well. Multiple ways to do what you're trying to do.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Or if possible use std::string rather than old C style processing. – suspectus Mar 08 '13 at 23:25
  • that is how I would do it @suspectus . since the OP wants to learn about C styled strings, . But I always say "when in rome, do the romans" – Aniket Inge Mar 08 '13 at 23:25
  • On my machine, the manpage for strncpy says that it null-fills the rest of the array it's copying to. – medgno Mar 08 '13 at 23:30
  • @medgno that's non-standard behavior. The standard says `strncpy()` **should not** nullterminate – Aniket Inge Mar 08 '13 at 23:31
  • From Cplusplus.com : No null-character is implicitly appended at the end of destination if source is longer than num (thus, in this case, destination may not be a null terminated C string). – Aniket Inge Mar 08 '13 at 23:32
  • Right, I saw that bit, but thought that only means that you might want to set `name[NAME_SIZE-1] = 0` if you're really paranoid. Otherwise, if the buffer has enough size for what you're copying, it'll be null-padded. I think we might be strongly agreeing with each other. :) – medgno Mar 08 '13 at 23:36
  • If you want to guarantee that the string is always null-terminated, initialize `name[19]` to 0, and use `strncpy(name, c.name, 19);` – Barmar Mar 08 '13 at 23:36
  • @medgno The issue is if you specify `NAME_SIZE` as the limit, it can overwrite the null-terminator with a character. So you have to use `NAME_SIZE-1` as the limit as well. – Barmar Mar 08 '13 at 23:38
  • @Barmar, I would use `memset()` and clear the whole damn string :-P – Aniket Inge Mar 08 '13 at 23:38
  • `strcpy()` definitely should **not** be used, since it may cause a buffer overflow unless you check the length of the source first. Using a `string` is the best choice, otherwise use `strncpy()` with a limit of `(sizeof Cow.name)-1`. – Barmar Mar 08 '13 at 23:40
  • how about `memcpy()`?? @Barmar - Historically, `memcpy()` has been reported to be faster than `strcpy()` and `strncpy()`(I distinctly remember reading an article about that) – Aniket Inge Mar 08 '13 at 23:41
  • @Aniket That's even more convoluted. Then the amount to copy is `min(NAME_SIZE-1, strlen(c.name)+1)`. This requires two passes through the source, one to get the length, and another to copy it. – Barmar Mar 08 '13 at 23:44
  • `strncpy()` *may or may not* null-terminate the target array. It pads it with zero or more `'\0'` characters, depending on the length of the source string and the specified size of the target array. – Keith Thompson Mar 09 '13 at 00:00
  • @KeithThompson yes, I clarified that in the bottom half of the answer :-) – Aniket Inge Mar 09 '13 at 00:17
0

First, if you're using C++ you shouldn't be using C-style strings and should instead be using the class std::string which makes everything easier in every way.

Assuming you're required to use char* strings, strncpy takes care of this. C-style string are null-terminated, meaning that a string such as "test" takes up five bytes. The bytes are, in order, {'t', 'e', 's', t', 0}. The zero (or null) byte serves as a marker that the end of the string has been reached.

From the manpage for strncpy on my system:

The following sets chararray to abc\0\0\0:

       char chararray[6];

       (void)strncpy(chararray, "abc", sizeof(chararray));

So this means that the string will contain "adam\0\0\0\0\0\0\0[etc.]" where \0 represents the null byte. String functions will stop processing when they read the first null (because, remember, with C-style strings, there's no way to know the length of the string without scanning through it looking for \0).

medgno
  • 188
  • 1
  • 5