views:

203

answers:

7

I have a string pointer like below,

char *str = "This is cool stuff";

Now, I've references to this string pointer like below,

char* start = str + 1;
char* end = str + 6;

So, start and end are pointing to different locations of *str. How can I copy the string chars falls between start and end into a new string pointer. Any existing C++/C function is preferable.

+3  A: 

Just create a new buffer called dest and use strncpy

char dest[end-start+1];
strncpy(dest,start,end-start);
dest[end-start] = '\0'
Arkaitz Jimenez
Why Kaboom? What's magic about 256?
jmucchiello
previously it was "dest[256]"
mxp
Keep in mind that if there is a `\0` character somewhere between `start` and `end`, the copying will stop there.
ndim
@ndim - we've already established that start and end are pointers within a C string, so therefore there can't be a 0 byte anywhere except at the end.
Paul Tomblin
A: 
char newChar[] = new char[end-start+1]]
p = newChar;
while (start < end)
  *p++ = *start++;
Paul Tomblin
You have a reserved word for your string name and no delete[].
Ron Warholic
A bit complicated compared to Arkaitz Jimenez's solution.Also, isn't 'new' a protected keyword that cannot be used as variable name? Doesn't copmpile on VC9.
mxp
@Sid, if you delete it, then you don't have the string any more.
Paul Tomblin
@Paul, I think @Sid he means when you've finished with the string you need to delete[] itAlso, there's no check for end > start, so you could get issues if that's the case. In this simple example end is > start, but it's a good check to have on more generic code.
pxb
@pxb, you always have to delete the memory once you're done with it. The question wasn't about the full life cycle of the variable, just how to create it.
Paul Tomblin
@Paul, agreed. I'm just guessing as to the reason for Sid's comment about delete[]. If you really want to know exactly what Sid meant, you'll have to ask him ;)Personally, I don't see any problem when giving a code example to make it clear when and how to tidy up. It's easily forgotten. Of course if it was a regular pointer (not an array new) you could use std::auto_ptr to make things simpler and safer.
pxb
For beginner's questions I much prefer to show the lifecycle to better reinforce it. A '// do stuff' before the delete would suffice. It's not strictly necessary so that's a minor point.
Ron Warholic
@Sid, not one of the other answers showed the entire lifecycle of the variable, so why are you slamming on just mine?
Paul Tomblin
A: 

It's best to do this with strcpy(), and terminate the result yourself. The standard strncpy() function has very strange semantics.

If you really want a "new string pointer", and be a bit safe with regard to lengths and static buffers, you need to dynamically allocate the new string:

char * ranged_copy(const char *start, const char *end)
{
  char *s;

  s = malloc(end - start + 1);
  memcpy(s, start, end - start);
  s[end - start] = 0;

  return s;
}
unwind
A: 

If you want to do this with C++ STL:

#include <string>
...
std::string cppStr (str, 1, 6); // copy substring range from 1st to 6th character of *str
const char *newStr = cppStr.c_str(); // make new char* from substring
Alex Reynolds
+2  A: 

Use STL std::string:


#include 
const char *str = "This is cool stuff";
std::string part( str + 1, str + 6 );

This uses iterator range constructor, so the part of the C-string does not have to be zero-terminated.

Nikolai N Fetissov
A: 

This is one of the rare cases when function strncpy can be used. Just calculate the number of characters you need to copy and specify that exact amount in the strncpy. Remember that strncpy will not zero-terminate the result in this case, so you'll have to do it yourself (which, BTW, means that it makes more sense to use memcpy instead of the virtually useless strncpy).

And please, do yourself a favor, start using const char * pointers with string literals.

AndreyT
A: 

Assuming that end follows the idiomatic semantics of pointing just past the last item you want copied (STL semantics are a useful idiom even if we're dealing with straight C) and that your destination buffer is known to have enough space:

memcpy( buf, start, end-start);
buf[end-start] = '\0';

I'd wrap this in a sub-string function that also took the destination buffer size as a parameter so it could perform a check and truncate the result or return an error to prevent overruns.

I'd avoid using strncpy() because too many programmers forget about the fact that it might not terminate the destination string, so the second line might be mistakenly dropped at some point by someone believing it unnecessary. That's less likely if memcpy() were used. (In general, just say no to using strncpy())

Michael Burr