strtok函数
char * strtok ( char * str, const char * sep );(字符串切割函数)
sep 参数是个字符串,定义了用作分隔符的字符集合, sep中放分隔符
第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的标记。 第一个参数是待切割的字符串,里面可有分隔符,也可以没有
strtok 函数找到 str 中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。 找到分割符后,将分隔符变为\0,并且返回a这个位置
(注: strtok函数会改变被操作的字符串,所以在使用strtok 函数切分的字符串一般都是临时拷贝的内容 并且可修改。) 使用strtok进行切割时,最好临时拷贝一份,不要破坏原数据
strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将保存它在字符串 中的位置。 当地一个参数不为NULL时,找到第一个标记(上面标记为@),并把它变为\0,同时它会保存这个分隔符的位置,然后返回a的地址
strtok 函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。 当记住上面的位置之后,下一次寻找分隔符,将会从上面所记住的位置开始找,也就是说传参的时候在找到第一个分隔符之前传参要穿地址,找到第一个分隔符之后传参就要传空指针
如果字符串中不存在更多的标记,则返回 NULL 指针, 没有标记时就返回空指针
#include<stdio.h> #include<string.h> int main() { char a[] = "123@456#789"; char b[] = "@#"; char* ret = strtok(a, b); printf("%s\n", ret); ret = strtok(NULL, b); printf("%s\n", ret); ret = strtok(NULL, b);//第三次找到末尾\0,也会停下来 printf("%s\n", ret); return 0; }
当俩个分隔符挨着的时候,程序获取不到任何东西,它会直接跳过第二个分隔符
sterror函数
char * strerror ( int errnum );
errnum 错误码,
C语言中程序执行失败的时候,都会返回一个错误码,sterror是来查看错误码的具体含义的
#include<stdio.h> #include<string.h> #include<errno.h> int main() { //errno:全局错误码存放的全局变量 FILE *pf=fopen("test.txt", "r"); if (pf == NULL) { printf("%s", strerror(errno)); return 1; } return 0; }
字符分类函数
memcpy函数
void * memcpy ( void * destination, const void * source, size_t num );
内存拷贝函数,将源内容拷贝到目标内容中区,并可以设置所拷贝的字节大小,参数为void *,返回目标的起始地址 ,是为了使这个函数具有通用性,void *不能直接解引用,也不能直接进行指针相减
模拟实现memcpy函数
void* my_memcpy(void* a,const void* b, size_t s) { assert(a && b); void* ret = a; while (s--) { *(char*)a = *(char*)b; a=(char*)a+1; b=(char*)b+1; } return ret; } int main() { int arr1[] = { 1,23,54,165,56,1,51,65 }; int arr2[] = { 165,195 }; my_memcpy(arr1, arr2, 8); for (int i = 0; i < 8; i++) printf("%d ", arr1[i]); return 0; }
这里最好采用a=(char*)a+1,这个写法比较通用,当写成(char *)a++之后,这个在有些编译器上跑不过去
memcpy无法实现通过自我拷贝,改变自身的值,因为:这是arr1,将它的值传给arr1+2,arr1每传一个数,原数据就会被改变一次,这里arr1走了四次,原数据就被改变了四次,然后接着赋值
我们用memcpy函数却能实现,自我拷贝,这里不是我们的模拟函数有问题,而是memcpy函数不用来处理重叠的内存数据处理,应该使用memmove,只不过这里的memcpy能力比较强,完成了memmove应该做的事情
memmove函数
void * memmove ( void * destination, const void * source, size_t num );
跟memcpy参数一样,返回值为目标首地址
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,23,54,165,56,1,51,65 }; int arr2[] = { 165,195 }; memmove(arr1 + 2, arr1, 12); for (int i = 0; i < 8; i++) printf("%d ", arr1[i]); return 0; }
模拟实现memmove
当dest<src时,应该从4开始往后拷贝,即从前向后拷
当两块位置没什么关联的时候,从4-8拷贝或者从8-4拷贝都可以
当dest>src时,应该从8-4进行拷贝,即从后向前拷贝
#include<stdio.h> #include<string.h> #include<assert.h> void* my_memmove(void* des, const void* src, size_t num) { assert(des && src); char* ret = des; if (des < src) { while (num--) { *(char*)des = *(char*)src; des = (char*)des + 1; src = (char*)src + 1; } } else { while (num--) { *((char*)des + num) = *((char*)src + num); } } return ret; } int main() { int arr1[] = { 1,23,54,165,56,1,51,65 }; int arr2[] = { 165,195 }; my_memmove(arr1+2, arr1, 12); for (int i = 0; i < 8; i++) printf("%d ", arr1[i]); return 0; }
memcmp函数
int memcmp ( const void * ptr1,const void * ptr2,size_t num );
依旧比较的时ASCII码,num是要比较的字节数大小
比较方法跟strcmp一样。只不过这里是一个字节一个字节进行比较
memset函数
void *memset( void *dest, int c, size_t count );
返回值是目标首地址 ,给目标地址设置值,值的具体内容在参数里是int c,size_t是要设置的字节数,中间的int参数可以是字符也可以是整数,因为都是以ASCII码形式存储的
这个函数是以字节为单位的,这里将每个字节都改为了1
习题1
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
方法一
int is_left_move(char* arr1, char* arr2) { int str = strlen(arr1); int i = 0, j = 0; for (i = 0; i < str; i++) { char tmp = arr1[0]; for (j = 0; j < str - 1; j++) { arr1[j] = arr1[j + 1]; } arr1[j] = tmp; if (strcmp(arr1, arr2) == 0) return 1; } return 0; } int main() { char arr1[] = "abcdef"; char arr2[] = "bcdefa"; int z=is_left_move(arr1, arr2); if (z == 1) printf("是"); else printf("否"); return 0; }
方法二
int is_left_move(char* arr1, char* arr2) { int str1 = strlen(arr1); int str2 = strlen(arr2); if (str1!=str2) return 0; strncat(arr1, arr1, str1); char* ret = strstr(arr1, arr2); if (ret == NULL) return 0; else return 1; } int main() { char arr1[20] = "abcdef"; char arr2[] = "bcdefa"; int z=is_left_move(arr1, arr2); if (z == 1) printf("是"); else printf("否"); return 0; }
将所有的可能性都加进去,然后判断,采用这种方法注意arr1的空间必须足够大,而且可变