一文带你玩转C库中的一系列字符串函数

简介: 一文带你玩转C库中的一系列字符串函数

目录

前言

求字符串长度

strlen的介绍与使用

strlen的模拟实现

方法一 计数器

递归二 递归

方法三 指针 - 指针

长度不受限制的字符串函数

strcpy的介绍和使用

strcpy的模拟实现

strcat的介绍和使用

strcat的模拟实现

strcmp的介绍和使用

strcmp的模拟实现

长度受限制的字符串函数

strncpy的介绍和使用

strncpy的模拟实现

strncat的介绍和使用

strncat的模拟实现

strncmp的介绍和使用

strncmp的模拟实现

字符串查找函数

strstr的介绍和使用

strstr的模拟实现

strtok的介绍

strtok的使用

错误信息报告

strerror的介绍和使用

字符分类函数

字符转换函数

转换函数的使用


前言

在大家使用C语言进行编程的时候,我们可以发现C中对字符和字符串的处理十分的频繁,但是呢,c它本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。字符串常量只使用于那些对它不做修改的字符串函数,字符数组可适用于任何字符串函数。今天,我们就要对这些函数一探究竟。

求字符串长度

strlen的介绍与使用

size_t strlen ( const char * str )
//strlen的使用
#include <stdio.h>
#include <string.h>
int main()
{
  char arr[] = "abcdef";
  size_t ret = strlen(arr);
  printf("%zu\n", ret);
  return 0;
}

字符串的'\0'作为结束标志,strlen返回的是'\0'前面出现的字符个数,'\0'不计入其中。

参数指向的字符串必须要以'\0'为结束。

strlen的返回值的类型为size_t,是无符号的。

这里解释一下第三个说明,举个栗子:通过下面代码我们可以发现arr1的长度明显大于arr2的长度,但是结果却是>。这就是因为strlen的返回类型是无符号的,两个无符号的相减,得到的还是无符号的。

int main()
{
  char arr1[] = "xxxxxxx";
  char arr2[] = "xxxx";
  if (strlen(arr2) - strlen(arr1) > 0)
    printf(">");
  else
    printf("<");
  return 0;
}

strlen的模拟实现

方法一 计数器

int my_strlen(char* str)
{
  int count = 0;
  while (*str != '\0')
  {
    count++;
    str++;
  }
  return count;
}
int main()
{
  char arr[] = "abcdef";
  int ret = my_strlen(arr);
  printf("%d\n", ret);
  return 0;
}

递归二 递归

int my_strlen(char* str)
{
  if (*str == 0)
    return 0;
  else
    return 1 + my_strlen(str + 1);
}
int main()
{
  char arr[] = "abcdef";
  int ret = my_strlen(arr);
  printf("%d\n", ret);
  return 0;
}

方法三 指针 - 指针

int my_strlen(char* str)
{
  char* p = str;
  while (*str != '\0')
  {
    str++;
  }
  return str - p;
}
int main()
{
  char arr[] = "abcdef";
  int ret = my_strlen(arr);
  printf("%d\n", ret);
  return 0;
}

长度不受限制的字符串函数

strcpy的介绍和使用

char * strcpy ( char * destination, const char * source )
//使用strcpy函数
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "XXX";
  strcpy(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}

源字符串必须以'\0'结束

会将字符串中的'\0'拷贝到目标空间

目标空间必须可变

这里解释一下第三个说明:strcpy的第一个参数只能是可变参数,也就是字符数组。不能是常量字符串,因为它不能改变。

strcpy的模拟实现

//模拟实现strcpy函数
//优化前
char* my_strcpy(char* dest, char* source)
{
  char* ret = dest;
  while (*source != '\0')
  {
    *dest = *source;
    dest++;
    source++;
  }
  *dest = '\0';
  return ret; 
}
//优化后
char* my_strcpy(char* dest, const char* source)
{
  char* ret = dest;
  assert(dest && source);
  while (*dest++ = *source++);
  return ret;
}
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "XXX";
  my_strcpy(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}

strcat的介绍和使用

char * strcat ( char * destination, const char * source )
//使用strcat函数
int main()
{
  char arr1[20] = "abcdef";
  char arr2[] = "xxxxx";
  strcat(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}

源字符串必须以'\0'结束

目标空间必须有足够的大,可以容纳下源字符串的内容

目标空间必须可以修改

这里解释一下第二个说明:因为要将源字符串放到目标字符串后面,所以他的空间大小必须大于等于两个字符串的大小,不然会溢出。

strcat的模拟实现

//模拟实现strcat
char* my_strcat(char* str1, const char* str2)
{
  assert(str1 && str2);
  char* ret = str1;
  while (*str1)
  {
    str1++;
  }
  while (*str1++ = *str2++);
  return ret;
}
int main()
{
  char arr1[20] = "abcdef";
  char arr2[] = "XXXX";
  my_strcat(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}

strcmp的介绍和使用

int strcmp ( const char * str1, const char * str2 );
//使用strcmp函数
int main()
{
  char arr1[] = "adcdef";
  char arr2[] = "adsdf";
  int ret =strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}

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

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

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

它们比较的是对应字符的ASCII码值,要是相等就比较下一个

strcmp的模拟实现

//模拟实现strcmp函数
int my_strcmp(const char* str1, const char* str2)
{
  assert(str1 && str2);
  while (*str1 == *str2)
  {
    if (*str1 == '\0')
      return 0;
    else
    {
      str1++;
      str2++;
    }
  }
  if (*str1 > *str2)
    return 1;
  else if (*str1 < *str2)
    return -1;
}
int main()
{
  char  arr1[] = "adcdef";
  char arr2[] = "abcdef";
  int ret = my_strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}

长度受限制的字符串函数

strncpy的介绍和使用

char * strncpy ( char * destination, const char * source, size_t num )
//使用strncpy函数
int main()
{
  char arr1[] = "adcdefdsaf";
  char arr2[] = "XXXxx";
  strncpy(arr1, arr2, 3);
  printf("%s\n", arr1);
  return 0;
}

拷贝num个字符从源字符串到目标字符串

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

strncpy的模拟实现

//模拟strncpy
char* my_strncpy(char* dest, const char* str, int num)
{
 assert(dest && str);
  char* ret = dest;
  int i = 0;
  for (i = 1; i <= num; i++)
  {
    if (strlen(ret) < i)
    {
      *dest = '\0';
    }
    *dest = *str;
    dest++;
    str++;
  }
  return ret;
}
int main()
{
  char arr1[] = "adcdefdsaf";
  char arr2[] = "XXXxx";
  my_strncpy(arr1, arr2, 8);
  printf("%s\n", arr1);
  return 0;
}

strncat的介绍和使用

char * strncat ( char * destination, const char * source, size_t num )
//使用strncat函数 
int main()
{
  char arr1[20] = "adcdefdsaf";
  char arr2[] = "XXXxxxx";
  strncat(arr1, arr2, 5);
  printf("%s\n", arr1);
  return 0;
}

将源字符串 的第一个数字字符追加到目标,外加一个终止空字符。

如果源字符串中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。

strncat的模拟实现

//模拟strncat函数
char* my_strncat(char* dest, const char* str, int num)
{
  char* ret = dest;
  assert(dest && str);
  while (*dest != '\0')
  {
    dest++;
  }
  int count = 0;
  int count = 0;
  while (count++, count<=num && count<=strlen(str))
  {
      *dest = *str;
      dest++;
      str++;
  }
  *dest = '\0';
  return ret;
}
int main()
{
  char arr1[20] = "adcdefd";
  char arr2[] = "XXXxxxx";
  my_strncat(arr1, arr2, 19);
  printf("%s\n", arr1);
  return 0;
}

strncmp的介绍和使用

int strncmp ( const char * str1, const char * str2, size_t num )
//使用strncmp函数
int main()
{
  char arr1[] = "abcdefg";
  char arr2[] = "abces";
  int ret = strncmp(arr1, arr2, 4);
  printf("%d\n", ret);
  return 0;
}

比较出现字符不一样或者一个字符串结束或者num个字符全部比较完

strncmp的模拟实现

//模拟strncmp函数
int my_strncmp(char* str1, char* str2, int num)
{
  int i = 0;
  for (i = 1; i <= num; i++)
  {
    if (*str1 == *str2)
    {
      if (*str1 == '\0')
        return 0;
      str1++;
      str2++;
    }
    else if (*str1 > *str2)
      return 1;
    else if (*str1 < *str2)
      return -1;
  }
}
int main()
{
  char arr1[] = "aefg";
  char arr2[] = "abces";
  int ret = my_strncmp(arr1, arr2, 4);
  printf("%d\n", ret);
  return 0;
}

字符串查找函数

strstr的介绍和使用

char * strstr ( const char * str1, const char * str2 )
//使用strstr函数
int main()
{
  char arr1[] = "abbbcd";
  char arr2[] = "bbc";
  char* p = strstr(arr1, arr2);
  puts(p);
  return 0;
}

作用是返回指向 str2 中第一次出现的 str1 的指针,如果 str2 不是str1 的一部分,则返回一个空指针。匹配过程不包括终止空字符,但它到此为止。

返回值是指向 str1 中指定的整个字符序列在 str2 中首次出现的指针,如果序列在 str1 中不存在,则为 null 指针。

strstr的模拟实现

//模拟实现strstr函数
char* my_strstr(char* dest, const char* source)
{
  assert(dest && source);
  char* cp = dest;
  char* s1 = dest;
  char* s2 = source;
  if (*source == '\0')
    return dest;
  while (*cp != '\0')
  {
    while (*s1 == *s2&& *s1 && *s2)
    {
      s1++;
      s2++;
    }
    if (*s2 == '\0')
      return cp;
    else
    {
      cp++;
      s1 = cp;
      s2 = source;
    }
  }
  return NULL;
}
int main()
{
  char arr1[] = "abbbbcd";
  char arr2[] = "bbc";
  my_strstr(arr1, arr2);
  printf("%s\n", my_strstr(arr1, arr2));
  return 0;
}

strtok的介绍

char * strtok ( char * str, const char * delimiters )

delimiters参数是一个字符串,定义了用做分隔符的集合

第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分割符

strtok函数找到str中的下一个标记,并将其用'\0'结尾,返回一个指向这个标记的指针注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)

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

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

如果字符串中不存在更多的标记,则返回 NULL 指针。

strtok的使用

//使用strtok函数
int main()
{
  char arr[] = "3435151626@qq.com";
  char cpy[20];
  strcpy(cpy, arr);
  char* ret = NULL;
  char sep[] = "@.";
  for (ret = strtok(cpy, sep); ret != NULL; ret = strtok(NULL, sep))
  {
    printf("%s\n", ret);
  }
  return 0;
}

错误信息报告

strerror的介绍和使用

char * strerror ( int errnum );
//使用strerror函数
int main()
{
  int i = 0;
  for (i = 0; i < 9; i++)
  {
    printf("%d: %s\n", i, strerror(i));
  }
  return 0;
}

对应的错误信息

字符分类函数屏幕截图 2023-07-12 234322.png

字符转换函数

int tolower ( int c );
int toupper ( int c );

tolower将大写转小写

toupper将小写转大写

转换函数的使用

int main()
{
    char ch[10] = { 0 };
  gets(ch);
  char* p = ch;
  while (*p)
  {
    if (isupper(*p))
    {
      *p = tolower(*p);
    }
    p++;
  }
  printf("%s\n", ch);
  return 0;
}


目录
相关文章
|
1月前
|
安全 C语言 C++
|
6月前
|
安全 C语言
需要知道的字符串函数
需要知道的字符串函数
|
存储 C语言
字符串函数介绍&应用(一)
字符串函数介绍&应用
|
6月前
|
C语言
字符函数和字符串函数
字符函数和字符串函数
68 0
|
C语言 Python
字符函数和字符串函数(下)
字符函数和字符串函数(下)
53 0
字符函数和字符串函数(下)
|
11月前
|
C语言
字符函数和字符串函数(上)
字符函数和字符串函数
|
11月前
|
C语言
字符函数和字符串函数(下)
字符函数和字符串函数(下)
|
12月前
|
编译器
C详细的字符串函数
C详细的字符串函数
66 0
|
11月前
|
C语言
详解字符函数和字符串函数-2
详解字符函数和字符串函数
48 0
|
编译器 C语言 Python
字符函数和字符串函数(上)
字符函数和字符串函数(上)
46 0