目录
求字符串长度
strlen函数
长度不受限制的字符串函数
strcpy 字符串复制函数
strcat 字符串追加函数
strcmp 字符串比较函数
长度受限制的字符串函数
strncpy 字符串复制函数
strncat 字符串追加函数
strncmp 字符串比较函数
字符串查找函数
strstr
strtok
错误信息报告
strerror 错误信息报告函数
perror 错误信息打印函数
内存操作函数
memcpy 内存复制函数
memmove 内存移动函数
memset 初始化内存函数
memcmp 内存比较函数
size_t strlen ( const char * str );
strlen函数返回类型是size_t,size_t其实就是无符号整形
1.字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包括'\0')。
2.参数指向的字符串必须要以'\0'结束。
例:
3.模拟实现strlen
//创建临时变量方式
int my_strlen(const char*str)
{
assert(str!=NULL);//保证指针的有效性,使用时记得引用头文件
int count=0;
while(*str)//当*str不为'\0'的时候进入循环
{
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(const char*str)
{
char*p=str;//把起始地址赋值给p,让p进行while循环
while(*p!='\0')
{
p++;
}
return p-str;
}
char * strcpy ( char * destination, const char * source );
1.源字符串(source指针指向的字符串)必须以'\0'结束
2.strcpy函数将source指针指向的字符串(包括'\0')复制到dest指定的位置。复制或追加字符串时不执行溢出检查。如果源字符串和目标字符串重叠,则strcpy的行为未定义。所以目标空间必须足够大,确保能放入源字符串。
3.模拟实现strcpy
char* my_strcpy(char* dest,const char* src)
{
char* ret=dest;//把目的地地址存起来,以防下面计算时变化找不到原来地址
assert(dest&&src);//保证指针的有效性,使用时记得引用头文件
//while (*src != '\0')
//{
// *dest = *src;
// dest++;
// src++;
//}
//*dest = *src;//拷贝'\0'
while((*dest++ = *src++))//上面和这里的实现是一样的
{
;
}
return ret;
}
--------------------------------------------------------------------------------------------------------------------------------
char * strcat ( char * destination, const char * source );
1.目标空间可修改且必须足够大,能容纳下源字符串内容,源字符串(source指针指向的字符串)必须以'\0'结束
2.strcat函数将source追加到dest,并用空字符终止结果字符串。source的第一个字符覆盖dest的终止空字符(即'\0')。追加字符串时不执行溢出检查。如果源字符串和目标字符串重叠,则strcat的行为未定义。
例:
3.模拟实现strcat
char* my_strcat(char* dest, const char*src)
{
char*ret = dest;//把目的地地址存起来,以防下面计算时变化找不到原来地址
assert(dest&&src);//保证指针的有效性,使用时记得引用头文件
while (*dest)//先找到目的地的'\0'
{
dest++;
}
while ((*dest++ = *src++))//追加过去
{
;
}
return ret;
}
--------------------------------------------------------------------------------------------------------------------------------
int strcmp ( const char * str1, const char * str2 );
strcmp函数不是比较字符串长度,是比较字符串字符的ASCII值,并返回一个值,指示它们之间的关系。
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字;
第一个字符串等于第二个字符串,则返回0;
第一个字符串小于第二个字符串,则返回小于0的数字;
例:
模拟实现strcmp:
int my_strcmp(const char*str1, const char*str2)
{
assert(str1&&str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;//str1大于或者小于str2的时候返回他们的差值
}
———————————————————————————————————————————
char * strncpy ( char * dest, const char * source, size_t num );
strncpy函数将source的初始计数字符复制到dest并返回dest。如果num小于或等于source的长度,则不会自动将空字符('\0')追加到复制的字符串中。如果num大于source的长度,则目标字符串将补0,补足num个。如果源字符串和目标字符串重叠,则strncpy的行为未定义。
例:
模拟实现strncpy:
#include
char* my_strncpy(char*dest,const char*source,size_t num)
{
char *ret = dest;
while (num && (*dest++ = *source++))//复制
num--;
if (num) //用零填充
while (--num)
*dest++ = '\0';
return ret;
}
-------------------------------------------------------------------------------------------------------------------------------
char * strncat ( char * dest, const char * source, size_t num ); strncat函数将source的初始字加上终止的null字符追加到dest终止空字符。如果在追加计数字符之前,source中出现空字符,strncat将追加source中的所有字符,直至空字符。如果num大于source的长度,则使用source的长度代替num(不足目标长度时不会补0)。结果字符串以空字符结尾。如果复制发生在重叠的字符串之间,则行为未定义。例:
模拟实现strncat:
#include
char* my_strncat(char* dest,const char* source,size_t num)
{
char *ret = dest;
while (*dest++)
{
;
}
dest--;
while (num--)
{
if (!(*dest++ = *source++))
return ret;
}
*dest = '\0';
return ret;
}
-------------------------------------------------------------------------------------------------------------------------------
int strncmp ( const char * str1, const char * str2, size_t num );
strncmp函数按ASCII比较str1和str2中的num个字符,并返回一个值,该值指示子字符串之间的关系。strncmp是_strnicmp的一个区分大小写的版本。
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字;
第一个字符串等于第二个字符串,则返回0;
第一个字符串小于第二个字符串,则返回小于0的数字;
例:
模拟实现strncmp:
int my_strncmp(const char* str1, const char* str2, size_t num)
{
assert(str1&&str2);//保证指针的有效性,使用时记得引用头文件
while (num > 0)
{
if (*str1 > *str2)
{
return *str1-*str2;//str1大于或者小于str2的时候返回他们的差值
}
else if (*str1 < *str2)
{
return *str1 - *str2;//str1大于或者小于str2的时候返回他们的差值
}
else if (*str1 == *str2)
{
str1++;
str2++;
num--;
}
else
{
str1++;
str2++;
num--;
}
}
return 0;
}
———————————————————————————————————————————
const char * strstr ( const char * str1, const char * str2 );
str2为要查找的字符串,str1为查找目的地,找到了就返回指向str1中第一个出现的str2的指针,如果str不是str1的一部分,则返回空指针。匹配过程不包括终止的空字符,但会在此停止。
例:
模拟实现strstr:
char* my_strstr(const char*str1, const char*str2)
{
assert(str1&&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++;
}
}
-------------------------------------------------------------------------------------------------------------------------------
char * strtok ( char * str, const char * sep ); sep参数是个字符串,定义了用作分隔符的字符合集,第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。 strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针(strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。) strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置。 strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多标记,则返回NULL指针。
例:
char * strerror ( int errnum ); 这个函数是把错误码转换成错误信息,每个数字都有自己的错误信息,strerror可以帮我们把信息翻译出来,使用时记得包含
例:
void perror ( const char * str );
这个函数首先把错误码转化为错误信息然后打印错误信息(包含了自定义信息)如图:
———————————————————————————————————————————
void * memcpy ( void * destination, const void * source, size_t num );
将num个字节从源指向的位置直接复制到目标指向的内存块。该函数不检查源中是否有任何终止的空字符,它总是精确复制num字节。为避免溢出,目标和源参数指向的数组大小应至少为num字节,且不应重叠(对于重叠的内存块,memmove是一种更安全的方法)
模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest&&src);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;//转化为char*比较方便
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
void * memmove ( void * destination, const void * source, size_t num ); 将num个字节从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,允许目标和源重叠。该函数不检查源中是否有任何终止的空字符-它总是精确复制num字节。为避免溢出,目标和源参数所指向的数组的大小应至少为num字节。
模拟实现:
void * memmove(void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
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;
}
void * memset ( void * ptr, int value, size_t num );
将ptr指向的内存块的首个num字节设置为value。memset() 函数常用于内存空间初始化。
如:
char str[100];
memset(str,0,100);
模拟实现:
void*my_memset(void*str, int val, size_t num)
{
assert(str);
void*p = str;
while (num--)
{
*(int*)str = val;
str = (int*)str + 1;
}
return p;
}
int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 将ptr1指向的内存块的第一个num字节与ptr2指向的第一个num字节进行比较,如果它们都匹配,则返回零;如果不匹配,则返回一个不同于零的值,ptr1
模拟实现:
int my_memcmp(const void*ptr1,const void*ptr2, size_t num)
{
assert(ptr1);//记得使用assert头文件
assert(ptr2);
while (num--)
{
if (*(char*)ptr1 == *(char*)ptr2)
{
ptr1 = (char*)ptr1 + 1;
ptr2 = (char*)ptr2 + 1;
}
else
{
if (*(char*)ptr1 > *(char*)ptr2)
{
return 1;
}
else
{
return -1;
}
}
}
return 0;
}