tags:

views:

494

answers:

8

Hello 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.

+2  A: 

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.

Charles Bailey
`std::fill_n` might be a better match than fill. Otherwise, good answer, +1 :)
jalf
+1  A: 

If you are just doing string manipulation, use string.

ergosys
+4  A: 

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
+1  A: 

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
But is the use appropriate when it can be replaced with the safer, and potentially more efficient `std::fill`?
jalf
@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
+1  A: 

Typically, it is better you use std::string for what you're trying to do.

std::ostringstream stream;
stream << name << oldname << ' ' << r.name;
std::string str(stream.str());

Directly manipulating char* is not ideal.

Travis Gockel
This gets my upvote, but if you are using char*, you may as well use the C-style functions for working with it. That said, I don't know why you don't use strcpy rather than memcpy (..., strlen (...)). Also, you don't need to use std::ostringstream just to concatenate two std::string instances, though it's very useful for more complex string-building.
Steve314
+1  A: 

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
+1  A: 

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
A: 
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