9

I have this code

  char * oldname = new char[strlen(name) + 1];

  memcpy(oldname,name,strlen(name) + 1);

  name = new char[strlen(oldname) + strlen(r.name) + 1];
  memset(name, '\0', strlen(name));

  strcat(name,oldname);
  strcat(name," ");
  strcat(name,r.name);

I understand that it is a no no to use memcpy and memset but I haven't understood exactly how to use this in C++, preferably without std.

Does anyone know? Thank you.

Luca Matteis
  • 29,161
  • 19
  • 114
  • 169
Para
  • 2,022
  • 5
  • 34
  • 73
  • 1
    It seems you may have allocated one character too little for name. And I don't quite see why you fill the array with zeros in the first place, if you are going to overwrite it thereafter. (The first strcat requires only the first character to be null, strcpy wouldn't require even that. Both these functions null-terminate the string for you.) Oh, and `strlen(name)` will not work very nicely, unless the string already contains a properly terminated c-string! It doesn't do anything else than count all the characters up to the first null character. – UncleBens Jan 24 '10 at 23:35

7 Answers7

13

In general, there's std::fill. http://www.cplusplus.com/reference/algorithm/fill/

Or in this particular instance, you should consider using std::vector<char>.

(Note that memset can still be used in C++ if you use #include <cstring>, although it's less idiomatic in C++.)

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
12

One possible replacement for memset when you have an array of object types is to use the std::fill algorithm. It works with iterator ranges and also with pointers into arrays.

memcpy calls can usually be replaced with calls to std::copy.

e.g.

std::copy(name, name + strlen(name) + 1, oldname);
// ...
std::fill(name, name + strlen(name), '\0');

memset and memcpy are still there and can be used when appropriate, though. It's probably a bigger no-no from many C++ developer's point of view to be using a raw new and not using a resource managing object. It's much better to use a std::string or a std::vector<char> so that memory deallocation is automatic and the code is more exception safe.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
2

I understand that it is a no no to use memcpy and memset but I haven't understood exactly how to use this in C++, preferably without std.

It's not a no-no to use memcpy and memset when their use is appropriate. Why should it be?

There's std::copy in C++ that copies a set of items (works on any type and not just char*) from an iterator to another.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • But is the use appropriate when it can be replaced with the safer, and potentially more efficient `std::fill`? – jalf Jan 24 '10 at 23:24
  • 1
    @jalf: There's no doubt that `std::fill` should be preferred to `memset` in general *when it can be used*. My point was there's usually no language feature that you'll throw out completely. One example is some piece of code that needs to be compiled in C as well as C++. – Mehrdad Afshari Jan 24 '10 at 23:47
2

Other than the inconvenience of having to manually copy and do all the memory allocation yourself, there's nothing wrong with that C++ code.

I would, however, strongly encourage the use of std::string for string manipulation in C++.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
1

If you are just doing string manipulation, use string.

ergosys
  • 47,835
  • 5
  • 49
  • 70
1

To copy from a to b, take std::copy(src_start,src_end,dest_start) which increments src_start and copies it to the next destination element until src_start==src_end is met.

memcpy(oldname,name,strlen(name)+1)
// is the same as
std::copy(name,name+strlen(name)+1,oldname)

.. except it will also work for non-PODs, and you don't need to mess with byte lengths if a single element is more than one byte.

However, if you just want to do string manipulation, the std::string class (and std::wstring for wide char strings) are provided. Concatenating them is as simple as:

std::string s = "name",s2 = ..,s3 = ..;
s = s2+s+s3+"Hello";

Nothing keeps you from using the strxxx family of functions in C++, but I'd highly recommend you to switch to std::stringand rest of the STL. It's not perfect either, but much less error-prone.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
-3
char * oldname = new char[strlen(name) + 1];

    //memcpy(oldname,name,strlen(name) + 1);
    strcpy(oldname,name);

    name = new char[strlen(oldname) + strlen(r.name) + 1];
    //memset(name, '\0', strlen(name));
    name[0] = '\0';

    strcat(name,oldname);
    strcat(name," ");
    strcat(name,r.name);

I understand this now, just wanted to paste this code for all future visitors The commented lines are equivalent with the uncommented ones below them. C commented, C++ uncommented.

Para
  • 2,022
  • 5
  • 34
  • 73