c equivilant to "copy"

S

Shagy

Greetings,
I've been trying to find an equivant c funtion to the c++ copy function.

Description:

copy(char *cstring, size_t count, size_t offset);

Copies "count" characters from a C-style string starting at offset.


Let's say I have the string "Hello There" and I needed only the "llo" part
from hello. How would I accomplish this? Using the c++ I could use the
copy function.

Any help would be appreciated,
Thanks!
 
K

Krishanu Debnath

Shagy said:
Greetings,
I've been trying to find an equivant c funtion to the c++ copy function.

Description:

copy(char *cstring, size_t count, size_t offset);

Copies "count" characters from a C-style string starting at offset.


Let's say I have the string "Hello There" and I needed only the "llo" part
from hello. How would I accomplish this? Using the c++ I could use the
copy function.

Any help would be appreciated,
Thanks!
Probably what you are asking ...

strncpy(dest, cstring + offset, count);
dest[count] = '\0';

assuming dest in large enough to hold 'count + 1' character.

Krishanu
 
P

pete

Probably what you are asking ...

strncpy(dest, cstring + offset, count);
dest[count] = '\0';

assuming dest in large enough to hold 'count + 1' character.

Since you are not copying an entire string,
memcpy would work just as well as strncpy.

/* BEGIN new.c */

#include <string.h>
#include <stdio.h>

int main(void)
{
char dest[sizeof "llo"];
size_t count;

count = sizeof dest - 1;
memcpy(dest, "Hello There" + 2, count);
dest[count] = '\0';
puts(dest);
return 0;
}

/* END new.c */
 
C

CBFalconer

Shagy said:
I've been trying to find an equivant c funtion to the c++ copy
function.

Description:

copy(char *cstring, size_t count, size_t offset);

Copies "count" characters from a C-style string starting at
offset.

Let's say I have the string "Hello There" and I needed only
the "llo" part from hello. How would I accomplish this? Using
the c++ I could use the copy function.

char *strncpy(char *dest, const char *src, size_t max);

is available in <strings.h>. The corresponding usage would be:

dest = strncpy(dest, src + offset, max);

and you can obviously omit the "dest =" portion. In your example:

strncpy(dest, "Hello There" + 2, 3);

However you will get better and safer results by using strlcpy (and
strlcat) as proposed by the BSD group. You can find an
implementation, justification, and description at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>
 
L

Lawrence Kirby

char *strncpy(char *dest, const char *src, size_t max);

But be aware that strncpy() is a dangerous function for the unwary, it
doesn't always null terminate the destination string. strncat() is better.
is available in <strings.h>. The corresponding usage would be:

That would be said:
dest = strncpy(dest, src + offset, max);

and you can obviously omit the "dest =" portion. In your example:

strncpy(dest, "Hello There" + 2, 3);

dest[0] = '\0';
strncat(dest, "Hello There" + 2, 3);

is a better approach. In this case as others have mentioned memcpy() is
another possibility as in

memcpy(dest, "Hello There" + 2, 3);
dest[3] = '\0';

Also consider sprintf()

sprintf(dest, "%.3s", "Hello There" + 2);

The real benefit of sprintf() can be seen if this is just a part of
building a more complex string.

Lawrence
 
S

Stan Milam

Krishanu said:
Probably what you are asking ...

strncpy(dest, cstring + offset, count);
dest[count] = '\0';

assuming dest in large enough to hold 'count + 1' character.

Krishanu

My favorite way of doing this is:

strncpy( dest, cstring + offset, count )[count] = '\0';

It works because strncpy() returns the address of the dest argument.

--
Regards,
Stan Milam
=============================================================
Charter Member of The Society for Mediocre Guitar Playing on
Expensive Instruments, Ltd.
=============================================================
 
W

William Xuuu

Stan Milam said:
My favorite way of doing this is:

strncpy( dest, cstring + offset, count )[count] = '\0';

It works because strncpy() returns the address of the dest argument.

cool. ;-)

Can someone give an example that strncpy() would be safer than strcpy() ?
Should we never use strcpy() ?
 
C

Chris Croughton

Stan Milam said:
My favorite way of doing this is:

strncpy( dest, cstring + offset, count )[count] = '\0';

It works because strncpy() returns the address of the dest argument.

cool. ;-)

Can someone give an example that strncpy() would be safer than strcpy() ?

#include <stdio.h>

void func(const char *str)
{
char buff[10];
strcpy(buff, str);
printf("%s\n", buff);
}

int main(int argc, char **argv)
{
if (argc > 1)
func(argv[1]);
return 0;
}

If the user runs this with parameter "1234567890", the buffer will
overflow (10 characters plus the terminating '\0'), as it will with a
longer string. In the Real World(tm) user input can't be guaranteed to
be right. If the strcpy were replaced by

strncpy(buff, str, 9)[9[ = '\0';

the program would be safe. (In practice, of course, you might want to
detect the overflow and report it as an error, and to use sizeof(buff)-1
instead of an explicit value.)
Should we never use strcpy() ?

strcpy() is completely safe to use /if/ you know that the string will
fit. Most of the time in my programs I know that the string will fit
because I have done checks elsewhere, or because I have just allocated
memory to the size of the string:

char *strDup(const char *str)
{
char *p = malloc(strlen(str) + 1);
if (p)
return strcpy(p, str);
return NULL;
}

Note that strcat also has the problem that the buffer can overflow, and
it's messy and wasteful to use strncat to detect that (since strncat
takes the number of characters to be copied not the length of the
buffer, so you still have to do strlen(buff) to determine whether the
string will fit).

Also, strncpy() will pad out the rest of the buffer with nul ('\0')
characters. Most of the time this is wasteful, especially if using a
big buffer with a small source string many times.

Because of these faults, the functions strlcpy() and strlcat() were
introduced in OpenBSD 2.4, and many of us hope that they will be
incorporated into a future C standard revision. See

http://www.courtesan.com/todd/papers/strlcpy.html

for example (the functions are easy to write, or you can use the OpenBSD
source under their Free Software licence).

Chris C
 
C

CBFalconer

Chris said:
.... snip ...

Because of these faults, the functions strlcpy() and strlcat() were
introduced in OpenBSD 2.4, and many of us hope that they will be
incorporated into a future C standard revision. See

http://www.courtesan.com/todd/papers/strlcpy.html

for example (the functions are easy to write, or you can use the
OpenBSD source under their Free Software licence).

Or you can use my implementation (in portable code, which I have
put in the public domain) found at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

The point is that they are much safer. If your system already
provides them, use them. If not it is almost always safe to use
those reserved names (I know of no exceptions).
 
C

Chris Croughton

Or you can use my implementation (in portable code, which I have
put in the public domain) found at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

My ones use memmove so they are safe against overlapping strings, but I
see why you didn't want to use other library functions (my code uses the
Zlib licence, which is about as free as it gets without being PD). I
notice you include the page I pointed to.
The point is that they are much safer. If your system already
provides them, use them. If not it is almost always safe to use
those reserved names (I know of no exceptions).

Solaris and some of the BSD variants already have them in string.h If
the prototypes are compatible (for instance no one using the restrict
keyword on the pointers) there shouldn't be a problem with including the
header file as well as string.h.

Chris C
 
R

Richard Bos

Stan Milam said:
Krishanu said:
strncpy(dest, cstring + offset, count);
dest[count] = '\0';

assuming dest in large enough to hold 'count + 1' character.

My favorite way of doing this is:

strncpy( dest, cstring + offset, count )[count] = '\0';

Well, thanks a lot for propagating the idea that we C programmers create
write-only code :-/

Richard
 
L

Lawrence Kirby

Krishanu said:
Probably what you are asking ...

strncpy(dest, cstring + offset, count);
dest[count] = '\0';

assuming dest in large enough to hold 'count + 1' character.

Krishanu

My favorite way of doing this is:

strncpy( dest, cstring + offset, count )[count] = '\0';

It is best to avoid strncpy() completely. It isn't a "true" string
function as it *always* writes out exactly the number of characters
specified by the 3rd argument. This means that the result may not be null
termnated (hence the extra write you need to do) or it may end up writing
a whole load of unnecessary null characters after the string data. If you
want to do it in one statement you can use sprintf() or

*dest = '\0', strncat( dest, cstring + offset, count );

Lawrence
 
B

bd

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

CBFalconer wrote:

[snip]
However you will get better and safer results by using strlcpy (and
strlcat) as proposed by the BSD group. You can find an
implementation, justification, and description at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

Until this becomes standard one must not use it in ANSI/ISO C comforming
programs, as it intrudes upon the str*() namespace.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)

iD8DBQFB7BZS+hz2VlChukwRAkV4AJ9RSs/cdfx1vwnw9t64mGo6k3HYswCfYcdk
n+A4IQXI6M/7M66UM7ggeuE=
=bL30
-----END PGP SIGNATURE-----
 
C

CBFalconer

bd said:
CBFalconer wrote:

[snip]
However you will get better and safer results by using strlcpy
(and strlcat) as proposed by the BSD group. You can find an
implementation, justification, and description at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

Until this becomes standard one must not use it in ANSI/ISO C
comforming programs, as it intrudes upon the str*() namespace.

If it creates a difficulty, rename the functions. You have the
complete source. In practice there will be no problem unless the
existing system already implements them.
 
J

jake1138

Wouldn't a function like this give you safety and NUL-termination?

char *mystrncpy(char *dest, const char *src, size_t size)
{
*dest = '\0';
return strncat(dest, src, size-1);
}
 
C

CBFalconer

jake1138 said:
Wouldn't a function like this give you safety and NUL-termination?

char *mystrncpy(char *dest, const char *src, size_t size)
{
*dest = '\0';
return strncat(dest, src, size-1);
}

no. Think about it.
 
R

Richard Bos

CBFalconer said:
no. Think about it.

Ok, I've thought about it. Given

char s1[20];
char s2[]="abcdefghijklmnopqrstuvwxyz";

how is

mystrcpy(s1, s2, 20);

less safe than

strlcpy(s1, s2, 20);

and how is

strlcpy(s1, s2, 26);

safer than

strlcpy(s1, s2, 26);

Richard
 
C

CBFalconer

Richard said:
CBFalconer said:
no. Think about it.

Ok, I've thought about it. Given

char s1[20];
char s2[]="abcdefghijklmnopqrstuvwxyz";

how is

mystrcpy(s1, s2, 20);

less safe than

strlcpy(s1, s2, 20);

mystrcpy leaves an unterminated string (no '\0') in s1, and returns
a pointer to s1, which will almost certainly lead to future
faults. strlcpy leaves a terminated string in s1, and returns 26
to indicate the size required. Since 26 >= 20 you know the output
was truncated.
and how is

strlcpy(s1, s2, 26);

safer than

strlcpy(s1, s2, 26);

These are identical, and are lying to strlcpy about the space
available.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top