字符串函数详解(宝藏总结,看了必懂)

1.求长度函数strlen

1.1模型

size_t strlen(const char* string);

1.2易错

#include <stdio.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
//u_int - u_int == u_int -3被当成无符号数 
  printf("str2>str1\n");//ok
else
  printf("srt1>str2\n");
return 0;
}

1.3源码

size_t __cdecl strlen (const char * str )
{
const char *end = str;
while( *end++ ) ;
return end - str - 1 ;
}

1.4模拟实现

//计数器
size_t my_strlen(const char* str)
{
    assert(str);
    size_t count = 0;
    while (*str != '\0')
    {
        count++;
        str++;
    }
    return count;
}

//函数递归
int my_strlen(const char * str)
{
if(*str == '\0')
  return 0;
else
  return 1+my_strlen(str+1);
}

//指针
size_t my_strlen(const char* str)
{
    const char* end = str;
    while (*end++);
    return end - str - 1;
}

2.拷贝函数strcpy

2.1模型

char* strcpy(char * des, const char * src );

2.2注意

  • 源字符串以 '\0' 结束。

  • 源字符串中 '\0' 拷贝到目标地址。

  • 目标空间足够大能存放源字符串。

  • 目标空间可变。

2.3模拟实现

char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest && src);

while(*dest++ = *src++);

while(*src!='\0')
  *dest++=*src++;
*dest=*src;

return ret;
}

3.比较函数strcmp

3.1模型

int strcmp ( const char * str1, const char * str2 );

3.2注意

  • 第一个字符串大于第二个字符串,则返回大于0的数字

  • 第一个字符串等于第二个字符串,则返回0

  • 第一个字符串小于第二个字符串,则返回小于0的数字

3.3源码

int __cdecl strcmp (const char * src,const char * dst )
{
int ret = 0 ;
while((ret = *(u_char *)src - *(u_char *)dst) == 0 && *dst)
      ++src, ++dst;
return ( (-ret) < 0 ) - (ret < 0); 
}

3.4模拟实现

int my_strcmp (const char * src, const char * dst)
{
assert(dest && src);
While (*s1 == *s2 )
{
  if (*s1 == '\0')
      return 0;
  s1++ ;
  s2++ ;
}
return *s1 -*s2;
}

4.追加函数strcat

4.1模型

char * strcat ( char * dest, const char * src );

4.2用途

  • 源字符串以 '\0' 结束。

  • 目标空间能容纳下源字符串。

  • 目标空间可修改。

4.3源码

char * strcat (char * dst,const char * src)
{
char * cp = dst;
while( *cp )
  cp++;                  
while((*cp++ = *src++) != '\0') ;       
return dst ;                  
}

4.4模拟实现

char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest && src);
while(*dest)
dest++;
while((*dest++ = *src++))
{
;
}
return ret;
}

5.查重函数strstr

5.1模型

char * strstr ( const char *str1, const char * str2);

5.2用途

5.3源码

char*strstr(const char* str1,const char *str2)
{
    char* cp = (char*)str1;
    char* s1,*s2;
    if (!*str2)
        return (char*)str1;
    while (*cp)
    {
        s1 = cp;
        s2 = (char*)str2;
        while (*s2 && *s1 ==*s2)
            s1++,s2++;
        if (!*s2)
            return(cp);
        cp++;
    }
    return NULL;
}

5.4模拟实现

char *  strstr (const char * str1, const char * str2)
{
    const char *s1, *s2;
    if ( !*str2 )
      return (char *)str1;
    while (*str1)
   {
        s1 = str1;//更新
        s2 = str2;//回归原位
        while ( *s1 && *s2 && *s1==*s2 )
            s1++, s2++;
        if (!*s2)//*s2=='\0'
            return (char*)str1;
        str1++;//str1记录首个字符相同的地址
   }
    return NULL;

6.切割函数strtok

6.1模型

char * strtok ( char * str, const char * sep );

6.2注意

  • sep指向用作分隔符的字符集合

  • str指向一个含1个或多个sep指向字符串中分隔符的字符串。

  • 函数找到一个标记,将其用 \0 结尾,返回指向这个标记的指针。

注:函数会改变被操作的字符串,使用strtok切分的字符串一般是临时拷贝且可修改。

  • str不为 NULL 时,函数找到第一个标记,保存它在字符串中的位置。

str为 NULL时 ,函数在同一个字符串中被保存的位置开始,查找下一个标记。

  • 如果字符串中不存在标记,返回 NULL 指针。

6.3用途

6.4模拟实现

char* my_strtok(char* str, const char* dmt)
{   //delimiters分隔符
    static char* p = NULL;//静变记录每个字符串的首地址
    if (str != NULL)      //首次传参,p=str;之后p为上次调用后的p
        p = str;
    char Dmt[256] = { 0 };
    while (*dmt)  //含有分隔符的元素置1,其余为0
        Dmt[*dmt++] = 1;
    char* ret = *p ? p : NULL; 
    //最后一个字符串得到后,p指向整个字符串的\0
    //再次调用,ret返回NULL,调用结束,主函数for循环也结束
    while (*p && Dmt[*p] == 0)
        p++;              //没有遇到dmt前p++
    if (*p)       //因为遇到dmt循环结束,将其置\0
        *p++ = '\0';  
    return ret;
}
int main()
{
    char a[] = "aaa#bbb@ccc", t[30] = { 0 };
    char* s = "#@", * p = NULL;
    strcpy(t, a);
    for (p = my_strtok(t, s); p != NULL; p = my_strtok(NULL, s))
        printf("%s\n",p);
    return 0;
}

7.strerror

7.1模型

#include<errno.h>
char * strerror ( int errnum );

7.2用途

  • 使用库函数,调用失败时,将错误码放于全局变量int errno;

  • strerror会将errno翻译成对应错误信息

int main()
{
    FILE* pf = fopen("test. txt", "r");
    if (pf == NULL)
    {
        printf("%s\n", strerror(errno));
        return 1;//No such file or directory
    }
    fclose(pf);
    pf = NULL;
    return 0;
}

7.3perror函数

#include<stdio.h>
void perror( const char *string );

int main()
{
    FILE* pf = fopen("test. txt", "r");
    if (pf == NULL)
    {
        printf("%s\n", strerror(errno));
        perror("results");
        return 1;
    }
    fclose(pf);
    pf = NULL;
    return 0;
}

打印结果:

8.strncpy

8.1模型

char* strncpy ( char* dest,const char* src,size_t num );

8.2用途

  • 拷贝num个字符从源字符串到目标空间。

  • 当num>src长度时,仍拷贝n个字符(src中没有的拷贝\0)

  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标后追加0,直到num个。

8.3模拟实现

char* my_strncpy(char* dest, const char* src, size_t n)
{
    char* ret = dest;
    while (n--)
        *dest++ = *src++;
    *dest = '\0';
    return ret;
}
int main()
{
    char a[] = "aaaaaa";
    char b[] = "bbb";
    my_strncpy(a, b, 3);
    printf("%s", a);
    return 0;
}

9.strncmp

9.1模型

int strncmp ( const char* str1, const char* str2, size_t num );

9.2调用结束

  • 出现字符不一样

  • 字符串结束

  • num个字符比较完

9.3用途

int main()
{
    char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
    for (int n = 0; n < 3; n++)
    {
        if (strncmp(str[n], "R2xx", 2) == 0)
            printf("found %s\n", str[n]);
    }
    return 0;
}
//输出
found R2D2
found R2A6

10.strncat

10.1模型

char* strncat ( char* dest, const char* src, size_t num )

10.2源码

char*  my_strncat(char* p,const char* q,size_t n)
{
    char* ret = p;
    while (*p++); 
    p--;
    while (n--)
    {
        if ((*p++ = *q++) == 0)
            return ret;
    }
    *p = '\0';
    return ret;
}

10.3模拟实现

char* my_strncat(char* p, const char* q, size_t n)
{
    char* ret = p;
    while (*p++);
    p--;
    while (n--)
    {
        if ((*p++ = *q++) == 0)
            return ret;
    }
    *p = '\0';
    return ret;
}
int main()
{
    char str1[20];
    char str2[20];
    strcpy(str1, "To be ");
    strcpy(str2, "or not to be");
    my_strncat(str1, str2, 6);
    puts(str1);
    return 0;
}

11.各类字符函数

11.1函数 如果参数符合条件返回真

iscntrl 控制字符

isspace 空白字符:‘ ’‘\f’'\n'‘\r’,'\t' '\v'

isdigit 十进制 0~9

isxdigit 十六进制数字,十进制数字,小写字母a~f,大写字母A~F

islower 小写a~z

isupper 大写A~Z

isalpha a~z或A~Z

isalnum 字母或数字,a~z,A~Z,0~9

ispunct 标点符号,不属于数字或字母的可打印字符

isgraph 图形字符

isprint 可打印字符,图形字符和空白字符

11.2字符转换函数

int tolower ( int c );

int toupper ( int c );

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿猿收手吧!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值