目录
[1 .strlen](#1 .strlen)
[12. 字符转换函数](#12. 字符转换函数)
[1 .memcpy](#1 .memcpy)
Ⅰ、字符函数和字符串函数
1 .strlen
函数原型:
注意事项:
1.字符串以 '\0' 作为结束标志 , strlen 函数返回的是在字符串中 '\0' 前面 出现的字符个数( 不包含 '\0' ) 。
2.参数指向的字符串 必须要以 '\0' 结束 。
3.注意函数的 返回值 为 size_t ,是无符号的( 易错 )
4.学会 strlen 函数的模拟实现
模拟实现:三种方法(计数器,递归,指针-指针)
cpp
//模拟实现strlen
//方法一:计数器
size_t my_strlen1(const char* str)
{
char* st = str;
size_t count = 0;
while (*st++)
{
count++;
}
return count;
}
//方法二:递归
size_t my_strlen2(const char* str)
{
if (*str == '\0')
return 0;
return 1 + my_strlen2(++str);//注意这里不能用 后置++
}
//方法三:指针-指针
size_t my_strlen3(const char* str)
{
char* st = str;
while (*st != '\0')
{
//printf("%p\n", str);// 从小地址往大地址编址
st++;
}
return st-str;
}
2.strcpy
函数原型:
注意事项:
1.Copies the C string pointed by source into the array pointed by destination, including the
terminating null character (and stopping at that point).
2.源字符串 必须以 '\0' 结束 。
3.会将 源字符串 中的 '\0' 拷贝到 目标空间 。
4.目标 空间必须足够大 ,以确保能存放源字符串。
5.目标 空间必须可变 。
6.学会模拟实现。
模拟实现:
cpp
//模拟实现strcpy
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* cur = src; char *re = dest;
while (*dest++ = *src++);
return re;
}
3.strcat
函数原型:
注意事项:
1.Appends a copy of the source string to the destination string. The terminating null character
in destination is overwritten by the first character of source, and a null-character is included
at the end of the new string formed by the concatenation of both in destination.
2.源字符串 必须以 '\0' 结束 。
3.目标 空间 必须有 足够 的大,能容纳下源字符串的内容。
4.目标空间必须 可修改 。
5.字符串自己给自己追加,如何?不能,可能会 非法访问
模拟实现:
cpp
//模拟实现strcat
char* my_strcat(char* dest, const char* src)
{
assert(dest&&src);
char* ret = dest;
while (*dest != '\0')
dest++;
char* sr = src;
while (*dest++ = *sr++);
return ret;
}
4.strcmp
函数原型:
注意事项:
1.This function starts comparing the first character of each string. If they are equal to each
other, it continues with the following pairs until the characters differ or until a terminating
null-character is reached.
标准规定:
1.第一个字符串大于第二个字符串,则返回 大于0 的数字
2.第一个字符串等于第二个字符串,则返回 0
3.第一个字符串小于第二个字符串,则返回 小于0 的数字
模拟实现:
cpp
//模拟实现strcmp
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 < *str2)
return -1;
else
return 1;
}
5.strncpy
函数原型:
注意事项:
1.Copies the first num characters of source to destination. If the end of the source C string
(which is signaled by a null-character) is found before num characters have been copied,
destination is padded with zeros until a total of num characters have been written to it.
2.拷贝 num个字符 从 源 字符串到 目标空间 。
3.如果源字符串的长度 小于num ,则拷贝完源字符串之后,在目标的后边 追加0 ,直到 num 个
简单使用;
cpp
//使用strncpy
int main()
{
char buf[128] = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
char* str = "abcdef";
printf("%s\n", strncpy(buf, str,7 ));//没有超过就是n为多大就拷贝几个过去,
//n如果超过了字符串的长度后面就进行补 '\0'
return 0;
}
执行结果:
6.strncat
函数原型:
注意事项:
1.Appends the first num characters of source to destination, plus a terminating null-character.
2.If the length of the C string in source is less than num, only the content up to the terminating null-character is copied
3.如果 空间 不够,要报错
4.如果num比源字符串长,则紧追加 NULL之前 的字符
简单使用:
cpp
//使用strncat
int main()
{
char buf[128]="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
buf[10] = '\0'; //从第一个'\0'开始拼接
buf[20] = '\0';
char* str = "abcdef";
printf("%s", strncat(buf, str, 5));
return 0;
}
执行结果:
7.strncmp
函数原型:
注意事项:
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
简单使用:
cpp
/* strncmp example */
int main()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts("Looking for R2 astromech droids...");
for (n = 0; n < 3; n++)
if (strncmp(str[n], "R2xx", 2) == 0)
{
printf("found %s\n", str[n]);
}
return 0;
}
执行结果:
8.strstr
函数原型:
注意事项:
Returns a poin ter to the first occurrence of str2 in str1, or a null pointer if str2 is not part of
str1.
模拟实现:
cpp
//strstr的模拟实现
char* my_strstr(const char* str1, const char* str2)
{
while (*str1)
{
if (*str1 == *str2)
{
char* s1 = str1; char* s2 = str2;
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
return str1;
}
str1++;
}
}
9.strtok
函数原型:
注意事项:
1.sep 参数是个字符串,定义了用作 分隔符的字符集合
2.第一个参数指定一个字符串,它包含了 0个或者多个由sep字符串中一个或者多个分隔符 分割的标记。
3.strtok 函数 找到str中的下一个标记 ,并将其用 \0 结尾 ,返回一个指向这个 标记的指针 。
(注strtok函数会 改变被操作的字符串 ,所以在使用 strtok 函数切分的字符串一般都是 临时拷贝的内容并且可修改 。)
4.strtok 函数的 第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将 保存它在字符串中的位置 。
5.strtok 函数的 第一个参数为 NULL ,函数将在同一个字符串中被 保存的位置开始 ,查找下一个标记。
6.如果字符串中 不存在更多的标记 ,则 返回 NULL 指针 。
简单使用:
cpp
//strtok使用
int main()
{
char str[128] = "hyd@qwer.com.cn.edu.com";//注意这里必须是可修改的字符串,常量不能修改
char* sep = "@.";
char* ret = strtok(str, "@.");
printf("%s\n", ret);
while(ret=strtok(NULL,sep))
printf("%s\n", ret);
return 0;
}
执行结果:
10.strerror
函数原型:
注意事项:
返回错误码(errno),所对应的错误信息。
简单使用:
cpp
//使用strerror
int main()
{
FILE* fp = fopen("data.txt", "r");
if (fp == NULL)
{
//printf("打开失败:%s\n", strerror(errno));//打印错误信息
perror("打开失败");//类似于 printf+错误原因
}
else
printf("文件打开成功\n");
return 0;
}
执行结果:
11.字符函数
函数 如果他的参数符合下列条件就返回真(非0)
iscntrl 任何控制字符(1-31是控制字符,32-127是可打印字符)
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 任何可打印字符,包括图形字符和空白字符
12. 字符转换函数
int tolower ( int c );
int toupper ( int c );
简单使用:
cpp
/* isupper example */
#include <stdio.h>
#include <ctype.h>
int main ()
{
int i=0;
char str[]="Test String.\n";
char c;
while (str[i])
{
c=str[i];
if (isupper(c))
c=tolower(c);
putchar (c);
i++;
}
return 0;
}
执行结果:
Ⅱ、内存函数
1 .memcpy
函数原型:
注意事项:
1.函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 的内存位置。
2.这个函数在遇到 '\0' 的时候并不会停下来。
3.如果 source 和 destination 有任何的重叠,复制的结果都是未定义的。
模拟实现:
cpp
//模拟实现memcpy
char* my_memcpy(void* dest, const void* src,size_t sz)
{
assert(dest && src);
char* ret = dest;
while (sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
2.memmove
函数原型:
注意事项:
1.和 memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的。
2.如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。
模拟实现:
cpp
//char* my_memmove(void* dest, const void* src, size_t sz)
{
assert(dest && src);
char* ret = (char*)dest;
if (dest < src)
{
while(sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (sz--)
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
}
3.memcmp
函数原型:
注意事项;
1.比较从 ptr1 和 ptr2 指针开始的 num 个字节
2.返回值如下:
简单使用:
cpp
int main()
{
int arr1[] = { 1,2,3,4,5,6,7 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
//
int arr2[] = { 1,2,3,0x11223304 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 33 22 11
int ret = memcmp(arr1, arr2, 13);
printf("%d\n", ret);
return 0;
}
执行结果:0
4.memset
函数原型:
注意事项:
以字节为单位设置内存的
简单使用:
cpp
int main()
{
char arr[] = "hello world";
memset(arr+6, 'x', 3);
printf("%s\n", arr);
// int arr[10] = { 0 };
// memset(arr, 0, 40);
return 0;
}
执行结果:hello xxxld