字符串相关函数
头文件都是 string.h
概述:
由系统提供的由字符串处理的函数
属于库函数
所属头文件
string.h
1 strlen
测量字符串长度
语法:
size_t strlen(const char *s);
参数:
要测量的字符串
返回值:
长度
注意:
测量的长度不包括\0
#include <stdio.h> #include <string.h> int main(int argc, char const *argv[]) { char *str = "hello6\0"; int len = strlen(str); printf("str len = %d\n", len); // 结果不包含\0 因为\0 本身是0 char str02[100] = {0}; printf("请输入内容:"); fgets(str02, 100, stdin); int len2 = strlen(str02); printf("len2 = %d\n", len2); // 为什么会输入 长度 为5 因为 你敲击回车 代表\n换行了 也算一个字符 return 0; }
为什么会输入root 明明只有4长度 但是为什么显示长度 为5 因为 你敲击回车 代表\n换行了 也算一个字符
2 strcpy:
拷贝字符串(深拷贝)
char *strcpy(char *dest, const char *src); 参数: dest:目标位置 src:资源位置 返回值: 就是目标位置 作用:将src的内容赋值给dest char *strncpy(char *dest, const char *src, size_t n); 参数: dest:目标位置 src:资源位置 n:拷贝的字节数 返回值: 就是目标位置 作用:将src前n个字节的内容赋值给dest
浅拷贝 : 拷贝的是地址 如 : // char *str01 = "abc";//此时abc在常量区,str01 指向常量区,此时不能对其值进行修改 char str01[] = "abc"; // 将常量区的abc拷贝到str01所在的栈的区域 char *str02 = str01; // 此时产生浅拷贝,只拷贝了str01的地址,并没有拷贝其值, 那么此时str01与str02指向同一位置 str01[0] = 'A'; // 当str01被修改后,str02打印的内容也将被修改 printf("str01 = %s\n", str01); printf("str02 = %s\n", str02);//深拷贝 : 拷贝的是内容 如 : char str01[] = "abc"; char *str02 = (char *)malloc(100); memset(str02, 0, 100); strcpy(str02, str01); // 使用strcpy函数对字符串拷贝为深拷贝,将str01的内容拷贝到str02中, 此时str01与str02指向的地址不同 str01[0] = 'A'; // 修改str01中的内容,并不会影响str02中的内容 printf("str01 = %s\n", str01); printf("str02 = %s\n", str02);
3 strcat:
追加
语法:
char *strcat(char *dest, const char *src); 参数: dest:目标位置 src:资源位置 作用:将src的内容追加到dest的尾部 char *strncat(char *dest, const char *src, size_t n); 参数: dest:目标位置 src:资源位置 n:追加的字节数 作用:将src的内容的前n个字节追加到dest的尾部
注意:
使用该函数需注意目标位置指向的内存大小要足够
4 strcmp
比较字符串内容是否相同
时刻注意字符串尾部的 \0
语法:
int strcmp(const char *s1, const char *s2); 参数: s1: 字符串1 s2: 字符串2 返回值: 0 表示相同 非0 表示不同 因为 比较的原理就是 相减 要是为0 就表示一致 不为0 表示不一致
示例:
判断 账号与密码是否正确
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char const *argv[]) { // 输入账号密码,判断登录是否成功注册时账号:root,密码:123456 printf("请输入账号:\n"); // 提示输入账号 char *username = (char *)calloc(100, 1); // calloc(每块内存大小,几块) fgets(username, 99, stdin); int len1 = strlen(username); // 求出 username的字符串长度 // 关键一步: 去掉 尾部 '\0' username[len1 - 1] = '\0'; printf("请输入密码:\n"); char *password = (char *)malloc(100); // malloc(申请开辟的内存大小) // 因为 malloc 生成的内存存放的是随机的 而calloc申请的内存存放的是0 memset(password, 0, 100); fgets(password, 99, stdin); // 因为字符以\n 换行结束 int len2 = strlen(password); password[len2 - 1] = '\0'; int x = strcmp(username, "admin"); int y = strcmp(password, "123456"); printf("%d\n", x); // 比较结果 printf("%d\n", y); if (x == 0 && y == 0) { printf("登录成功\n"); } else { printf("登录失败\n"); } return 0; }
要是不将 尾部 \0 去掉 会怎么样:
5 strchr
查询单个字符首次出现的位置
语法:
char *strchr(const char *s, int c); 作用: 在s中查询 c第一次出现的位置 参数: s:被查找的字符串 c:要查找的字符 返回值: c第一次出现的位置的地址 如果c不存在则返回NULL char *strrchr(const char *s, int c); // 从右侧往左侧数
示例:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char const *argv[]) { // 输入一个字符串输出其长度,查询其指定字符 a 第一次出现的位置 与 最后一次出现的位置 printf("请输入内容:\n"); char *str = (char *)malloc(100); int len = strlen(str); if (str != NULL) { memset(str, 0, 100); fgets(str, 99, stdin); // 获取输入的内容 // char *strchr(const char *s, int c); s:被查找的字符串 c:要查找的字符 返回值:c第一次出现的位置的地址 如果c不存在则返回NULL char *p = strchr(str, 'a'); printf("首次位置==%p\n", &p); // 首次位置 char *p1 = strrchr(str, 'a'); printf("最后一次位置=%p\n", &p1); // 最后一次位置 } free(str); // 释放内存 return 0; }
6 strstr
查找指定字符串出现的位置
语法:
char *strstr(const char *haystack, const char *needle); 参数: haystack:被查找的字符串 needle:要查找的字符串 返回值: 查找到的字符串第一次出现的位置 如果不存在返回NULL
7 atoX:
转数字
int atoi(const char * p); 将字符串型的整数,转换为int double atof(const char * p); 将字符串型的浮点数,转换为double
示例:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char const *argv[]) { // 键盘输入两个整型字符串,计算两个输入的数之和 // 考核:转 数字 // 使用 fgets 从标准输入读取字符串时,包括换行符 \n 也会被读取。因此,在使用 atoi 转换之前,应该去除字符串末尾的换行符。 char *arr1 = (char *)calloc(60, 1); // 申请内存 printf("请输入内容1:"); fgets(arr1, 60, stdin); // 获取用户输入 char *arr2 = (char *)calloc(60, 1); int len1 = strlen(arr1); // 去除 \0 arr1[len1 - 1] = '\0'; printf("请输入内容1:"); fgets(arr2, 60, stdin); int len2 = strlen(arr2); // 去除 \0 arr2[len2 - 1] = '\0'; int x = atoi(arr1); int y = atoi(arr2); int z = x + y; printf("总和为:%d\n", z); return 0; }
8 strtok():
切割字符串内容
注意点: 首次切割 和 余下后面的切割 切割的内容不一样
首次 是以整个数组切割
余下切割都是以上一次切割后剩余部分继续切割
语法:
char *strtok(char *str, const char *delim); 参数: str:被切割的字符串 delim:以什么切割 返回值: 切割后的字符串
注意:
每调用一次该函数,切割一次 切割上一次剩余的字符串时str填NULL
示例1:
void method07() { char str[] = "hehehe:::::::::hahaha#xixixi@lalala:heiheihei"; char tag[] = ":#@"; char *p = strtok(str,tag); // 首次切割 printf("str = %s\n",str); printf("p = %s\n",p); //当被切割的字符串为NULL,将会切割上一次剩余的字符串 char *p2 = strtok(NULL,tag); // 余下切割 是以上一次剩余的部分进行的 printf("p2 = %s\n",p2); }
示例2:
#include <stdio.h> #include <string.h> int main(int argc, char const *argv[]) { // 1 定义数组来接收 原始数据 char str[] = "hehehe:::::::::hahaha#xixixi@lalala:heiheihei"; // 2 定义切割标准数组 char tag[] = ":#@"; // 3 定义来存储 切割后的字符段 char *strs[6] = {str}; // 初始化strs[0]为str的地址 int len = 0; ; // 定义切割完的段数 int i = 0; // 定义切割的位置从0开始 while ((strs[i] = strtok(strs[i], tag)) != NULL && ++i && ++len) ; printf("切割完的段数= %d\n", len); for (int i = 0; i < len; i++) { printf("%s\n", strs[i]); } return 0; }
格式化字符串
概述:
1 组包
sprintf
int sprintf(char *str, const char *format,...); 作用: //给str指向的内存中写入指定内容,format格式化字符串,....替换掉占位符的值。
2 解包
0sscanf
int sscanf(const char *str, const char *format, ...); 作用: 从str中按format获取数据到...中
注意
正则表达式
%d:只能取整数 %c:一次读取一个字符 %s:与空格,换行,\0读取结束 %2d:取两位整数,如果超过2位取两位,不足两位有几位取几位 %*d:跳过整数 %*2d:跳过两位整数 %[a-z] 表示匹配 a 到 z 中任意字符(尽可能多的提取,遇除a-z以外结束) 贪婪性:尽可能多的提取 %[aBc] 匹配 a、B、c 中一员,贪婪性 %[^aFc] 匹配非 a Fc 的任意字符,贪婪性,遇a,F,c结束 %[^a-z] 表示读取除 a-z 以外的所有字符 遇到小写字母就结束
示例
char buf[20]; sscanf("x@1000phone.com","%*[^@]@%[^.]",buf); printf("%s\n",buf); // 结果 1000phone
%d:只能取整数
%c:一次读取一个字符
%s:与空格,换行,\0读取结束
%2d:取两位整数,如果超过2位取两位,不足两位有几位取几位
%*d:跳过整数
%*2d:跳过两位整数
%[a-z] 表示匹配 a 到 z 中任意字符(尽可能多的提取,遇除a-z以外结束)
贪婪性:尽可能多的提取
%[aBc] 匹配 a、B、c 中一员,贪婪性
%[^aFc] 匹配非 a Fc 的任意字符,贪婪性,遇a,F,c结束
%[^a-z] 表示读取除 a-z 以外的所有字符 遇到小写字母就结束示例 ~~~c char buf[20]; sscanf("x@1000phone.com","%*[^@]@%[^.]",buf); printf("%s\n",buf); // 结果 1000phone