1.求长度函数strlen
1.1模型
size_t strlen(const char* string);
1.2易错
#include <stdio.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
//u_int - u_int == u_int -3被当成无符号数
printf("str2>str1\n");//ok
else
printf("srt1>str2\n");
return 0;
}
1.3源码
size_t __cdecl strlen (const char * str )
{
const char *end = str;
while( *end++ ) ;
return end - str - 1 ;
}
1.4模拟实现
//计数器
size_t my_strlen(const char* str)
{
assert(str);
size_t count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
//函数递归
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
//指针
size_t my_strlen(const char* str)
{
const char* end = str;
while (*end++);
return end - str - 1;
}
2.拷贝函数strcpy
2.1模型
char* strcpy(char * des, const char * src );
2.2注意
源字符串以 '\0' 结束。
源字符串中 '\0' 拷贝到目标地址。
目标空间足够大能存放源字符串。
目标空间可变。
2.3模拟实现
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest && src);
while(*dest++ = *src++);
while(*src!='\0')
*dest++=*src++;
*dest=*src;
return ret;
}
3.比较函数strcmp
3.1模型
int strcmp ( const char * str1, const char * str2 );
3.2注意
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
3.3源码
int __cdecl strcmp (const char * src,const char * dst )
{
int ret = 0 ;
while((ret = *(u_char *)src - *(u_char *)dst) == 0 && *dst)
++src, ++dst;
return ( (-ret) < 0 ) - (ret < 0);
}
3.4模拟实现
int my_strcmp (const char * src, const char * dst)
{
assert(dest && src);
While (*s1 == *s2 )
{
if (*s1 == '\0')
return 0;
s1++ ;
s2++ ;
}
return *s1 -*s2;
}
4.追加函数strcat
4.1模型
char * strcat ( char * dest, const char * src );
4.2用途
源字符串以 '\0' 结束。
目标空间能容纳下源字符串。
目标空间可修改。
4.3源码
char * strcat (char * dst,const char * src)
{
char * cp = dst;
while( *cp )
cp++;
while((*cp++ = *src++) != '\0') ;
return dst ;
}
4.4模拟实现
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest && src);
while(*dest)
dest++;
while((*dest++ = *src++))
{
;
}
return ret;
}
5.查重函数strstr
5.1模型
char * strstr ( const char *str1, const char * str2);
5.2用途
![](https://img-blog.csdnimg.cn/img_convert/b117a37d552e4bca9f79243366f90bd1.png)
5.3源码
char*strstr(const char* str1,const char *str2)
{
char* cp = (char*)str1;
char* s1,*s2;
if (!*str2)
return (char*)str1;
while (*cp)
{
s1 = cp;
s2 = (char*)str2;
while (*s2 && *s1 ==*s2)
s1++,s2++;
if (!*s2)
return(cp);
cp++;
}
return NULL;
}
5.4模拟实现
char * strstr (const char * str1, const char * str2)
{
const char *s1, *s2;
if ( !*str2 )
return (char *)str1;
while (*str1)
{
s1 = str1;//更新
s2 = str2;//回归原位
while ( *s1 && *s2 && *s1==*s2 )
s1++, s2++;
if (!*s2)//*s2=='\0'
return (char*)str1;
str1++;//str1记录首个字符相同的地址
}
return NULL;
6.切割函数strtok
6.1模型
char * strtok ( char * str, const char * sep );
6.2注意
sep指向用作分隔符的字符集合
str指向一个含1个或多个sep指向字符串中分隔符的字符串。
函数找到一个标记,将其用 \0 结尾,返回指向这个标记的指针。
注:函数会改变被操作的字符串,使用strtok切分的字符串一般是临时拷贝且可修改。
str不为 NULL 时,函数找到第一个标记,保存它在字符串中的位置。
str为 NULL时 ,函数在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在标记,返回 NULL 指针。
6.3用途
![](https://img-blog.csdnimg.cn/img_convert/966ab2e31a2b424e82b0dd6b9ee7db39.png)
6.4模拟实现
char* my_strtok(char* str, const char* dmt)
{ //delimiters分隔符
static char* p = NULL;//静变记录每个字符串的首地址
if (str != NULL) //首次传参,p=str;之后p为上次调用后的p
p = str;
char Dmt[256] = { 0 };
while (*dmt) //含有分隔符的元素置1,其余为0
Dmt[*dmt++] = 1;
char* ret = *p ? p : NULL;
//最后一个字符串得到后,p指向整个字符串的\0
//再次调用,ret返回NULL,调用结束,主函数for循环也结束
while (*p && Dmt[*p] == 0)
p++; //没有遇到dmt前p++
if (*p) //因为遇到dmt循环结束,将其置\0
*p++ = '\0';
return ret;
}
int main()
{
char a[] = "aaa#bbb@ccc", t[30] = { 0 };
char* s = "#@", * p = NULL;
strcpy(t, a);
for (p = my_strtok(t, s); p != NULL; p = my_strtok(NULL, s))
printf("%s\n",p);
return 0;
}
7.strerror
7.1模型
#include<errno.h>
char * strerror ( int errnum );
7.2用途
使用库函数,调用失败时,将错误码放于全局变量int errno;
strerror会将errno翻译成对应错误信息
int main()
{
FILE* pf = fopen("test. txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//No such file or directory
}
fclose(pf);
pf = NULL;
return 0;
}
7.3perror函数
#include<stdio.h>
void perror( const char *string );
int main()
{
FILE* pf = fopen("test. txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
perror("results");
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
打印结果:
![](https://img-blog.csdnimg.cn/img_convert/1bf4982997c04e00b5499ab91544f2e1.png)
8.strncpy
8.1模型
char* strncpy ( char* dest,const char* src,size_t num );
8.2用途
拷贝num个字符从源字符串到目标空间。
当num>src长度时,仍拷贝n个字符(src中没有的拷贝\0)
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标后追加0,直到num个。
8.3模拟实现
char* my_strncpy(char* dest, const char* src, size_t n)
{
char* ret = dest;
while (n--)
*dest++ = *src++;
*dest = '\0';
return ret;
}
int main()
{
char a[] = "aaaaaa";
char b[] = "bbb";
my_strncpy(a, b, 3);
printf("%s", a);
return 0;
}
9.strncmp
9.1模型
int strncmp ( const char* str1, const char* str2, size_t num );
9.2调用结束
出现字符不一样
字符串结束
num个字符比较完
9.3用途
int main()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
for (int n = 0; n < 3; n++)
{
if (strncmp(str[n], "R2xx", 2) == 0)
printf("found %s\n", str[n]);
}
return 0;
}
//输出
found R2D2
found R2A6
10.strncat
10.1模型
char* strncat ( char* dest, const char* src, size_t num )
10.2源码
char* my_strncat(char* p,const char* q,size_t n)
{
char* ret = p;
while (*p++);
p--;
while (n--)
{
if ((*p++ = *q++) == 0)
return ret;
}
*p = '\0';
return ret;
}
10.3模拟实现
char* my_strncat(char* p, const char* q, size_t n)
{
char* ret = p;
while (*p++);
p--;
while (n--)
{
if ((*p++ = *q++) == 0)
return ret;
}
*p = '\0';
return ret;
}
int main()
{
char str1[20];
char str2[20];
strcpy(str1, "To be ");
strcpy(str2, "or not to be");
my_strncat(str1, str2, 6);
puts(str1);
return 0;
}
11.各类字符函数
11.1函数 如果参数符合条件返回真
iscntrl 控制字符
isspace 空白字符:‘ ’‘\f’'\n'‘\r’,'\t' '\v'
isdigit 十进制 0~9
isxdigit 十六进制数字,十进制数字,小写字母a~f,大写字母A~F
islower 小写a~z
isupper 大写A~Z
isalpha a~z或A~Z
isalnum 字母或数字,a~z,A~Z,0~9
ispunct 标点符号,不属于数字或字母的可打印字符
isgraph 图形字符
isprint 可打印字符,图形字符和空白字符
11.2字符转换函数
int tolower ( int c );
int toupper ( int c );