#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<assert.h>
//字符函数
//int main()
//{
// int ret = islower('a');//如果是小写字母返回非零的值,其他返回0
// printf("%d\n", ret);
// return 0;
//}
//写一个代码,将字符串中的小写字母转大写,其他字符不变 'a'->97 'A'->65
//int main()
//{
// char str[] = "i am A Student";//1.遍历字符串2.发现小写字母转大写
// size_t len = strlen(str);
// size_t i = 0;
// for (i = 0; i < len; i++)
// {
// if (islower(str[i]))
// {
// //str[i] = str[i] - 32;
// str[i] = toupper(str[i]);
// }
// }
// printf("%s\n", str);
// return 0;
//}
//也可以使用函数toupper
//int main()
//{
// int ch = 0;
// scanf("%c", &ch);
// //ch = ch + 32;//大写转小写
// ch = tolower(ch);//与上一行效果相等
// printf("%c\n", ch);
// return 0;
//}
//下面是字符串函数
//1.strlen:求字符串长度函数
//
//下边三个函数不受长度限制,有可能产生安全问题。
//2.strcpy:字符串拷贝函数
//3.strcat函数:字符串追加
//4.strcmp函数:比较两个字符串大小
//
//下边三个是长度受限制的函数
//5.strncpy 6.strncat 7.strncmp
//
//8.strtok函数:按指定分隔符分割字符
//9.strstr函数:在字符串中查找另一个字符串,返回str2在str1中第一次出现的位置,如果没有出现,返回空指针
//10.strerror函数:返回一个错误码所对应的错误信息字符串的起始地址 const char * strerror(int i)
//strlen函数
//int main()
//{
// char arr[] = "abcdef";
// //a b c d e f \0
// size_t len = strlen(arr);
// printf("%zd\n", len);
// return 0;
// //1.strlen函数要正确获得字符串长度的话,字符串中必须要有\0
//}
//2.strlen函数的返回值是size_t,也就是无符号整型
//int main()
//{
// if (strlen("sbc") - strlen("ancdef") > 0)//两个无符号数相减结果为无符号数 -3会变为一个及其大的数,可以前边加上(int)进行强制类型转换
// printf(">\n");
// else
// printf("<=\n");
// //结果为>
// return 0;
//}
//strlen函数的模拟实现
//仿照strlen函数的参数,返回类型,功能写一个类似的函数
第一种实现方式:计数器方式
//size_t my_strlen1(const char * str)
//{
// int count = 0;
// assert(str != NULL);
// while(*str != '\0')
// {
// count++;
// str++;
// }
// return count;
//}
第二种实现方式:指针-指针--->地址-地址
得到的是指针和指针之间元素的个数
//size_t my_strlen2(const char*str)
//{
// const char* start = str;
// while (*str != '\0')
// {
// str++;
// }
// return str - start;
//}
第三种方法:不能使用临时变量(递归)
//size_t my_strlen3(const char*str)
//{
// if (*str != '\0')
// return 1 + my_strlen3(str + 1);
// else
// return 0;
//}
//int main()
//{
// char arr[] = "abcdef";
// size_t len = my_strlen1(arr);
// size_t len = my_strlen2(arr);
// size_t len = my_strlen3(arr);
// printf("%zd\n", len);
// return 0;
//}
//strcpy函数
//1.源字符串必须包含'\0',会将源字符串中的 '\0' 拷⻉到⽬标空间。拷贝到'\0'处停止拷贝
//2.要保证目标空间要足够大,能放得下拷贝来的数据
//3.保证目标空间必须可以修改(常量字符串不可被修改)
//int main()
//{
// char arr1[] = "abcdef";
// char arr2[20] = "xxxxxxxx";//不给出数组长度时根据数组元素个数定义长度
// strcpy(arr2, arr1);//将字符串arr1拷贝到arr2中
// printf("%s\n", arr2);
// return 0;
//}
//模拟实现strcpy函数
//版本1
//void my_strcpy(char* dest, char* src)
//{
// while (*src != '\0')//拷贝\0之前的字符
// {
// *dest = *src;
// dest++;
// src++;
// }
// //拷贝\0
// *dest = *src;
//}
//版本2
//void my_strcpy(char* dest, char* src)
//{
// while (*dest++ = *src++)
// {
// ;
// }
//}
//版本3
//void my_strcpy(char* dest, char* src)
//{
// assert(dest);
// assert(src);
// while (*dest++ = *src++)
// {
// ;
// }
//}
//版本4
//dest指向的空间是需要改变的,但是src指向的空间是不期望被改变的
//void my_strcpy(char* dest, const char* src)
//{
// assert(dest && src);
// while (*dest++ = *src++)
// {
// ;
// }
//}
//版本5
//返回目标空间的起始地址
//char* my_strcpy(char* dest, const char* src)
//{
// char* ret = dest;
// assert(dest && src);
// while (*dest++ = *src++)
// {
// ;
// }
// return ret;
//}
//int main()
//{
// char arr1[] = "abcdef";
// char arr2[20] = { 0 };
// my_strcpy(arr2, arr1);
// printf("%s\n", arr2);
// printf("%s\n", my_strcpy(arr2, arr1));//只有版本5能这么用
// return 0;
//}
//strcat函数:字符串追加
//1.目标空间中要有'\0'(从哪里开始追加),源头字符串中得有'\0'(追加到什么时候结束)
//2.目标空间要足够大,目标要可以修改
//int main()
//{
// char arr1[20] = "hello ";
// char* p = "world";
// strcat(arr1, p);
// printf("%s\n", arr1);
// return 0;
//}
//模拟实现strcat
//char *my_strcat(char *dest,const char*src)//返回目标空间的起始地址
//{
// char* ret = dest;
// assert(dest && src);
// //1.找到目标空间中的\0
// while (*dest != '\0')
// {
// dest++;
// }
// //2.拷贝数据
// while (*dest++ = *src++)
// {
// ;
// }
// return ret;
//}
//int main()
//{
// char arr1[20] = "hello ";
// char* p = "world";
// my_strcat(arr1, p);
// printf("%s\n", arr1);
// printf("%s\n", my_strcat(arr1, p));
// printf("%s\n", my_strcat(arr1, arr1));//这样不行,dest指向的\0被修改成a,...,src永远不会指向\0,程序不会停止,会陷入死循环。
// //想实现字符串自己追加自己可以使用strncat函数
// return 0;
//}
//strcmp函数:用来比较两个字符串大小(按字典序比较)(按位依次比较)
//前<后,返回小于零的数
//前>后,返回大于零的数
//前==后,返回0
//int main()
//{
// int ret = strcmp("abcdef", "abq");
// printf("%d\n", ret);//返回-1
// return 0;
//}
//模拟实现strcpy函数
//int my_strcmp(const char* s1, const char* s2)
//{
// assert(s1 != NULL);
// assert(s2 != NULL);
// while (*s1 == *s2)
// {
// if (*s1 == '\0')
// {
// return 0;
// }
// s1++;
// s2++;
// }
// //1.if (*s1 > *s2)
// // return 1;
// // else
// // return -1;
// //2.return *s1 - *s2;
//}
//int main()
//{
// int ret = my_strcmp("abcdef", "abc");
// printf("%d\n", ret);
// return 0;
//}
//strncpy函数 strncat函数和strncmp函数同理
//int main()
//{
// char arr1[10] = "xxxxxxxx";
// char arr2[] = "ab";
// strncpy(arr1, arr2, 5);
// printf("%s\n", arr1);
// return 0;
//}
//strtok函数:返回类型为char* char * strtok(char *str,const char * sep)
//strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。
//注意:strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷⻉的内容并且可修改。
//strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。
//strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。
//如果字符串中不存在更多的标记,则返回 NULL 指针。
//int main()
//{
// char arr[] = "zpengwei@yeah.net";//@ 和.称为分隔符
// char buf[30] = { 0 };
// strcpy(buf, arr);
// char* p = "@.";
// char * s = strtok(buf, p);
// printf("%s\n", s);//打印出来的是zpengwei
//
// s = strtok(NULL, p);
// printf("%s\n", s);//yeah
//
// s = strtok(NULL, p);
// printf("%s\n", s);//net
//
// return 0;
//
// }
//以上只是举例子,下面是正常写法
//int main()
//{
// char arr[] = "zpengwei@yeah.net@xxxx.yyyy.zzzz";
// char buf[60] = { 0 };
// strcpy(buf, arr);
// char* p = "@.";
// char* r = NULL;
// for (r = strtok(buf, p); r != NULL; r = strtok(NULL, p))
// {
// printf("%s\n", r);
// }
// return 0;
//}
//strstr函数:在字符串中查找另一个字符串,返回str2在str1中第一次出现的位置,如果没有出现,返回空指针
//int main()
//{
// char arr1[] = "abcdefabcdef";
// char arr2[] = "def";
// char * ret = strstr(arr1, arr2);
// if (ret != NULL)
// {
// printf("%s\n", ret);//打印出defabcdef
// }
// else
// printf("找不到\n");
// return 0;
//}
//模拟实现strstr函数
//const char* my_strstr(const char* str1, const char* str2)
//{
// assert(str1);
// assert(str2);
// const char* cp = str1;
// const char* s1 = str1;
// const char* s2 = str2;
// if (*str2 == '\0')//如果子串是空字符串,直接返回str1
// return str1;
// while (*cp)
// {
// s1 = cp;
// s2 = str2;
// while (*s1 == *s2 && *s1 & *s2)
// {
// s1++;
// s2++;
//
// }
// if (*s2 == '\0')
// return cp;
// cp++;
// }
// return NULL;
//}
//int main()
//{
// char arr1[] = "abcdefabcdef";
// char arr2[] = "def";
// char * ret = my_strstr(arr1, arr2);
// if (ret != NULL)
// {
// printf("%s\n", ret);//打印出defabcdef
// }
// else
// printf("找不到\n");
// return 0;
//}
//strerror函数:返回一个错误码所对应的错误信息字符串的起始地址 const char * strerror(int i)
//int main()
//{
// int i = 0;
// for (i = 0; i < 10; i++)
// {
// char* ret = strerror(i);
// printf("%d,%s\n", i, ret);
// }
// return 0;
//}
//当库函数调用失败时,会将错误码记录到errno这个变量中
//errno是一个c语言的全局变量