K&R2, exercise 5.5

A

arnuld

I have created this program, it works, runs fine, no errors. I just wanted
to have some comments or any advice:


/* K&R2, exercise 5-5, page 107
*
* write versions of the library function strncpy, strncat, and strncmp
* which operate on at most 1st n characters of their argumen strings. for
* example, strncpy(s, t, n) copies at most n characters from t to s. Full
* descriptions are in Appendix B.
*
* This time this is the original problem statament of the authors ;)
*
* presently I have created only the strncat
*
*/


#include <stdio.h>
#include <stdlib.h>


char* my_strcpy( char* , char*, int );
int my_strlen( char* );


int my_strlen( char* s )
{
char* ps;

ps = s;
while( *ps != '\0' )
{
++ps;
}

return ps - s;
}


char* my_strcpy( char* s, char* t, int n)
{
char *ps, *pt;
int len_of_s, len_of_t;


/* these pointers will store the original position of
s and t.
*/
ps = s;
pt = t;

len_of_s = my_strlen( s );
len_of_t = my_strlen( t );

s = ps;
t = pt;

/* what if number of characters to be copied are larger
* than the length of the string
*/
if( n > len_of_s )
{
printf("\n");
printf("ERROR: too many characters\n\n\n");
exit(EXIT_FAILURE);
}

/* what if oone of the strings or both were empty */
if( !len_of_s || !len_of_t)
{
printf("\n");
printf("OOPS: empty strings ? \n\n\n");
exit(EXIT_FAILURE);
}


s = ps;
t = pt;

/* now we are sure that n < length of s, so we do not need
* to check for NULL character at the end of the array
*/
for( ; n != 0; ++s, ++t, --n )
{
*s = *t;
}

return ps;
}



int main(void)
{
int n;
char s[] = "pope";
char t[] = "zzzzzzzz";


n = 3;
printf("copying %d characters from <%s> into <%s> = ", n, t, s);
printf("<%s>\n", my_strcpy( s, t, n));


return 0;
}



my friend said that it is a good C programming practice to check for
NULL pointer at the beginning of both "my_strlen" and "my_strcpy":


if( !s || !t )
printf("ERROR: NULL pointers\n");


any views on this too ?
 
B

Ben Bacarisse

arnuld said:
I have created this program, it works, runs fine, no errors. I just wanted
to have some comments or any advice:


/* K&R2, exercise 5-5, page 107
*
* write versions of the library function strncpy, strncat, and strncmp
* which operate on at most 1st n characters of their argumen strings. for
* example, strncpy(s, t, n) copies at most n characters from t to s. Full
* descriptions are in Appendix B.
*
* This time this is the original problem statament of the authors ;)

So now we know, in part, where the confusion about strncpy comes
from. Appendix B may explain the oddities, but the summary is vague
enough to engender confusion about the standard strncpy. I don't have
K&R2 and the exercise in not in K&R1.
* presently I have created only the strncat

You seem to have done strncpy.
char* my_strcpy( char* s, char* t, int n)
{
char *ps, *pt;
int len_of_s, len_of_t;


/* these pointers will store the original position of
s and t.
*/
ps = s;
pt = t;

len_of_s = my_strlen( s );
len_of_t = my_strlen( t );

s = ps;
t = pt;

/* what if number of characters to be copied are larger
* than the length of the string
*/
if( n > len_of_s )

This does not match the specification. The function "copies at most n
chars" it does not depend in any way on the number of initial non-null
chars in s (i.e. its current "string length").

my friend said that it is a good C programming practice to check for
NULL pointer at the beginning of both "my_strlen" and "my_strcpy":

if( !s || !t )
printf("ERROR: NULL pointers\n");

any views on this too ?

It is only worth asking a question is you know what to do with the
answer. I don't think printing a message is very useful. If I were
to do this check, I'd make it an 'assert' (and document it).
 
A

arnuld

This does not match the specification. The function "copies at most n
chars" it does not depend in any way on the number of initial non-null
chars in s (i.e. its current "string length").

s = "Bacarisse"
t = "Ben";
n = 5;

user mistakenly enters 5, when there are only 3 characters. So that if
condition check will print error.

It is only worth asking a question is you know what to do with the
answer. I don't think printing a message is very useful.

yes, that's why I was using exit(EXIT_FAILURE) from program.

If I were to
do this check, I'd make it an 'assert' (and document it).

K&R2 have not started to discuss <assert> yet.



This is from Appendix B of K&R2:

char *strncpy(s, ct, n)

copy at most n characters of string ct to s, return s. Pad with
'\0' if t has fewer elements than s.
 
B

Ben Bacarisse

arnuld said:
s = "Bacarisse"
t = "Ben";
n = 5;

user mistakenly enters 5, when there are only 3 characters. So that if
condition check will print error.

I am really confused now... The test is against the length of s (not
t) so why would it fail in this case? Swap the over:

s = "Ben";
t = "Bacarisse"
n = 5;

and your test rejects the copy even though there may be room (you can't
tell) in s for 5 rather than 3 chars.

Either way, you are writing a new function that does more (or less)
than the spec. calls for. That is almost always bad unless the more
you do is 100% safe and falls within some grey area of the spec.
yes, that's why I was using exit(EXIT_FAILURE) from program.

Fine for now, but you might like to search this group for the pros. and
cons. (mostly cons.) of calling exit from a general-purpose library
function.

This is from Appendix B of K&R2:

char *strncpy(s, ct, n)

copy at most n characters of string ct to s, return s. Pad with
'\0' if t has fewer elements than s.

Thanks. I'd have expected more clarity from that book. The number of
elements that s has is not obviously related to n.
 
M

Martin

char* my_strcpy( char* s, char* t, int n)
{
char *ps, *pt;
[...]

return ps;
}



int main(void)
{
int n;
char s[] = "pope";
char t[] = "zzzzzzzz";

n = 3;
printf("copying %d characters from <%s> into <%s> = ", n, t, s);
printf("<%s>\n", my_strcpy( s, t, n));


return 0;
}

As pointed out by Ben, this seems to be strncpy().

strncpy() always places n characters in s. It may truncate the source
(including the null character) or it may need to append null characters.
If the source string is less than n, it will stop the copy and append null
characters.

strncpy()'s second parameter is 'const char *' (indicating it's not
changed by the function).

Except that strncpy() stops on a terminating null character, it's actually
similar to memcpy().

You are doing a lot of unnecessary work in your function. All you need to
do is copy n characters from cs to t unless the character you're about to
copy is a null character, in whicih case you stop. This can be done in one
loop. When the loop finishes, activate another loop that adds the '\0'
characters up to n (if necessary). Then return t.
my friend said that it is a good C programming practice to check for
NULL pointer at the beginning of both "my_strlen" and "my_strcpy":


if( !s || !t )
printf("ERROR: NULL pointers\n");


any views on this too ?

It is good advice, but the Standard C functions strlen() and strcpy() are
not defined for null pointer arguments, and the caller may not want you to
display anything on the standard output in such a case.
 
M

Martin

All you need to do is copy n characters from cs to t
unless the character you're about to copy is anull character, in whicih
case you stop. This can be done in one loop. When the loop finishes,
activate another loop that adds the '\0' characters up to n (if
necessary). Then return t.

After I posted I noticed three typos in my response (quoted above).
All you need to do is copy n characters from cs to t

This should read

All you need to do is copy n characters from ct to s

Then return t.

This should read

Then return s.

... whicih ...

This, of course, is "which"! ;-)
 
A

arnuld

I am really confused now... The test is against the length of s (not
t) so why would it fail in this case? Swap the over:
s = "Ben";
t = "Bacarisse"
n = 5;

and your test rejects the copy even though there may be room (you can't
tell) in s for 5 rather than 3 chars.


"t" is getting copied in "s", so "s" must have length == or < n. length -f
"s" == 3 and n = 5. "s" is not going to dynamically expand because
"malloc" not discussed yet. Hence I don't think authors want me to copy 5
characters over an array which is filled with 3 characters at maximum.


Fine for now, but you might like to search this group for the pros. and
cons. (mostly cons.) of calling exit from a general-purpose library
function.

ok, thats a new thing. I will do it.


Thanks. I'd have expected more clarity from that book. The number of
elements that s has is not obviously related to n.



I for got to mention this:

s & ct are of type char* and const char* respectively. n is of type
size_t.


thats it what authors have to say about strncpy in Appendix B.
 
B

Ben Bacarisse

arnuld said:
"t" is getting copied in "s", so "s" must have length == or < n.

You must mean == or > n.
length -f
"s" == 3 and n = 5. "s" is not going to dynamically expand because
"malloc" not discussed yet. Hence I don't think authors want me to copy 5
characters over an array which is filled with 3 characters at
maximum.

Yes they do. You are confusing arrays and strings again. A string is
a pattern of data in an array of chars. The array always has a size,
but it may not always contain a string. Even when it does contain a
valid string, the length of that string tells you little about the
size of the array (except that the size is at least one more than the
string length). Functions like strncpy must be usable even in these
cases:

char a1[10]; /* size 10, no known data at all */
my_strcpy(a1, "abc", 10);

char a2[10] = ""; /* size 10, (string) length 0 */
my_strcpy(a2, "abc", 10);

char a3[10] = "abcdefghij"; /* size 10, no string at all! (no '\0') */
my_strcpy(a2, "abc", 10);
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top