Write versions of the library functions strncpy , strncat , and strncmp , which operate on at most the first n characters of their argument strings. For example, strncpy(s,t,n) copies at most n characters of t to s . Full descriptions are in Appendix B.
Solution by Lars Wirzenius
Note: Lars uses EXIT_FAILURE in his test code, but not in the actual solution code. As far as I can tell, then, this is a Category 0 solution.
/*
* Solution to exercise 5-5 in K&R2, page 107:
*
* Write versions of the library functions strncpy, strncat,
* and strncmp, which operate on at most the first n characters
* of their argument strings. For example, strncpy(s,t,n) copies
* at most n characters of t to s. Full descriptions are in
* Appendix B.
*
* Note that the description in the exercise is not precise. Here are
* descriptions from Appendix B (though one should really follow the
* descriptions in the standard):
*
* char *strncpy(s,ct,n) copy at most n characters of string ct
* to s, return s. Pad with '\0's is ct
* has fewer than n characters.
* char *strncat(s,ct,n) concatenate at most n characters of
* string ct to string s, terminate s with
* '\0'; return s.
* int strncmp(cs,ct,n) compare at most n characters of string
* cs to string ct; return <0 if cs<ct,
* 0 if cs==ct, or >0 if cs>ct.
*
* Further note that the standard requires strncmp to compare the
* characters using unsigned char internally.
*
* Implementation note: since the function names are reserved by the
* standard, I've used the prefix `liw_'. This also allows Richard Heathfield to check
* the functions against the standard library versions. For each library
* function, I've written a test function that tests a particular test
* case. Where appropriate, the test functions use internal buffers that
* are of size MAX_BUF; at least some of the test cases should be longer
* to test all boundary conditions.
*
* Feel free to modify, copy, and use as you wish.
*
* Lars Wirzenius <liw@iki.fi>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BUF 16
char *liw_strncpy(char *s, const char *ct, size_t n) {
char *p;
p = s;
for (; n > 0 && *ct != '\0'; --n)
*p++ = *ct++;
for (; n > 0; --n)
*p++ = '\0';
return s;
}
char *liw_strncat(char *s, const char *ct, size_t n) {
char *p;
p = s;
while (*p != '\0')
++p;
for (; n > 0 && *ct != '\0'; --n)
*p++ = *ct++;
*p = '\0';
return s;
}
int liw_strncmp(const char *cs, const char *ct, size_t n) {
while (n > 0 && *cs == *ct && *cs != '\0') {
++cs;
++ct;
--n;
}
if (n == 0 || *cs == *ct)
return 0;
if (*(unsigned char *) cs < *(unsigned char *) ct)
return -1;
return 1;
}
void test_ncpy(const char *str) {
char std_buf[MAX_BUF];
char liw_buf[MAX_BUF];
memset(std_buf, 0x42, sizeof(std_buf));
strncpy(std_buf, str, sizeof(std_buf));
memset(liw_buf, 0x42, sizeof(liw_buf));
liw_strncpy(liw_buf, str, sizeof(liw_buf));
if (memcmp(std_buf, liw_buf, sizeof(std_buf)) != 0) {
fprintf(stderr, "liw_strncpy failed for <%s>\n", str);
exit(EXIT_FAILURE);
}
}
void test_ncat(const char *first, const char *second) {
char std_buf[MAX_BUF];
char liw_buf[MAX_BUF];
memset(std_buf, 0x69, sizeof(std_buf));
strcpy(std_buf, first);
strncat(std_buf, second, sizeof(std_buf) - strlen(std_buf) - 1);
memset(liw_buf, 0x69, sizeof(liw_buf));
strcpy(liw_buf, first);
liw_strncat(liw_buf, second, sizeof(liw_buf) - strlen(liw_buf) - 1);
if (memcmp(std_buf, liw_buf, sizeof(std_buf)) != 0) {
fprintf(stderr, "liw_strncat failed, <%s> and <%s>\n",
first, second);
exit(EXIT_FAILURE);
}
}
void test_ncmp(const char *first, const char *second) {
size_t len;
int std_ret, liw_ret;
if (strlen(first) < strlen(second))
len = strlen(second);
else
len = strlen(first);
std_ret = strncmp(first, second, len);
liw_ret = liw_strncmp(first, second, len);
if ((std_ret < 0 && liw_ret >= 0) || (std_ret > 0 && liw_ret <= 0) ||
(std_ret == 0 && liw_ret != 0)) {
fprintf(stderr, "liw_strncmp failed, <%s> and <%s>\n",
first, second);
exit(EXIT_FAILURE);
}
}
int main(void) {
test_ncpy("");
test_ncpy("a");
test_ncpy("ab");
test_ncpy("abcdefghijklmnopqrstuvwxyz"); /* longer than MAX_BUF */
test_ncat("", "a");
test_ncat("a", "bc");
test_ncat("ab", "cde");
test_ncat("ab", "cdefghijklmnopqrstuvwxyz"); /* longer than MAX_BUF */
test_ncmp("", "");
test_ncmp("", "a");
test_ncmp("a", "a");
test_ncmp("a", "ab");
test_ncmp("abc", "ab");
printf("All tests pass.\n");
return 0;
}
Category 0 Solution by Jose G. López
#include <stdio.h>
#define MAX 20
char *my_strncpy(char *s, const char *t, int n);
char *my_strncat(char *s, const char *t, int n);
int my_strncmp(const char *s, const char *t, int n);
int main(void)
{
char s[MAX] = "hello";
char *t = "he";
/* test my_strncpy */
my_strncpy(s, t, 5);
printf("my_strncpy - s = \"%s\"\n", s);
/* test my_strncat */
my_strncat(s, t, 20);
printf("my_strncat - s = \"%s\"\n", s);
/* test my_strncmp */
printf("my_strncmp - returns %d comparing \"%s\" with \"%s\"\n",
my_strncmp(s, t, 4), s, t);
return 0;
}
char *my_strncpy(char *s, const char *t, int n)
{
int i;
for (i = 0; i < n; i++)
*(s + i) = *(t + i) ? *(t + i) : '\0';
return s;
}
char *my_strncat(char *s, const char *t, int n)
{
int i;
while (*++s)
;
for (i = 0; i < n && *(t + i); i++)
*(s + i) = *(t + i);
*(s + i) = '\0';
return s;
}
int my_strncmp(const char *s, const char *t, int n)
{
int i;
for (i = 0; i < n && *(s + i) == *(t + i) && *(s + i); i++)
;
if (*(s + i) != *(t + i))
return (unsigned char)*(s + i) - (unsigned char)*(t + i);
return 0;
}
Category 0 Solution by Jesus Alvarez
#include <stdio.h>
#define STR_BUF 10000
#define STR_MATCH 7 /* Used as the base number of characters to match with. */
char *my_strncpy (char *, char *, int);
char *my_strncat (char *, char *, int);
int my_strncmp (char *, char *, int);
int my_strlen (char *);
int main(int argc, char *argv[])
{
int result;
char str_s[STR_BUF] = "All along the watchtower.";
char buf_1[STR_BUF];
char buf_2[STR_BUF] = "Bob Dylan: ";
char buf_3[STR_BUF] = "All along the Watchposition.";
printf ("----------------------------------------------------------\n");
printf (" Base String: %s\n", str_s);
printf ("----------------------------------------------------------\n");
my_strncpy (buf_1, str_s, STR_MATCH);
printf ("buf_1 (my_strncpy, 7 chars): %s\n", buf_1);
my_strncat (buf_2, str_s, STR_MATCH);
printf ("buf_2 (my_strncat, 5 chars): %s\n", buf_2);
result = my_strncmp(buf_3, str_s, STR_MATCH);
printf ("buf_3 (my_strncmp, 6 chars): %s\n", buf_3);
if ( result == 0 ) {
printf ("my_strncmp result: Both strings match up to %d char(s).\n",
STR_MATCH );
} else if ( result == -1 ) {
printf ("my_strncmp result: Strings do not match, buf_3 string ");
printf ("has a lesser value.\n");
} else if ( result == 1 ) {
printf ("my_strncmp result: Strings do not match, ");
printf ("base string has a greater value than buf_3.\n");
}
return 0;
}
/*
* Copy at most n characters of string ct to s; return s.
*/
char *my_strncpy (char *s, char *ct, int n)
{
int count = 1;
while ((*s++ = *ct++)) {
if (count++ == n) {
break;
}
}
return s;
}
/*
* Concatenate at most n characters of string ct to string s, terminate s with
* '\0'; return s.
*/
char *my_strncat (char *s, char *ct, int n)
{
int i = 0;
int len = my_strlen(s);
for (i = 0; n > 0; i++, n--) {
*(s + len + i) = *ct++;
}
*(s + len + i) = '\0';
return s;
}
/*
* Compare at most n characters of string cs to string ct; return < 0 if
* cs < ct, 0 if cs == ct, or > 0 if cs > ct.
*/
int my_strncmp (char *cs, char *ct, int n)
{
int i;
for (i = 0; i < n; i++) {
if (*(cs+i) < *(ct+i)) {
return -1;
} else if (*(cs+i) > *(ct+i)) {
return 1;
}
}
return 0;
}
int my_strlen (char *s)
{
int count = 0;
while (*s++ != '\0') {
count++;
}
return count;
}
menonsahab's
#include <stdio.h>
#include <string.h>
#define SIZE 100
char *my_strncpy(char *s, char *t, unsigned int n);
char *my_strncat(char *s, char *t, unsigned int n);
int my_strncmp(char *s, char *t, unsigned int n);
int main()
{
char s[SIZE] = "Aomine Daiki", t[SIZE] = "Kise Ryota";
char *ps = "Aomine Daiki", *pt = "Kise Ryota";
printf("my_strncmp(%s, %s, %d) = %d\n", ps, pt, 10, my_strncmp(s, t, 10));
printf("my_strncat(%s, %s, %d) = %s\n", ps, pt, 8, my_strncat(s, t, 8));
printf("my_strncpy(%s, %s, %d) = %s\n", ps, pt, 5, my_strncpy(s, t, 6));
return 0;
}
// Function description: http://www.cplusplus.com/reference/cstring/strncpy/
char *my_strncpy(char *s, char *t, unsigned int n)
{
int i, tlen = strlen(t);
for(i = 0; i < n; i++)
{
if(i < tlen)
s[i] = t[i];
else
s[i] = 0;
}
s[i] = 0;
return s;
}
// Function description: http://www.cplusplus.com/reference/cstring/strncat/
char *my_strncat(char *s, char *t, unsigned int n)
{
int i, tlen = strlen(t), slen = strlen(s);
for(i = 0; i < n; i++)
{
if(i < tlen)
s[slen + i] = t[i];
else
break;
}
s[slen + i] = '\0';
return s;
}
// Function description: http://www.cplusplus.com/reference/cstring/strncmp/
int my_strncmp(char *s, char *t, unsigned int n)
{
int i;
for(i = 0; i < n; i++)
if(s[i] != t[i] || s[i] == 0 || t[i] == 0)
return s[i] - t[i];
return 0;
}
'The C Programming Language' 카테고리의 다른 글
Chapter 5 - Pointers and Arrays 7 (0) | 2009.03.27 |
---|---|
Chapter 5 - Pointers and Arrays 6 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 4 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 3 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 2 (0) | 2009.03.27 |