头文件是#include
下面是函数的使用条件,有x的就代表只要符合体条件就返回真
我们以islower为例写一段代码实现一下功能:将小写字符改成大写字符
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main() {
int i = 0;
char arr[20] = { "aJsfjsJsfH" };
while (arr[i] != '\0') {
if (islower(arr[i]))
arr[i] -= 32;
i++;
}
printf("%s", arr);
return 0;
}
我们以tolower为例用代码实现将大写字符转化为小写字符
#include
#include
int main() {
char a = 'H'; //我们将h字符放在a里面
char b = tolower(a); //我们将小写h转换为大写H后放入b里面
printf("%c", b);
return 0;
}
函数原型
size_t strlen ( const char * str );
头文件:
#include
#include
int main() {
if (strlen("abc")-strlen("abcde")>0)
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
很多人会以为会打印出<=其实不然,由于strlen的返回值是无符号整型,无符号整型-无符号整型的结果也会是无符号整型。所以应该是打印出>号。(有符号减无符号结果也是无符号)
前面我们用计数器的方式,和指针减指针的方式模拟过strlen,下面我们用递归的方式来模拟
#include
size_t mystrlen(const char *str)
{
if (*str!='\0')
{
return 1 + mystrlen(str+1);
}
else
{
return 0;
}
}
int main() {
char arr[] = { "asjkldjgl" };
size_t lenght = mystrlen(arr);
printf("%zu", lenght);
return 0;
}
函数原型
char * strcpy ( char * destination, const char * source );
头文件:
作用是将source指向的字符复制到destination指向的数组中,包括终止字符\0。
注意事项:
1.源字符串必须以‘\0’结束
2.将源字符串中的‘\0’拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可修改。(就像常量字符串,不能修改或者是用const限定的)。
#include
#include
int main() {
char arrs[] = { "hasdfklj" };
char arrd[20] = {};
strcpy(arrd, arrs);
printf("%s", arrd);
return 0;
}
现在我们来模拟实现strcpy
#include
char my_strcpy(char* p1, const char* p2) {
do
{
*p1 =* p2;
p1++;
p2++;
} while (*p2!='\0');
*p1 = *p2;
return 0;
}
int main() {
char arrs[10] = { "hasdfklj" };
char arrd[10] = {};
my_strcpy(arrd, arrs);
printf("%s", arrd);
return 0;
}
其实还能将这段代码进行化简(加升级改造)
#include
#include
char* my_strcpy(char* p1,const char* p2) {
char*p=p1; //之所以要在创一个新指针将p1的首地址复制给它,那是因为经过循环后的p1指向的不是首地址,这会对我们模拟实现返回时要返回char*造成影响
assert(p1&&p2); //作用是避免指针为空指针
do
{ //后置++先运算后赋值
} while (*p1++ =* p2++); //这个执行原理其实和上面的一样,从第一个开始一个一个往后赋值,当赋值到\0时,它的ascll码值为0,所以退出循环
*p1 = *p2;
return p1; //由于是模拟实现strcpy的返回类型是char*
}
int main() {
char arrs[10] = { "hasdfklj" };
char arrd[10] = {};
my_strcpy(arrd, arrs);
printf("%s", arrd);
return 0;
}
函数原型
char * strcat ( char * destination, const char * source );
头文件:
作用是将源字符串的副本附加到目标字符串,destination中终止的\0字符被source中的第一个字符覆盖,并且\0字符包含在destination中由两者串联形成的新字符串的末尾。
#include
#include
int main() {
char arr1[20] = { "aakld" };
char arr2[20] = { "asskj"};
strcat(arr1, arr2);
printf("%s", arr1);
return 0;
}
注意事项:
1.源字符串必须以‘\0’结束
2.将源字符串中的‘\0’拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可修改。(就像常量字符串,不能修改或者是用const限定的)。
下面模拟实现strcat(我们自己写的strcat无法实现自己给自己追加字符,但是strcat可以(有风险))
#include
#include
void my_strcat(char* p1, const char* p2) {
assert(p1&&p2);
while (*p1) {
p1++;
}
while (*p2) {
*p1++ = *p2++;
}
*p1 = '\0';
}
int main() {
char arrd[30] = "hasdfklj";
char arrs[15] = "sdseds";
my_strcat(arrd, arrs);
printf("%s\n", arrd);
return 0;
}
函数原型
int strcmp ( const char * str1, const char * str2 );
头文件
作用是将字符串str1和str2进行比较,从第一个字符开始,比较他们的ascll码值,如果相等,则继续处理,直到字符不同,或到\0为止
#include
#include
int main() {
char arr1[] = { "asdslfkj" };
char arr2[] = { "asdeiwl" };
int r = strcmp(arr1, arr2); //要注意strcmp在vs环境中返回的值是1,-1,0,但是在其他环境中返回的值可能不是,所以判断条件一定要按照下面来写,而不是写成r==1,r==-1
if (r>0)
{
printf("arr1中字符的ascll码值大于arr2");
}
else if (r<0)
{
printf("arr1中字符的ascll码值小于arr2");
}
else if(r==0)
{
printf("arr1中字符的ascll码值等于arr2");
}
return 0;
}
现在我们用代码来实现自己的strcmp函数
#include
#include
int my_strcmp(const char* p1,const char* p2) {
assert(p1&&p2);
while (*p1++ == *p2++)
{
if (*p1 == '\0' && *p2 == '\0') //这个条件非常重要,如果两串字符串完全相同比完\0之后回一直比下去。直到出现不同的为止
return 0;
}
}
if (*p1 > *p2)
{
return 1;
}
else if (*p1 < *p2)
{
return -1;
}
}
int main() {
char arr1[] = { "asdf" };
char arr2[] = { "asdf" };
int r = my_strcmp(arr1, arr2);
if (r > 0)
{
printf("arr1中字符的ascll码值大于arr2");
}
else if (r < 0)
{
printf("arr1中字符的ascll码值小于arr2");
}
else if (r == 0)
{
printf("arr1中字符的ascll码值等于arr2");
}
return 0;
}
函数原型:
char * strncpy ( char * destination, const char * source, size_t num );
头文件
将源字符串的num个字符复制到目标字符串中,如果复制num个字符之前遇到源字符串的结束符,则用0填充目标字符串(这里的用0填充的意思是将\0换成0,防止在复制时遇到\0停止。而不是在复制完成后将源字符串原本是\0的地方用0填充),直到总共写入num个字符。(如果源字符串的长度大于num,则不会在目标字符串的末尾添加\0,这种情况下读取目标字符串可能会导致越界)
下面只演示越界的情况
#include
#include
int main() {
char dest[8] = { "xxxxx" };
char sour[20] = { "lsdkjflsdj" };
printf("%s", strncpy(dest, sour,8)); //这里就是源字符串大于num,在复制给目标字符串时无法给目标字符串填充\0。
return 0;
}
函数原型:
char * strncat ( char * destination, const char * source, size_t num );
头文件
从源字符串中最多复制num个字符串到目标字符串的末尾,过程中函数会先找到目标字符串的末尾(也就是\0所在的位置),然后从源字符串中复制最多num个字符串的末尾,覆盖原来的目标字符串的\0,最后,会在追加后的字符串末尾添加\0。
#include
#include
int main() {
char dest[14] = { "xxxxx" };
char sour[20] = { "lsdkjflsdj" };
printf("%s", strncat(dest, sour,8));
return 0;
return 0;
}
函数原型:
int strncmp ( const char * str1, const char * str2, size_t num );
头文件
strncmp函数会逐个字符比较str1和str2的前n个字符,直到出现以下情况
比较了n个字符
遇到了不同字符
其中一个字符串遇到了\0
代码实例就省略了
函数原型:
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
头文件
strstr函数会在str1中查找str2子字符串首次出现的位置。它会从str1的开头开始逐字符地进行比较,直到找到与str2完全匹配的子字符串,或者达到str1结尾结束。
指向 str2 中指定的整个字符序列在 str1 中首次出现的指针,如果 str1 中不存在该序列,则指向 null 指针。
注意
str1指向要被搜索的主字符串的指针,该字符串需要是以\0结尾的有效字符串。
str2指向要搜索的子字符串的指针,同样需要是以\0结尾的有效字符串。
#include
#include
int main()
{
char arr1[30] = { "how are you,i'm fine thankyou" };
char arr2[10] = { "fine" };
char* p = strstr(arr1, arr2);
if (p==NULL)
{
printf("找不到");
}
else
{
printf("找到了");
}
return 0;
}
下面我们来进行模拟strstr实现
#include
#include
char* my_strstr(const char* str1,const char* str2) {
assert(str1&&str2);
if (*str2=='\0')
{
return str1;
}
while (*str1)
{
char* p1 = str1; //这里设置p1p2,是为了防止在查找字符时轻易改变str1str2,各自的初始位置,同时在最外层进行一次循环后将str2的首地址赋值给p2,str1++后的地址赋值给p1
char* p2 = str2;
while (*p1&&*p2&&*p1==*p2) //情况1;如果其中p1p2有一个字符串已经历遍或者同时历遍,则跳出循环
{ //情况2:如果p1p2一直相等直到p2历遍找到\0,也跳出循环
p1++;
p2++;
}
if (*p2=='\0') //找到了
{
return str1;
}
str1++; //在最外层循环中,作用是用str1中的第一个字符与str2中第一个字符比较,如果不同,则str1++,用第2个与str2第一个来比较,直到找到为止(或找不到)
}
return NULL;
}
int main()
{
char arr1[40] = { "this is a sample string" };
char arr2[10] = { "sample" };
char* result = my_strstr(arr1,arr2);
if (result!=NULL)
{
printf("子字符串 '%s' 在主字符串中首次出现的位置是: %#X\n", arr2, result);
}
else
{
printf("未在主字符串中找到子字符串 '%s'\n",arr2);
}
return 0;
}
函数原型:
char * strtok(char* str,const char* sep);
头文件
sep参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,塔波扩了0个或多个由sep字符串中一个或多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以被strtok函数分割的字符串一般都是临时拷贝的内容并且可修改)
strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多标记,则返回NULL指针
#include
#include
int main()
{
char str[] = { "192.168.023.431" };
char cpy[50] = { 0 }; //这个就是要分割的临时拷贝
strcpy(cpy, str);
char sep[] = { "." };
char* r = strtok(cpy,sep);
for (r;r!=NULL;r=strtok(NULL,sep))
{
printf("%s\n", r);
}
return 0;
}
函数原型:
char * strerror ( int errnum );
头文件
strerror函数可以把参数部分错误码对应的u从无信息字符串地址返回来
在不同系统中C语言标准库的实现中规定了一些错误码,一般是放在error.h这个头文件中说明的,C语言程序启动的时候就会使用一个全局的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库的时候发生了某种错误,就会将对应的错误码,存放在errno中,而一个错误码的数字是整数,很难理解是什么意思,所以每一个错误码都是有对应的错误信息的,strerror函数就可以将错误的对应信息字符串的地址返回。
#include
#include
#include //这个头文件的作用是调用错误信息库
int main() {
FILE* pf = fopen("test.txt", "r"); //以读的形式打开test.txt文件,如果文件不存在,则打开失败
if (pf==NULL)
{
printf("错误信息是: %s", strerror(errno)); //这里的strerror的作用就是返回错误信息的字符串首地址
}
return 0;
}
拓展:
其实还可以用perror函数(就不用strerror函数了)
函数原型:
void perror(const char *s);
perror 函数会根据全局变量 errno 的值,将对应的错误信息输出到标准错误流。errno 是一个整数类型的全局变量,当系统调用或库函数执行出错时,会将相应的错误号赋值给 errno。perror 函数会将 s(如果不为 NULL)和错误信息一起输出,格式为:s: 错误信息。
#include
#include
#include //这个头文件的作用是调用错误信息库
int main() {
FILE* pf = fopen("test.txt", "r"); //以读的形式打开test.txt文件,如果文件不存在,则打开失败
if (pf==NULL)
{
perror("错误信息是"); //这个括号内如果不填字符则会直接输出错误信息
}
return 0;
}