zoukankan      html  css  js  c++  java
  • 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
    ", strSrc, strDest);
    
    memset_s(strDest, DEST_LEN, 0, DEST_LEN);
    strncpy_s(strDest, DEST_LEN, strSrc, CHAR_COUNT);
    printf("ncpy: strDest=%s
    ", 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:
    strSrc=%s,
    strDest=%s
    ", 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
    ", strDest, atol(strDest));
    printf("strSrc=%s
    ", strSrc);
    
    memset_s(strSrc, SRC_LEN, 0, SRC_LEN);
    snprintf_s(strSrc, SRC_LEN, CHAR_COUNT, "snprintf: %s+%d
    ", strDest, atol(strDest));
    printf("strSrc=%s
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", ret, s3, s4);
    
    

    五、比较

    // 头文件:string.h 
    // 函数原型:int strcmp(const char *s1,const char *s2);
    // 两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇''为止
    // s1 < s2, 返回负数;s1 = s2, 返回0;s1 > s2, 返回正数;(即返回s1 - s2)
    int ret = 0;
    ret = strcmp("abcdf0", "abcdf");
    printf("ret=%d
    ", 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
    ", strRet, index);
    
    strRet = strrchr(strDest, 'c');
    index = strRet - strDest;
    printf("strrchr: ret=%p, index=%d
    ", strRet, index);
    
    strRet = strstr(strDest, "du");
    index = strRet - strDest;
    printf("strstr: ret=%p, index=%d
    ", 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: 
    ret1(0)=%ld, 
    ret2(2)=%ld, 
    ret3(8)=%ld, 
    ret(16)=%ld, 
    endptr=%s
    ", 
        ret1, ret2, ret3, ret4, endPtr);
    printf("strtol: 
    ret1(0)=%ld, 
    ret2(2)=%ld, 
    ret3(8)=%o, 
    ret(16)=0x%x, 
    endptr=%s
    ", 
        ret1, ret2, ret3, ret4, endPtr);
    
    int iNum = atoi(strDest2);
    long lNum = atol(strDest2);
    double fNum = atof(strDest2);
    printf("inum= %d, lnum=%ld, fnum=%f
    ", 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
    ", p1, p2, p3, p4);
    printf("atoi: i1=%d, i2=%d, i3=%d, i4=%d
    ", atoi(p1), atoi(p2), atoi(p3), atoi(p4));
    
  • 相关阅读:
    luogu P3801 红色的幻想乡
    [USACO07OPEN]吃饭Dining
    [SCOI2007]蜥蜴
    [SDOI2011]染色
    [USACO07DEC]Sightseeing Cows
    [HNOI2007]紧急疏散EVACUATE
    [ZJOI2009]假期的宿舍
    [SDOI2013]费用流
    [CQOI2009]跳舞
    使用chrony安装chrony
  • 原文地址:https://www.cnblogs.com/HZL2017/p/15113786.html
Copyright © 2011-2022 走看看