本章重点
重点介绍字符和字符串的库函数
strlen
函数原型
size_t strlen ( const char * str );
size_t 是 unsigned int
头文件是#include <string.h>
功能:计算字符串的长度,读到'\0'结束
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello world!";
printf("%d\n", strlen(arr));
return 0;
}
请字符串的长度,要确保字符串里有'\0',否则无法确定数值
注意字符串和字符数组的区别
char arr1[]="hello"; //默认d后面又'\0'
char arr2[]={'h','e','l'}; //这种写法就没有'\0'
char arr3[]={'h','\0'}; //这种可以,字符数组要自己添加,用strlen计算得到的是1
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "abc";
char* p2 = "abcdef";
if (strlen(p1) - strlen(p2) > 0)
{
printf("haha\n");
}
else
{
printf("hehe\n");
}
return 0;
}
strlen的返回类型是size_t,两个无符号整数相加减,不是0就是大于0的数
strlen的模拟实现的三种方法
#include <stdio.h>
#include <assert.h>
//第一种
size_t my_strlen(const char* str)
{
assert(str);
size_t count = 0;
while (*str++)
{
count++;
}
return count;
}
//第二种
size_t my_strlen(char* str)
{
if (*str++ != '\0')
return 1 + my_strlen(str);
else
return 0;
}
//第三种
size_t my_strlen(char* str)
{
assert(str);
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", my_strlen(arr));
return 0;
}
strcpy
char* strcpy(char * destination, const char * source );
将一个字符串拷贝到另一个字符串中
源字符串必须以'\0'结束
会将源字符串的'\0'也拷贝进去
目标空间要足够大,确保能放下源字符串
目标空间必须可变,不能是字符串常量
strcpy的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src); //断言,dest/src不能为空指针
char* ret = dest;
while (*dest++ = *src++) //什么时候终止呢
{ //当*src等于'\0'时,'\0'的ascii码值为0,表达式为0,条件终止
;
}
//*dest = *src;
return ret;
}
//strcpy - 返回类型是char*
//为了实现链式访问的效果
int main()
{
char arr1[20] = {0};
char arr2[] = "hello world";
printf("%s\n", my_strcpy(arr1, arr2)); //打印字符串,直接传地址
return 0;
}
strcat
//NUL和Null一般是'\0'
char * strcat ( char * destination, const char * source );
追加一个字符串
在源字符串的'\0'处开始追加,覆盖'\0'
源字符串必须'\0'结尾
目标空间足够大
目标空间必须可修改
追加的字符串必须有'\0'
不能追加本身
strcat的模拟实现
#include <assert.h>
#include <stdio.h>
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest) //找到'\0'
{
dest++;
}
while (*dest++ = *src++) //拷贝
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
printf("%s\n",my_strcat(arr1, arr2));
return 0;
}
strcmp
比较两个字符串
从第一个字符开始比较,是比较字符的ascii码值
假设字符串(s1,s2),先比较第一个字符,如果是s1大于s2,直接返回大于0的数
等于,比较下一个字符,没有字符返回0
小于,直接返回小于0的数
strcmp的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* dest, const char* src)
{
assert(dest && src);
while (*dest == *src)
{
if (*src == '\0')
return 0;
dest++;
src++;
}
return *dest - *src;
}
int main()
{
int ret = my_strcmp("aza", "azb");
printf("%d\n", ret);
return 0;
}
长度受限制的字符串函数
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
目标空间要足够大
strncat
char * strncat ( char * destination, const char * source, size_t num );
strncmp
strstr
strerror
把错误码翻译成错误信息
本机上没有test.txt这个文件,所以打印出错误信息
perror
打印错误信息,比strerror更方便
字符分段函数
isdigit
判断是不是0-9的数字,是的话
tolower
内存操作函数
memcpy
memmove
memmove模拟实现
void* my_memmove(void* dest, void* src, size_t count)
{
assert(dest && src);
if (dest < src) //从前向后移动
{
while (count--)
{
*((char*)dest)++ = *((char*)src)++;
}
}
else //从后向前移动
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 16);
return 0;
}
memcmp
memset
一个字节一个字节初始化的