字符函数和字符串函数

字符函数和字符串函数

字符函数

下面介绍的函数均包含在头文件 <ctype.h>

字符分类函数

字符分类函数帮你判断一个字符是否是某个类型

我们举几个常见的字符分类函数:

  • 判断字符是否是小写字母
int islower(int c);

如果字符是小写字母,函数返回一个非零的整数;如果字符不是小写字母,返回0

例如:

#include <stdio.h>
#include <ctype.h>
int main()
{
    char c[] = {'g','2','S','!','\0'};
    int len = sizeof(c) / sizeof(c[0]);
    for(int i = 0; i < len - 1; i++)
    {
        int ret = islower(c[i]);
        if(ret)
        {
            printf("%c是小写字母\n",c[i]);
        }
        else
        {
            printf("%c不是小写字母\n",c[i]);
        }
    }
    return 0;
}
//打印结果是:
g是小写字母
2不是小写字母
S不是小写字母
!不是小写字母

字符分类函数的返回逻辑都是这样,判断为是,返回非0整数;判断不是,返回0。

在这里插入图片描述

字符转换函数

C提供了2个字符转换函数:字母大小写转换

int tolower(int c);//转换为小写
int toupper(int c);//转换为大写

以tolower为例,当我们传入的参数不是大写的字母时,返回值是原字符,不会做出任何改变;如果参数是大写的字母,则会返回它的小写字母。

#include <stdio.h>
#include <ctype.h>
int main()
{
    char a[] = "Hello FrIenDs";
    char c = 0;
    int i = 0;
    while(a[i])
    {
        c = toupper(a[i]);
        printf("%c",c);
        i++;
    }
    return 0;
}
//打印结果是:
HELLO FRIENDS

字符串函数

需要包含头文件 <string.h>

strlen

计算字符串长度

size_t strlen(const char* str);
  • 计算的是\0之前的字符的个数(不包含\0)。

  • 参数str指向的字符串必须以\0结束。

  • 返回类型是size_t类型,是无符号整数类型,因为一个字符串的长度不可能为负数。

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[10] = "abcdef";
    size_t ret = strlen(arr);
    printf("%d\n",ret);//打印结果是6
    return 0;
}

模拟实现

//1.
size_t My_strlen(const char* str)
{
    assert(str);
    size_t count = 0;
    while(*str != '\0')
    {
        count++;
        str++;
    }
    return count;
}

//2.
size_t My_strlen(const char* str)
{
    assert(str);
    if(*str == '\0')
        return 0;
    else
    {
        return 1 + My_strlen(str++);
    }
}

//3.
size_t My_strlen(const char* str)
{
    assert(str);
    char* tmp = str;
    while(*str != '\0')
    {
        str++;
    }
    return str - tmp;
}

strcpy

拷贝字符串到指定地址

char* strcpy(char* destination, const char* source);
  • 目标字符串指向的空间必须可以修改,且足够大
  • 源字符串必须以\0结尾
  • 拷贝时会将\0拷贝到目标空间
  • 返回的是目标字符串的起始地址

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char src[] = "hello friends";
    char des[20] = { 0 };
    char* ret = strcpy(des, src);
    printf("%s\n", ret);//打印hello friends
    return 0;
}

模拟实现

char* My_strcpy(char* des, const char* src)
{
    assert(des && src);
    char* tmp = des;
    while (*des++ = *src++)
    {
        ;
    }
    return tmp;
}

strcat

在某个字符串后追加字符

char* strcat(char* destination, const char* source);
  • 实现逻辑:strcat函数会寻找目标空间的\0,然后将源字符串追加到后面,注意从\0这个位置追加,覆盖目标空间的\0,最终也会将源字符串的\0拷贝过去。
  • 源字符串需要\0结尾,指示追加结束
  • 目标字符串需要\0结尾,指示追加开始的位置
  • 目标空间需要足够大并且可以修改
  • 返回目标字符串的地址

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[30] = "hello ";
    char a2[] = "friends";
    char* ret = strcat(a1, a2);
    printf("%s\n", ret);//打印hello friends
    return 0;
}

当然,字符串可以追加自己。

模拟实现

char* My_strcat(char* des, const char* src)
{
    assert(des && src);
    char* tmp = des;
    while (*des)
    {
        des++;
    }
    while (*des++ = *src++)
    {
        ;
    }
    return tmp;
}

strcmp

比较两个字符串的内容

int strcmp(const char* str1, const char* str2);
  • 比较方法:strcmp函数会将两个字符串一个一个进行比较,比较的是字符的ASCII码值,当两个字符的ASCII码值相等时,继续向后比较,当不相等时,若str1当前字符大于str2当前字符,函数返回一个大于0的数,相反,返回一个小于0的数

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[] = "abcdef";
    char a2[] = "abcdy";
    int ret = strcmp(a1, a2);
    if (ret > 0)
    {
        printf("a1 > a2\n");
    }
    else if (0 == ret)
    {
        printf("a1 = a2\n");
    }
    else
    {
        printf("a1 < a2\n");
    }
    printf("%d\n", ret);
    return 0;
}
//最终打印值为:
a1 < a2 
-1

strcmp函数比较的是内容,不是长度,在例子中a1长度比a2长,但是,y的 ASCII码值大于e的,所以a2更大。

模拟实现

int My_strcmp(const char* str1, const char* str2)
{
    assert(str1 && str2);
    while (*str1 == *str2)
    {
        if (*str1 == '\0')
        return 0;
        str1++;
        str2++;
    }
    return *str1 - *str2;
}

strncpy

拷贝指定数量的字符到目标空间

char* strncpy(char* destination, const char* source, size_t num);
  • num就是要拷贝的字符的数量
  • 拷贝后不会在后面放\0
  • 拷贝的个数比源字符串字符数量多,会用\0补充缺失的字符,直到拷贝加补充的字符数量达到num
  • 返回的是目标字符串地址

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[] = "hello friends";
    char a2[20] = { 0 };
    char* ret = strncpy(a2, a1, 5);
    printf("%s\n", ret);//输出hello
    return 0;
}

strncat

在字符串后追加指定数量的字符

char* strncat(char* destination, const char* source, size_t num);
  • num就是要追加的字符的数量
  • 追加后会自动放一个\0,但是如果想追加的个数比源字符串长,不会补\0,这里要区别strncpy函数
  • 返回目标字符串地址

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[30] = "hello friends";
    char a2[20] = "! how are you?";
    char* ret = strncat(a1, a2, 5);
    printf("%s\n", ret);//输出hello friends! how
    return 0;
}

strncmp

比较指定数量字符的内容

int strncmp(const char* str1, const char* str2, size_t num);
  • num就是要比较的字符的个数

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[30] = "abcdefw";
    char a2[20] = "abcdeff";
    int ret = strncmp(a1, a2, 5);
    if (ret > 0)
    {
        printf("a1 > a2\n");
    }
    else if (ret < 0)
    {
        printf("a1 < a2\n");
    }
    else
        printf("a1 = a2\n");
    return 0;
}
//输出:a1 = a2

strstr

在一个字符串里寻找另一个字符串。

char* strstr(const char* str1, const char* str2);
  • 在str1指向的字符串中寻找str2指向的字符串,如果找到了,返回第一次出现的位置;如果找不到返回NULL
  • \0不在比较范围内,作为结束标志

例如:

#include <stdio.h>
#include <string.h>
int main()
{
    char a1[30] = "abcde";
    char a2[20] = "ddabcdeff";
    char* ret = strstr(a2, a1);
    printf("%s\n", ret);//打印abcdeff
    return 0;
}

模拟实现

char* My_strstr(const char* str1, const char* str2)
{
    assert(str1 && str2);
    const char* s1 = NULL;
    const char* s2 = NULL;
    const char* cur = str1;
    if (*str2 == '\0')//特殊情况:要寻找的是空字符串
        return (char*)str1;
    while (*cur)
    {
        s1 = cur;//s1记录每次开始比较的位置,每次寻找失败初始化
        s2 = str2;//s2记录每次开始比较的位置,每次寻找失败初始化
        while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')//找到相等的字符后面才可能找到指定字符串,继续向后比较,同时保证不是\0这一结束标志
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')//寻找成功的标志
            return (char*)cur;
        cur++;
    }
    return NULL;
}

strtok

通过分隔符(标志),将字符串分割

char* strtok(char* str, const char* delimiters);
  • delimiters指向的字符串,就是我们指定的分隔符(标志)的集合。可以是多个字符,字符内容不变的情况下,顺序无关结果。
  • strtok会在str指向的目标空间寻找指定的标志,找到后会将标志换成\0,然后返回标志位置之前的一段字符串的起始地址。
  • 由于strtok函数会改变目标字符串,所以我们在使用时,会将要查询的字符串strcpy一份,传参时传入拷贝的字符串的起始地址,strtok函数就会修改拷贝产生的空间的内容。
  • 值得注意的是,strtok会记录上一次标志的位置,当我再次调用strtok函数查询上一个目标空间时,第一个参数传NULL,strtok会寻找下一个标志。
  • 当字符串中不再有标志,返回NULL
#include <stdio.h>
#include <string.h>
int main()
{
    char a1[] = "310xxx2934@qq.com";
    char sign[] = "@.";
    char copy[20] = { 0 };
    //拷贝
    char* cop = strcpy(copy, a1);
    //第一次调用
    char* ret = strtok(copy, sign);
    printf("%s\n", ret);
    //之后调用
    ret = strtok(NULL, sign);
    printf("%s\n", ret);
   
    ret = strtok(NULL, sign);
    printf("%s\n", ret);
    
    ret = strtok(NULL, sign);
    printf("%s\n", ret);
    
    return 0;
}

打印结果:
    310xxx2934
    qq
    com
    (null)
    

strerror

会返回错误码对应的错误信息的字符串的地址

char * strerror ( int errnum );
  • errnum是错误码

  • 我们通常在使用strerror函数时,会传errno这个变量

    errno这个变量是在C程序开始时自动创建的一个全局变量。当我们在调用库函数时出错,errno变量会记录这一错误的错误码,比如0、1、2、3、4等等,我们当然不明白这个错误码是什么意思,基于此,头文件 <errno.h> 中记录了错误码对应的错误信息。

前面提到错误码是从0开始的,我们不妨打印一下0~10对应的的错误信息

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    for (int i = 0; i < 11; i++)
    {
        printf("%d  :%s\n", i, strerror(i));
    }
    return 0;
}
//这段代码的打印结果是:
0  :No error
1  :Operation not permitted
2  :No such file or directory
3  :No such process
4  :Interrupted function call
5  :Input/output error
6  :No such device or address
7  :Arg list too long
8  :Exec format error
9  :Bad file descriptor
10  :No child processes

我们再模拟一下调用函数出错的情况,并打印错误信息

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
    int* pi = (int*)malloc(10000000000000000000);
    if(pi = NULL)
    {
        printf("%s\n",strerror(errno));
    }
    free(pi);
    pi = NULL;
    return 0;
}
//malloc是一个库函数,当我们给malloc传入一个相当大的数字,malloc函数会返回NULL,我们将错误信息打印得到:
Not enough space

以上就是常见的字符函数和字符串函数了。

  • 40
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值