// 在标准库中,函数不考虑src的'\0'终止字符,始终从src中拷贝count个字符到dst中。
// 建议使用memmove函数代替memcpy
void *memcpy ( void *dst, const void *src, size_t count )
{
//assert(dst != NULL && src != NULL && count >= 0);
void * ret = dst;
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
// 首先考虑源地址与目标地址是否存在重叠部分(目标地址是源地址连续内存的一部分),
// 如果有重叠部分从高地址向地址赋值,否则从低地址向高地址赋值。
void *memmove(void *dst, const void *src, size_t count)
{
//assert(dst != NULL && src != NULL && count >= 0);
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
// 把src中所有字符(包括'\0')拷贝到dst中;
// 如果dst的内存长度小于src,会造成dst越界
char *strcpy(char *dst, const char *src)
{
//assert(dst != NULL && src != NULL);
char *ret = dst;
/* Copy src over dst,'*'优先于++,先进行赋值再判断*ret是否有效,无论while()成立与否ret都加1 */
while (*ret++ = *src++);
return(dst);
}
// 把src中前count个字符拷贝到dst中;count小于sizeof(src)时拷贝后dst末尾要加'\0'
// 通常count是sizeof(dst)-1的值,防止越界拷贝
char *strncpy(char *dst, const char *src, size_t count)
{
if (count <= 0)
{
return dst;
}
char *start = dst;
while (count && (*start++ = *src++)) /* copy string */
count--;
if (count) // sizeof(dst) 大于 sizeof(src)
while (--count)
*start++ = '\0';
return(dst);
}
// src字符串连接到dst末尾(注意越界)
char *strcat(char *dst, const char *src)
{
char * cp = dst;
while (*cp)
cp++; /* find end of dst */
while (*cp++ = *src++); /* Copy src to end of dst */
return(dst); /* return dst */
}
char* strncat(char *dst, const char *src, size_t count)
{
if (count <= 0)
{
return dst;
}
char *start = dst;
while (*start)
{
start++;
}
while (count--)
{
if (!(*start++ = *src++))
return(dst);
}
*start = '\0';
return(dst);
}
// 内存块ptr1前count字节与ptr2前n个字节比较
// 返回值<0: ptr1 < ptr2
// =0: prt1 == ptr2
// >0: ptr1 > ptr2
int memcmp(const void *ptr1, const void *ptr2, size_t count)
{
if (count<=0)
{
return 0;
}
// 遇到第一个不相等的字符或者count=0时终止
while (--count && *(char *)ptr1 == *(char *)ptr2)
{
ptr1 = (char *)ptr1 + 1;
ptr2 = (char *)ptr2 + 1;
}
return( *((unsigned char *)ptr1) - *((unsigned char *)ptr2) );
}
int strncmp(const char *ptr1, const char *ptr2, size_t count)
{
if (count <= 0)
{
return 0;
}
while (--count && *ptr1 == *ptr2)
{
ptr1++;
ptr2++;
}
return (*(unsigned char *)ptr1 - *(unsigned char *)ptr2);
}
int strcmp(const char *ptr1, const char *ptr2)
{
while (*ptr1 == *ptr2)
{
ptr1++;
ptr2++;
}
return (*(unsigned char *)ptr1 - *(unsigned char *)ptr2);
}
// 定位value值第一次在buf中的位置,并返回改位置的指针。
// count指定遍历buf多少个字节。
void *memchr(const void *buf, int value, size_t count)
{
while (count && (*(unsigned char *)buf != (unsigned char)value)) {
buf = (unsigned char *)buf + 1;
count--;
}
return(count ? (void *)buf : NULL);
}
char *strchr(const char *buf, int character)
{
while (*buf && *buf != (char)character)
buf++;
if (*buf == (char)character)
return((char *)buf);
return(NULL);
}
//定位value值最后一次在buf中的位置,并返回改位置的指针
char * strrchr(char *str, int character)
{
char *start = (char *)str;
while (*str++); /* find end of string */
/* search towards front */
while (--str != start && *str != (char)character);
if (*str == (char)character) /* char found ? */
return((char *)str);
return(NULL);
}
//在buf字符串中的哪个索引位置第一次出现了keys字符串才有的字符
size_t strcspn(const char *buf, const char *keys)
{
const unsigned char *str = buf;
const unsigned char *ctrl = keys;
unsigned char map[16];
int count;
/* Clear out bit map */
for (count = 0; count < 16; count++)
map[count] = 0;
/* Set bits in str2 map */
while (*ctrl)
{
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
ctrl++;
}
count = 0;
map[0] |= 1; /* null chars not considered */
while (!(map[*str >> 3] & (1 << (*str & 7))))
{
count++;
str++;
}
return(count);
}
//在buf字符串中的哪个索引位置最后一次出现了keys字符串才有的字符
size_t strspn(const char *buf, const char *keys)
{
const unsigned char *str = buf;
const unsigned char *ctrl = keys;
unsigned char map[16]; // VS提供的源码中,map是32个元素
int count;
/* Clear out bit map */
for (count = 0; count < 16; count++)
map[count] = 0;
/* Set bits in control map */
while (*ctrl)
{
int retn = *ctrl >> 3;
int rrt = (*ctrl & 7);
map[*ctrl >> 3] |= (1 << (*ctrl & 7)); // 用16个char元素记录128个ASCII字符
ctrl++;
}
if (*str)
{
count = 0;
while (map[*str >> 3] & (1 << (*str & 7))) // 按照统一算法找到对应字符下标
{
count++;
str++;
}
return(count);
}
return(0);
}
// 在buf字符串中的哪个索引位置第一次出现了keys字符串才有的字符,返回那个位置的指针
char* strpbrk(const char *buf, const char *keys)
{
const unsigned char *str = buf;
const unsigned char *ctrl = keys;
unsigned char map[16];
int count;
/* Clear out bit map */
for (count = 0; count < 16; count++)
map[count] = 0;
/* Set bits in control map */
while (*ctrl)
{
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
ctrl++;
}
while (*str)
{
if (map[*str >> 3] & (1 << (*str & 7)))
return((char *)str);
str++;
}
return(NULL);
}
// strbuf的某段子字符串与sunstring一致,并返回第一个字符相等位置指针
char *strstr(const char *strbuf, const char *substring)
{
char *cp = (char *)strbuf;
char *s1, *s2;
if (!*substring)
return((char *)strbuf);
while (*cp)
{
s1 = cp;
s2 = (char *)substring;
while (*s1 && *s2 && !(*s1 - *s2))
{
s1++;
s2++;
}
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
#if 0
// 三种字符串分隔方法,每种方法都会修改原字符串的完整性
// strtok方法遍历strbuf;如果strbuf的字符符合delimiters字符串中某个分割字符,把该字符置换为'\0',返回字符串开始位置的指针。剩下的字符串保留在一个全局变量中
// 该方法不适合多线程操作
char *strtok(char *strbuf, const char *delimiters);
// strtok_s是windows下的方法,作用等同于strtok。但是strtok_s把剩余字符串保存到subbuf中。
char *strtok_s( char *strbuf, const char *strDelimit, char **subbuf);
// strtok_r是linux下的方法
char *strtok_r(char *strbuf, const char *delim, char **subbuf);
#endif
// 返回字符串长度('\0'不会计算在内,区别于sizeof)
size_t strlen(char *str);
C语言字符串相关操作及源码
最新推荐文章于 2023-06-24 21:06:32 发布