C语言常用库函数:字符串操作与安全函数

一、复制

// 头文件:string.h 
// 函数原型:errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc);
// 函数原型:errno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t count);
// 将源缓冲区strSrc的字符串复制到目的缓冲区strDest, 复制的字符个数可以有count指定

char strDest[DEST_LEN] = {0};
char strSrc[SRC_LEN] = {0};
strcpy_s(strSrc, SRC_LEN, "strcpy: learning string on strcpy_s");
strcpy_s(strDest, DEST_LEN, strSrc);
printf("cpy: strSrc=%s, strDest=%s\n", strSrc, strDest);

memset_s(strDest, DEST_LEN, 0, DEST_LEN);
strncpy_s(strDest, DEST_LEN, strSrc, CHAR_COUNT);
printf("ncpy: strDest=%s\n", strDest);

二、拼接

// 头文件:string.h 
// 函数原型:errno_t strcat_s(char *_Dst, rsize_t _SizeInBytes, const char * _Src);
// 函数原型:errno_t strncat_s(char *_Dst, rsize_t _SizeInBytes, const char * _Src, size_t count);
// 将 _Src 所指向的字符串拼接到 _Dst 字符串的后面,_SizeInBytes是_Dst所指内存的大小, count为源缓冲区需要连接的字符个数
char strDest[DEST_LEN] = {0};
char strSrc[SRC_LEN] = {0};
strcat_s(strSrc, SRC_LEN, "strcat: learning string on strcpy_s");
strncat_s(strDest, DEST_LEN, strSrc, 10);
printf("cat:\nstrSrc=%s,\nstrDest=%s\n", strSrc, strDest);

三、格式化输出:

// 头文件:stdio.h
// 函数原型:int sprintf_s(char *_Dst, rsize_t _SizeInBytes);
// 函数原型:int snprintf_s(char *_Dst, rsize_t _SizeInBytes, size_t count, const char* format);
// 将数据格式化输出到目的缓冲区,rsize_t是_Dst所指内存的大小, count为需要输出到目的缓冲区的字符个数
char strDest[DEST_LEN] = "66668888";
char strSrc[SRC_LEN] = "6666.8888";
// 优先使用sprintf_s
sprintf_s(strSrc, SRC_LEN, "sprintf: %s+%d\n", strDest, atol(strDest));
printf("strSrc=%s\n", strSrc);

memset_s(strSrc, SRC_LEN, 0, SRC_LEN);
snprintf_s(strSrc, SRC_LEN, CHAR_COUNT, "snprintf: %s+%d\n", strDest, atol(strDest));
printf("strSrc=%s\n", strSrc);

四、格式化输入(正则表达式,超级好用)

// 头文件:stdio.h  
// 函数原型:int sscanf_s(const char* buffer, const char* format);
// 如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
// buffer要从中读取数据的缓冲区,format格式化控制字符串
// 如果格式化控制字符串(format)中包含了%s、%S、%c、%C或括号表达式(例如%[a-d])时,函数中应该传入输出缓冲区长度大小(format之后),
// 且长度大小必须小于等于输出缓冲区的实际大小、且大于等于(输出的数据长度 + 1)。

char strDest[DEST_LEN] = "192.168.1.100/24";
int ip0 = 0;
int ip1 = 0;
int ip2 = 0;
int ip3 = 0;
int mask = 0;
int ret = 0;
// 入参需要传入地址
ret = sscanf_s(strDest, "%d.%d.%d.%d/%d", &ip0, &ip1, &ip2, &ip3, &mask, DEST_LEN);
// printf("strDest=%s, ret=%d, ip0=%d, ip1=%d, ip2=%d, ip3=%d, maske=%d\n", strDest, ret, ip0, ip1, ip2, ip3, mask);

char strSrc[SRC_LEN] = "123456helloWORLD";
char strTemp[SRC_LEN] = {0};
// 字符匹配会被空格隔断, %5s——匹配5个字符; %[^o]——匹配到某个字符未止;%[a-z]——匹配a-z中的任意字符; %[^A-Z]——匹配除A-Z之外的任意字符
// %[1-9a-z]——范围匹配, *表示跳过此数据不读入,否则完全从开始读入,如%*[1-9]%*[a-z]%s,获取123456helloWORLD中的大写字符串;
ret = sscanf_s(strSrc, "%*[1-9]%*[a-z]%s", strTemp, SRC_LEN);
// printf("strSrc=%s, ret=%d, temp=%s\n", strSrc, ret, strTemp);

// %[^a]——匹配非a的任意字符, 配合*使用,%*[^a],表示跳过字符串前面的非a的任意字符,后续处理从a开始
ret = sscanf_s("ipadda=10.46.1.10/24", "%*[^=]=%d.%d.%d.%d/%d", &ip0, &ip1, &ip2, &ip3, &mask, DEST_LEN);
//printf("ret=%d, ip0=%d, ip1=%d, ip2=%d, ip3=%d, maske=%d\n", ret, ip0, ip1, ip2, ip3, mask);
// %*[ ] 可以去除空格
memset_s(strTemp, SRC_LEN, 0, SRC_LEN);
ret = sscanf_s("name   =    hzl", "%*[^=]=%*[ ]%s", strTemp, DEST_LEN);
// printf("ret=%d, strTemp=%s\n", ret, strTemp);

// 特殊数字匹配: 存在括号表达式时,需要在输出字符串后添加输出长度
memset_s(strTemp, SRC_LEN, 0, SRC_LEN);
char s1[SRC_LEN] = {0};
char s2[SRC_LEN] = {0};
ret = sscanf_s("1hello234world5", "%*[0-9]%[^2]234%[^5]", s1, SRC_LEN, s2, SRC_LEN);
// printf("ret=%d, s1=%s, s2=%s\n", ret, s1, s2);

// 跳过单个字符:%*c
char s3[SRC_LEN] = {0};
char s4[SRC_LEN] = {0};
ret = sscanf_s("michale/nHao", "%[^/n]%*c%*c%s", s3, SRC_LEN, s4, SRC_LEN);
printf("ret=%d, s3=%s, s4=%s\n", ret, s3, s4);

五、比较

// 头文件:string.h 
// 函数原型:int strcmp(const char *s1,const char *s2);
// 两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止
// s1 < s2, 返回负数;s1 = s2, 返回0;s1 > s2, 返回正数;(即返回s1 - s2)
int ret = 0;
ret = strcmp("abcdf0", "abcdf");
printf("ret=%d\n", ret);

六、查找

:string.h 
// 函数原型-从左侧查找字符,返回第一次出现的位置:char *strchr(const char *str, int c);
// 函数原型-从右侧查找字符,返回第一次出现的位置:char *strrchr(const char *str, int c);
// 函数原型-从左侧查找字符子串,返回第一次出现的位置:char *strstr(const char *haystack, const char *needle)
char strDest[SRC_LEN] = "www.cbaidu.com";
char *strRet = NULL;
int index = 0;
strRet = strchr(strDest, 'c');
index = strRet - strDest;
printf("strchr: ret=%p, index=%d\n", strRet, index);

strRet = strrchr(strDest, 'c');
index = strRet - strDest;
printf("strrchr: ret=%p, index=%d\n", strRet, index);

strRet = strstr(strDest, "du");
index = strRet - strDest;
printf("strstr: ret=%p, index=%d\n", strRet, index);

七、数字转换

// 头文件:stdlib.h 
// 函数原型(进制转换):long strtol(const char *_Str,char **_EndPtr,int _Radix);
// 把参数 str 所指向的字符串根据给定的 base 转换为一个长整数, base 必须介于 2 和 36(包含)之间,或者是特殊值 0(默认十进制)。
// endptr -- 对类型为 char* 的对象的引用,其值由函数设置为 str 中数值后的下一个字符,可以理解为转换的截止处。
// 若endptr 不为NULL,则会将遇到的不符合条件而终止的字符指针由 endptr 传回;若 endptr 为 NULL,则表示该参数无效,或不使用该参数。
// 函数原型: int atoi(const char *_Str);
// 函数原型: long atol(const char *_Str);
// 函数原型:double atof(const char *_String);

const char strDest[DEST_LEN] = "1111 This is test";
const char strDest2[DEST_LEN] = "688.688";
char *endPtr;
long ret1;
long ret2;
long ret3;
long ret4;

ret1 = strtol(strDest, &endPtr, 0);
ret2 = strtol(strDest, &endPtr, 2);
ret3 = strtol(strDest, &endPtr, 8);
ret4 = strtol(strDest, &endPtr, 16);

printf("strtol: \nret1(0)=%ld, \nret2(2)=%ld, \nret3(8)=%ld, \nret(16)=%ld, \nendptr=%s\n", 
    ret1, ret2, ret3, ret4, endPtr);
printf("strtol: \nret1(0)=%ld, \nret2(2)=%ld, \nret3(8)=%o, \nret(16)=0x%x, \nendptr=%s\n", 
    ret1, ret2, ret3, ret4, endPtr);

int iNum = atoi(strDest2);
long lNum = atol(strDest2);
double fNum = atof(strDest2);
printf("inum= %d, lnum=%ld, fnum=%f\n", iNum, lNum, fNum);

八、切割

// 头文件:stdlib.h
// 函数原型:strtok(char *_Str, const char *_Delim);
// 函数原型:char *strtok_s(char *_Str, const char *_Delim, char **_Context);
// _Context保存调用strok_s后的位置信息
char strDest[DEST_LEN] = "90.88.17.18";
const char s[2] = ".";
char *next_token = NULL;
char *p1, *p2, *p3, *p4;

p1 = strtok_s(strDest, s, &next_token);
// 继续获取其他的子字符串
p2 = strtok_s(NULL, s, &next_token);
p3 = strtok_s(NULL, s, &next_token);
p4 = strtok_s(NULL, s, &next_token);
printf("stroke: p1=%s, p2=%s, p3=%s, p4=%s\n", p1, p2, p3, p4);
printf("atoi: i1=%d, i2=%d, i3=%d, i4=%d\n", atoi(p1), atoi(p2), atoi(p3), atoi(p4));
posted @ 2021-08-07 23:54  Pangolin2  阅读(986)  评论(0编辑  收藏  举报