C语言字符函数和字符串函数的使用与实现

字符函数和字符串函数的使用与实现

查询文档CPlusPlus.com 编码过程当中我们经常会遇到处理字符或者字符串的场景, 比如你现在看到的每一个字 字符字符串

  • 字符''引起(例如'a', 'b'), 单引号引起的单个字符
  • 字符串""引起(例如"HelloWorld", "abcdef"), 双引号包裹的一个或者若干个字符

主要学习

  1. 操作字符的函数(例如大写字符变小写字符)
  2. 操作字符串的函数

字符函数

字符分类函数

C语言中有一系列的函数是专门做字符分类的, 也就是一个字符是属于什么类型的字符的 这些函数的使用都需要包含一个头文件ctype.h

函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符: 空格' ', 换页'\f', 换行'\n', 回车'\r', 制表符'\t'或者垂直制表符'\v'
isdigit 十进制数字'0'~'9'字符
isxdigit 十六进制数字, 包括所有十进制数字字符, 小写字母af, 大写字母AF
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母az或AZ
isalnum 字母或者数字, az, AZ, 0~9
ispunct 标点符号, 任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符, 包括图形字符和空白字符

这些函数的使用方法非常类似

c 复制代码
int islower (int c)

islower是能够判断参数部分的c是否是小写字母 通过返回值来说明是否为小写字母, 如果是小写字母就返回非0的整数, 如果不是小写字母, 则返回0

示例1

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    char ch = 'a';    //字符a
    if(isdigit(ch)) {    //如果参数符合条件就为真, a不是数字, 条件为假
        printf("是数字字符\n");    //跳过
    }
    else {
        printf("不是数字字符");    //打印
    }
    return 0;
}

示例2

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    char ch = 'a';    //字符a
    int ret = islower(ch);    //如果条件为假返回值0
    if(ret != 0) {
        printf("是小写字符\n");    //打印
    }
    else {
        printf("不是小写字符");
    }
    return 0;
}

示例3

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    char ch = 'a';    //字符a
    int ret = isupper(ch);    //如果条件为假返回值0
    if(ret != 0) {
        printf("是大写字符\n");
    }
    else {
        printf("不是大写字符");    //打印
    }
    return 0;
}

练习 写一个代码, 将字符串中的小写字母转为大写, 其他字符不变

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    /*为什么写成char *str[] = {"aBcdeF}会报错?
    因为char str[] = {"aBcdeF"}是创建一个str数组, 将"aBcdeF"字符串赋值给str数组
    而*str是直接指向这个字符串的地址的, 但是这个字符串是常量, 常量是无法更改的
    */
    char str[] = { "aBcdeF" };
    int i = 0;
    while (str[i] != '\0') {
        if (islower(str[i])) {
            str[i] -= 32;
        }
        i++;
    }
    printf("%s\n", str);    //打印ABCDEF
    return 0;
}

字符转换函数

C语言提供了两个字符转换函数

c 复制代码
int tolower (int c);    //将参数传进去的大写字母转小写
int toupper (int c);    //将参数传进去的小写字母转大写
函数 功能
tolower 将大写字母转换为小写字母
toupper 将小写字母转换为大写字母

返回值 该值的返回值为int类型, 可以隐式转换为char类型

上面的代码, 我们将小写转大写, 是-32完成的效果, 有了转换函数, 就可以直接使用toupper函数

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    char str[] = { "aBcdeF" };
    int i = 0;
    while (str[i] != '\0') {
        if (islower(str[i])) {
            str[i] = toupper(str[i]);    //注意 转换后的值是单独一个值, 不会修改原来的值
        }
        i++;
    }
    printf("%s\n", str);
    return 0;
}

如果传入非字母的字符呢

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main() {
    char ch = ',';
    char ch2 = toupper(ch);
    printf("%c\n", ch);    //输出',' 如果传入非字母的字符, 那么传入什么就输出什么
    return 0;
}

putchar

字符串函数

函数 功能
strlen 统计字符串长度
strcpy 字符串拷贝
strcat 字符串追加/拼接
strcmp 字符串比较
strncpy 字符串拷贝n个字符
strncat 字符串追加/拼接n个字符
strncmp 字符串比较
strerror 错误码
strstr 字符串查找

strlen

c 复制代码
size_t strlen ( const char * str );

功能 : 统计参数str指向的字符串长度. 统计的是字符串中'\0'之前的字符的个数 参数 : 指针, 指向了要统计长度的字符串 返回值 : 返回了str指向的字符串的长度, 返回的长度不会是负数, 所以是size_t 使用注意事项:

  • 字符串'\0'作为结束标志, strlen函数返回的是再字符串中'\0'前面出现的字符个数(不包含'\0')
  • 参数指向的字符串必须要以'\0'结束
  • 注意函数的返回值为size_t(unsigned int), 是无符号的(易错)
  • strlen的使用需要包含头文件<string.h>

练习

c 复制代码
#include <stdio.h>
#include <string.h>
int main() {
    const char *str1 = "abcdef";
    const char *str2 = "abc";
    /*是3-6? 符合条件吗? 注意strlen的返回值类型为无符号整形
    -3在内存中写入的是补码: (-3>源码(1000 0011)>反码(1111 1100)>补码(1111 1101)
    因为是无符号, 转换为十进制就是(253), 所以253 > 0)
    */
    if(strlen(str2) - strlen(str1) > 0) {
        printf("str2 > str1");
    }
    else {
        printf(str1 > str2);
    }
    return 0;
}

strcpy

c 复制代码
char* strcpy(char* destination, const char* source);

功能 : 字符串拷贝, 拷贝到源头字符串中的\0为止 参数 : destination: 指针, 指向目的地空间 source: 指针, 指向源头数据 返回值 : strcpy函数返回的目标空间的起始地址

strcpy的使用
c 复制代码
#include <stdio.h>
#include <>
int main() {
    char str_dest[10] = {0};
    char* src = "abcd";
    //将src字符串的值拷贝到str_dest字符串中, 使用ret获取返回值
    char* ret = strcpy(str_dest, src);
    printf("ret == %s\n", ret);    //abcd
    printf("str_dest == %s\n", str_dest);    //abcd
    return 0;
}

使用注意事项

  • 源字符串必须以\0结束
  • 会将源字符串中的\0拷贝到目标空间
  • 目标空间必须足够大, 以确保能存放源字符串
  • 目标空间必须可修改
strcpy函数的模拟实现
c 复制代码
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* destination, const char* source) {
    assert(destination != NULL && source != NULL);    //安全, 保证地址的合法性
    char* ret = destination;    //先记录一下destination的起始位置(内存地址)
    while (*source != '\0') {
        *destination = *source;
        destination++;
        source++;
    }
    /*也可以写成
    //先赋值后++, 如果赋值了\0那么就返回0, while循环接收到0则跳出循环
    while ((*destination++ = *source++)) {
        ;
    }
    */
    *destination = '\0';    //读取到\0的时候就退出while循环了, 需要手动为destination赋值\0
    return ret;    //由于复制完后的destination位置在\0, 所以使用ret(记录有起始位置)
}
int main() {
    char str_dest[10] = {0};
    char* src = "abcd";
    my_strcpy(str_dest, src);
    printf("ret == %s\n", src);
    printf("str_dest == %s\n", str_dest);
    return 0;
}

strcat

c 复制代码
char* strcat(char* destination, const char* source);

功能 :字符串追加/字符串拼接, 把source指向的源字符串中的所有字符串都追加/拼接到destination指向的空间中 参数 : destination: 指针, 指向目的地的空间 source: 指针, 指向源头数据 返回值 : strcat函数返回的目标空间的起始地址

c 复制代码
#include <stdio.h>
#include <assert.h>
#include <string.h>
int main() {
    char *str_src = "world";
    //数组的空间要足够大, str_sest数组有6个字符, str_src有6个字符, 拼接在一起总共11个字符(hello后面的\0被替换为world)
    char str_dest[20] = "hello";    //str_dest数组改变, 不能用指针
    //将str_src中的world拼接到str_dest中的hello后面就可以使用strcat
    char* ret = strcat(str_dest, str_src);
    printf("%s", ret);
    return 0;
}
strcat函数的模拟实现
c 复制代码
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* str_dest, char* str_src) {
    assert(str_dest != NULL && str_src != NULL);
    char* ret = str_dest;
    while (*str_dest != '\0') {
        str_dest++;
    }
    while (*str_src != '\0') {
        *str_dest = *str_src;
        str_dest++;
        str_src++;
    }
    *str_dest = '\0';
    return ret;
}
int main() {
    char* str_src = "World";
    char str_dest[20] = "Hello";
    char* ret = my_strcat(str_dest, str_src);
    printf("%s\n", ret);
    return 0;
}

strcmp

c 复制代码
int strcmp (const char* str1, const char* str2);

功能 : 用来比较str1str2指向的字符串, 从两个字符串的第一个字符开始比较, 如果两个字符的ASCII码值相等, 就比较下一个字符. 直到遇到不相等的两个字符, 或者字符串结束. 参数 : str1: 指针, 指向要比较的第一个字符串 str2: 指针, 指向要比较的第二个字符串 返回值:

  • 标准规定:
    • 第一个字符串大于第二个字符串, 则返回大于0的数字
    • 第一个字符串等于第二个字符串, 则返回0
    • 第一个字符串小于第二个字符串, 则返回小于0的数字
srtcmp的使用
c 复制代码
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
    const char* srt1 = "abcd";
    const char* str2 = "abcde";
    //第一个参数和第二个参数进行比较
    //<0 第一个参数小于第二个参数
    //== 0 第一个参数等于第二个参数
    //>0 第一个参数大于第二个参数
    int ret = strcmp(str1, str2);
    printf("%d\n"ret);
    return 0;
}
strcmp的模拟实现
c 复制代码
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2) {
    assert(str1 != NULL && str2 != NULL);
    while(*str1 == *str2) {
      if (*str1 == '\0') {
          return 0;
      }
      str1++;
      str2++;
    }
    return *str1 - *str2;
}
int main() {
    char* str1 = "abay";
    char* str2 = "abcd";
    int ret = my_strcmp(str1, str2);
    printf("%d\n", ret);
    return 0;
}

strncpy

c 复制代码
char* strncpy(char* destination, const char* source, size_t num);

功能 : 字符串拷贝; 将source指向的字符串拷贝到destination指向的空间中, 最多拷贝num个字符 参数 : destination: 指针, 指向目的地空间 source: 指针, 指向源头数据 num: 从source指向的字符串中最多拷贝的字符个数 返回值 : strncpy函数返回的目标空间的起始地址

strerror

c 复制代码
char* strerror(int errnum);

功能:

  1. strerror函数可以通过参数部分的errnum表示错误码, 得到对应的错误信息, 并且返回这个错误信息字符串首字符的地址
  2. strerror函数只针对标准库中的函数发生错误后设置的错误码的转换
  3. strerror的使用需要包含<string.h>

在不同的系统和C语言标准库的实现中都规定了一些错误码, 一般是放在errno.h这个头文件中说明的, C语言程序启动的时候就会使用一个全局变量errno来记录程序的当前错误码, 只不过程序启动的时候errno是0, 表示没有错误, 当我们在使用标准库中的函数的时候发生了某种错误, 就会将对应的错误码, 存放在errno中, 而一个错误码的数字是整数, 很难理解是什么意思, 所以每一个错误码都是有对应的错误信息的. strerror函数就可以将错误码对应的错误信息字符串的地址返回

参数 : errnum: 表示错误码 这个错误码一般传递的是errno这个变量的值, 在C语言有一个全局变量名叫: errno, 当库函数的调用发生错误的时候, 就会将本次错误的错误码存放在errno这个变量中, 使用这个全局变量需要包含一个头文件errno.h 返回值: 函数返回通过错误码得到的错误信息字符串的首字符地址

perror

也可以了解一下perror函数, perror函数直接将错误信息打印出来. perror函数打印完参数部分的字符串后, 再打印一个冒号和一个空格, 再打印错误信息

c 复制代码
//注: 错误信息非固定信息, 使用这个错误信息只是为了演示
printf("错误信息是: %s\n", strerror(errno));    //输出 错误信息是: No such file or directory
perror("错误信息是");    //输出 错误信息是: No such file or directory

strstr

c 复制代码
char* strstr(const char* str1, const char* str2);

功能 : strstr函数, 查找str2指向的字符串在str1指向的字符串中第一次出现的位置 简而言之: 在一个字符串中查找子字符串 参数 : str1: 指针, 指向了被查找的字符串 str2: 指针, 指向了要查找的字符串 返回值:

  • 如果str1指向的字符串中存在str2指向的字符串, 那么返回第一次出现位置的指针
  • 如果str1指向的字符串中不存在str2指向的字符串, 那么返回NULL

扩展 : 如果对字符串查找感兴趣, 可以看看KMP算法, 效率特别高

相关推荐
少司府5 小时前
C++进阶:智能指针
开发语言·数据结构·c++·b树·算法·c·智能指针
2601_962294613 天前
AI 基础设施的“去 Python 化“:Rust 与 C# 的两条替代路径
ai·rust·c·基础设施·去python化
2601_962297254 天前
C# vs Java vs Python:YOLO工业部署性能对比实战
java·python·c·工业视觉·性能对比
知无不研5 天前
一个简单的2048小游戏
游戏·c·2048·小项目
牢姐与蒯12 天前
Linux进程(三)之进程状态_僵尸孤儿
linux·运维·服务器·ubuntu·c
半点闲19 天前
深入解析小端序:把 4 字节的小端序拼成一个 32 位无符号长整数
c·字节序·大小端字节序·小端字节序转32位无符号长整数
C++ 老炮儿的技术栈24 天前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
一韦以航.1 个月前
C/C++ 基础深挖:strlen 与 sizeof 全方位对比区别
c语言·jvm·c++·算法·面试·c
Ronin-Lotus1 个月前
蓝桥杯篇---EEPROM内部存储地址
职场和发展·蓝桥杯·c·eeprom·keil