-
求字符串长度
- strlen
-
长度不受限制的字符串函数
- strcpy 字符串拷贝
- strcat 字符串连接
- strcmp 比较字符串大小
-
长度受限制的字符串函数介绍
- strncpy 如果源字符串长度小于num,则用’\0’补齐
- strncat 和strcat相比,多个参数,把b串的前边的n个字符直接连接到a后边
- strncmp 和strcmp相比,多个参数,可指定对比前n个字符
-
字符串查找
- strstr 判断字符串str2是否是str1的子串
- strtok 从一个字符串中提取第一个以特定字符串为分割的字符串,原串被破坏。token就是分隔符。
-
错误信息报告
- strerror
-
字符操作
-
内存操作函数
- memcpy 从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中(不覆盖)
- memmove 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
- memset 把指定内存区域的前count个字节设置成字符c
- memcmp
-
strchr
strlen
size_t strlen ( const char * str );
-
字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
含 ‘\0’ )。
-
参数指向的字符串必须要以 ‘\0’ 结束。
-
函数的返回值为size_t,是无符号的
//方式一:计数器
int my_strlen(const char * str)
{
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
//方式二:不能创建临时变量计数器
int my_strlen(const char * str)
{
if (*str == '\0')
{
return 0;
}
else
return 1 + my_strlen(str + 1);
}
//方式三:指针—指针
int my_strlen(char *s)
{
char * p = s;
while (*p != '\0')
{
p++;
}
return p - s;
}
strcpy
char* strcpy(char * destination, const char * source);
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
char*my_strcpy(char*dest, const char*src)
{
char *tmp = dest;
assert(dest != NULL);//断言,如果为空指针,编译器会报错
assert(src != NULL);
while (*dest++ = *src++)
{
;
}
return tmp;
}
strcat
char * strcat ( char * destination, const char * source );
- 源字符串必须以\0结束
- 目标空间必须足够大,可容纳下源字符串的内容
- 目标空间必须可修改
- 字符串自己给自己追加
char *my_strcat(char* dest, char* src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
strcmp
int strcmp ( const char * str1, const char * str2 );
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
//符串比较
int my_strcmp (const char * src, const char * dst) {
int ret = 0 ;
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
//字符串比较(不区分大小写比较,大写字母会被映射为小写字母)
int stricmp(const char *dst, const char *src)
if((ch1 = (int)*dst) >= 'A' && (ch1 <= 'Z'))
ch1 += 0x20;
if((ch2 = (int)*src) >= 'A' && (ch2 <= 'Z'))
ch2 += 0x20;
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
- 拷贝num个字符从源字符串到目标空间。
- n=length 此种情况就相当于strcpy
- 如果源字符串的长度小于num,则拷贝完源字符串后,再目标后追加0,直至num个。
char *my_strncpy(char *dest, const char *src, int n)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = *dest;
//此循环用于处理n小于或等于源字符串src的长度(length)的情况
while (n && (*src))//当n等于0或者*src为'\0'的时候while循环停下
{
*dest++ = *src++;
n--;
}
//此循环用于处理n大于源字符串src的长度的情况
while (n > 0)//若进入了该循环说明上一个循环是因为*src='\0'而退出的,及n>length
{
*dest++ = 0;
n--;
}
return ret;
}
strncat
char * strncat ( char * destination, const char * source, size_t num );
功能:把src所指字符串的前n个字符添加到dest结尾处,覆盖dest结尾处的’\0’,实现字符串连接。
返回值:dest 字符串起始地址。
char *my_strncat(char *dest, char *src, int len)
{
assert(dest);
assert(src);
char* ret = dest;
while (*dest)
{
dest++;
}
while (len--)
{
*dest = *src;
dest++;
src--;
}
*dest = '\0';
return ret;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
- 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
int my_strncmp(const char *str1, const char *str2, int maxlen)
{
assert(str1 != NULL);
assert(str2 != NULL);
int ret = 0;
while (!(ret = (*str1 - *str2)) && *str1 && (maxlen--))
//如果两者相等且不为'\0',并且只能比较字符串str1和str2的前maxlen个字符
{
str1++;
str2++;
}
if (ret < 0)
ret = -1;
else if (ret>0)
ret = 1;
return ret;
}
strstr
- strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;否则,返回NULL。
char * strstr ( const char *, const char * );
查找字符串第一次出现的位置
char * my_strstr(const char* str1, const char* str2)
{
assert(str1);
assert(str2);
char* cp = (char*)str1;
char* substr = (char*)str2;
char* s1 = NULL;
if (*str2 == '\0')
return NULL;
while (*cp)
{
s1 = cp;
substr = str2;
while (*s1 && *substr && (*s1 == *substr))
{
s1++;
substr++;
}
if (*substr == '\0')
return cp;
cp++;
}
}
strtok
char * strtok ( char * str, const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会
- 改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
//该程序的关键点在于定义了一个静态的字符指针,该指针用来记录分割后的字符串的首地址
//传入NULL,则表示继续处理静态指针指向的余下字符串
char *strtok(char *str, const char *delim)
{
static char *src=NULL;//记下上一次非分隔字符串字符的位置,详见图示
const char *indelim=delim;//对delim做一个备份
int flag=1,index=0;
//每一次调用strtok,flag标记都会使得程序只记录下第一个非分隔符的位置,以后出现非分隔符不再处理
char *temp=NULL;//程序的返回值
if(str==NULL)
{
str=src;//若str为NULL则表示该程序继续处理上一次余下的字符串
}
for(;*str;str++)
{
delim=indelim;
for(;*delim;delim++)
{
if(*str==*delim)
{
*str=NULL;//若找到delim中感兴趣的字符,将该字符置为NULL
index=1;//用来标记已出现感兴趣字符
break;
}
}
if(*str!=NULL&&flag==1)
{
temp=str;//只记录下当前第一个非感兴趣字符的位置
flag=0;
}
if(*str!=NULL&&flag==0&&index==1)
{
src=str;//第二次出现非感兴趣字符的位置(之前一定出现过感兴趣字符)
return temp;
}
}
src=str;
//执行该句表明一直未出现过感兴趣字符,或者说在出现了感兴趣的字符后,就没再出现过非感兴趣字符
return temp;
}
原文:https://blog.csdn.net/mormont/article/details/53677363
strerror
char * strerror ( int errnum );
返回错误码,所对应的错误信息。
memcpy
void * memcpy ( void * destination, const void * source,size_t num);
- 函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝num个字节到目标destin中。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的
//一般版本,这里把dest和src都强制转换成了(char*)类型,但是copy一定是一个个字节完成的吗?
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert((NULL != dest) && (NULL != source));
char* tmp = (char*)dest;
const char* cur = (char*)src;
while (count--)
*tmp++ = *cur++;
return dest;
}
//进阶
//1.考虑指针类型,不同类型指针不能通过++赋值
//2.内存重叠情况需要从高地址向低地址copy
void* my_memcpy(void* dst, const void* src, size_t count)
{
void* ret = dst;
//dst <= src表示,如果dst在src的前面,从前往后复制不会覆盖src中还没有复制的内容
if (dst <= src || (char*)dst >= ((char*)src + count))
{
//从前往后复制,则不会出现覆盖src中没有复制的内容
while (count--)
{
*(char*)dst = *(char*)src; //char类型指针,表示一个字节一个字节的复制
dst = (char*)dst + 1; //移动一个字节
src = (char*)src + 1;
}
}
else
{
//从后往前复制,则不会出现覆盖src中没有复制的内容
dst = (char*)dst + count - 1;//移动到末尾
src = (char*)src + count - 1;
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1; //移动一个字节
src = (char*)src - 1;
}
}
//返回dst的头指针,还方便左值操作。
//如:ptstr = memmove(ptstr,src,count); cout << memmove(ptstr,src,count);
return ret;
}
memmove
void * memmove ( void * destination, const void * source, size_t num );
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- memmove用于拷贝字节,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
//拷贝重叠或者是不重叠的内存块
void * memmove(void * dst, const void* src, size_t count)
{
void * ret = dst;
if (dst <= src || ((char *)src + count))
{// copy from lower addresses to higher addresses
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else
{
//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);
}
memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
//比较从ptr1和ptr2指针开始的num个字节
int my_memcmp(char *str1,char *str2,int len)
{
assert(str1);
assert(str2);
while(len--)
{
while(*str1==*str2)
{
if(*str1=='\0')
return 0;
str1++;
str2++;
}
}
if(*str1>*str2)
return 1;
if(*str1<*str2)
return -1;
}
memset
//memset():把指定内存区域的前count个字节设置成字符c
void * memset(void* buffer, int c, size_t count)
{
assert(buffer != NULL);
char * p = (char *)buffer;
while(count--)
*p++ = (char)c;
return buffer;
}
strchr
函数功能:为在一个串中查找给定字符的第一个匹配之处
char *strchr(const char *str, int c)
在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置,如果未找到该字符则返回 NULL。
char * strchr(char *s, char c)
{
assert(str != NULL);
while(*s != '\0' && *s != c)
{
++s;
}
return *s==c ? s : NULL;
}
**strcpy和memcpy主要有以下3方面的区别。 **
复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
复制的方法不同。strcpy不需要指定长度,它遇到字符串结束符"\0"便结束。memcpy则是根据其第3个参数决定复制的长度。
用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
memcopy和memmove的关系:
memmove这个函数名称有它的历史原因,是因为有了memcpy函数后,发现这个函数有问题,又发明了另一个没有问题的memcpy函数,但为了爆出兼容性依然保留了memcpy函数,而将新版本的memcpy函数改名为memmove函数.