超全超详细的字符串操作函数和字符分类函数(附模拟实现)

简介: 超全超详细的字符串操作函数和字符分类函数(附模拟实现)



注:点击蓝色的标题可以跳转到官方网站查阅更权威的函数解释哦。

字符串函数

需要包含头文件<string.h>

strlen

size_t strlen ( const char * str );
  • 字符串以\0作为结束标志,strlen()函数返回的是在字符串中\0前面出现的字符个数(不包含\0
  • 参数指向的字符串必须要以\0结束
  • 注意函数的返回值为size_t,是无符号的(注意无符号和有符号数的大小比较,如果有还不清楚的小伙伴请看这里👉C语言陷阱——无符号数和有符号数的大小比较

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str[] = "abcdefg";
  int len = strlen(str);
  pritnf("%d\n", len);
  return 0;
}

模拟实现:

#include<stdio.h>
size_t my_strlen(const char* str)
{
    size_t count = 0;
    while (*str)
    {
        count++;
        str++;
    }
    return count;
}
int main()
{
    char str[] = "abcdef";
    int len = my_strlen(str);
    printf("len = %d\n", len);
    return 0;
}

strcpy

char * strcpy ( char * destination, const char * source );
  • Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).——将source指向的 C 字符串复制到destination指向的数组中,包括终止的 null 字符(并在该点停止)。
  • 源字符串必须以\0结束
  • 会将源字符串中的\0拷贝到目标空间destination
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可变

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] =  "xxxxxxxxxxxxxxxxxx" ;
  char str2[20] = "abcde";
  printf("%s", strcpy(str1, str2));
  return 0;
}

模拟实现:

#include<stdio.h>
#include<string.h>
char* my_strcpy(char* destination, const char* source)
{
  char* head = destination;
  while (*source)
  {
    *destination++ = *source++;
  }
  *destination = '\0';
  return head;
}
int main()
{
  char str1[20] =  "xxxxxxxxxxxxxxxxxx" ;
  char str2[20] = "abcde";
  printf("%s", my_strcpy(str1, str2));
  return 0;
}

strcmp

int strcmp ( const char * str1, const char * str2 );
  • This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.——此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到终止空字符。
  • 标准规定:
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] =  "bbcdexxxxxx" ;
  char str2[20] = "abcde"; 
  printf("%d\n", strcmp(str1, str2));
  return 0;
}

模拟实现:

#include<stdio.h>
int my_strcmp(const char* str1, const char* str2)
{
  while (*str1 == *str2)
  {
    if (*str1 == '\0')
      return 0;
    str1++;
    str2++;
  }
  if (*str1 > *str2)
    return 1;
  else
    return -1;
}
int main()
{
  char str1[20] =  "bcdexxxxxx" ;
  char str2[20] = "abcde"; 
  printf("%d\n", my_strcmp(str1, str2));
  return 0;
}

strcat

char * strcat ( char * destination, const char * source );
  • Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.——将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。
  • 源字符必须以‘\0’结束
  • 目标空间必须足够大,能够容纳下源字符串的内容
  • 目标空间必须可修改

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] =  "abcde" ;
  char str2[20] = "abcde"; 
  printf("%s\n", strcat(str1, str2));
  return 0;
}

模拟实现:

#include<stdio.h>
char* my_strcat(char* destination, const char* source)
{
  char* head = destination;
  while (*destination)
    destination++;
  while (*source)
  {
    *destination++ = *source++;
  }
  *destination = '\0';
  return head;
}
int main()
{
  char str1[20] =  "abcde" ;
  char str2[20] = "abcde"; 
  printf("%s\n", my_strcat(str1, str2));
  return 0;
}

前面我们提到的字符串函数strcpy(), strcmp(), strcat(),可以说只有遇到结束符\0函数才会停止,跟传入的字符串长度没有关系,我们将这一类字符串函数称为长度不受限制的字符串函数。与之对应的,我们也有三个与之对应的长度受限制的字符串函数strncpy(), strncmp(), ctrncat()

strncpy

char * strncpy ( char * destination, const char * source, size_t num );
  • Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.——将源的第一个字符数复制到目标。如果在复制 num 个字符之前找到源 C 字符串的末尾(由 null 字符表示),则目标将填充零,直到总共写入 num 个字符为止
  • 拷贝num个字符从源字符串到目标空间
  • 如果原字符串的长度小于num,则拷贝完源字符串后,在目标的后面追加0,直到num个

具体使用:

#include<stdio.h>
#include<string.h>
nt main()
{
  char str1[20] =  "xxxxxxxxxxxxxxxxxxxx" ;
  char str2[20] = "abcde"; 
  printf("%s\n", strncpy(str1, str2, 20));
  return 0;
}

模拟实现:

#include<stdio.h>
char* my_strncpy(char* destination, const char* source, size_t num)
{
  char* head = destination;
  while (num && *source)
  {
    num--;
    *destination++ = *source++;
  }
  while (num--)
    *destination++ = '\0';
  return head;
}
int main()
{
  char str1[20] =  "x" ;
  char str2[20] = "abcde"; 
  printf("%s\n", my_strncpy(str1, str2, 4));
  return 0;
}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );
  • Compares up to num characters of the C string str1 to those of the C string str2.
    This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ, until a terminating null-character is reached, or until num characters match in both strings, whichever happens first.——将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较。此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或直到达到终止的空字符亦或者直到两个字符串中的 num 字符匹配,以先发生者为准。
  • 标准规定:
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] = "abcdf" ;
  char str2[20] = "abcde"; 
  int ret = (str1, str2, 5);
  if (ret == 0)
    printf("Equal: %d\n",ret);
  else
    printf("No Equal: %d\n", ret);
  return 0;
}

模拟实现:

#include<stdio.h>
int my_strncmp(const char* str1, const char* str2, size_t num)
{
  while (num && *str1 == *str2)
  {
    if (*str1 == '\0')
      return 0;
    str1++;
    str2++;
    num--;
    if (num == 0)
      return 0;
  }
  if (*str1 > *str2)
    return 1;
  else
    return -1;
}
int main()
{
  char str1[20] = "abcdf" ;
  char str2[20] = "abcde"; 
  int ret = my_strncmp(str1, str2, 5);
  if (ret == 0)
    printf("Equal: %d\n",ret);
  else
    printf("No Equal: %d\n", ret);
  return 0;
}

strncat

char * strncat ( char * destination, const char * source, size_t num );
  • Appends the first num characters of source to destination, plus a terminating null-character.If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.——将源的第一个数字字符追加到目标,外加一个终止空字符。如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] =  "x" ;
  char str2[20] = "abcde"; 
  printf("%s\n", strncat(str1, str2, 10));
  return 0;
}

模拟实现:

#include<stdio.h>
char* my_strncat(char* destination, const char* source, size_t num)
{
  char* head = destination;
  while (*destination)
    destination++;
  while (num && *source)
  {
    num--;
    *destination++ = *source++;
  }
  return head;
}
int main()
{
  char str1[20] =  "x" ;
  char str2[20] = "abcde"; 
  printf("%s\n", my_strncat(str1, str2, 5));
  return 0;
}

strstr

char * strstr ( const char * str1, const char * str2 );
  • Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.——返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回一个空指针。
  • 即找到子串str2在主串中第一次出现的位置,并返回指向这个位置的指针,如果如果 str2 不是 str1 的一部分,则返回一个空指针。

具体使用:

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[20] = "abcdfababcde" ;
  char str2[20] = "abcde"; 
  printf("%s\n", strstr(str1, str2));
  return 0;
}

模拟实现:

注:关于strstr的模拟实现博主专门写了一篇博文来进行详细的说明,大家感兴趣可以看看模拟实现strstr详解

暴力实现:

#include<stdio.h>
#include<string.h>
char* my_strstr(const char* str1, const char* str2)
{
  int len1 = strlen(str1);
  int len2 = strlen(str2);
  if (len2 > len1)
    return NULL;
  while (*str1)
  {
    if (*str1 != *str2)
      str1++;
    else
    {
      char* temp1 = str1;
      char* temp2 = str2;
      while (*temp2 && *temp1 == *temp2)
      {
        temp1++;
        temp2++;
      }
      if (*temp2 == '\0')
        return str1;
      else
        str1++;
    }
  }
  return NULL;
}
int main()
{
  char str1[20] = "abcdfababcde" ;
  char str2[20] = "abcde"; 
  printf("%s\n", my_strstr(str1, str2));
  return 0;
}

KMP实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetNext(int* next, char* str)
{
  int len = strlen(str);
  next[0] = -1;
  int k = -1;
  int begin = 1;
  while (begin < len)
  {
    if (k == -1 || str[begin - 1] == str[k])
    {
      next[begin] = k + 1;
      k++;
      begin++;
    }
    else
    {
      k = next[k];
    }
  }
}
char* my_strstr(const char* str1, const char* str2)
{
  int len1 = strlen(str1);
  int len2 = strlen(str2);
  if (len2 > len1)
    return NULL;
  int* next = (int*)malloc(sizeof(int) * len2);
  GetNext(next, str2);
  int begin1 = 0;
  int begin2 = 0;
  while (begin1 < len1 && begin2 < len2)
  {
    if (str1[begin1] == str2[begin2])
    {
      begin1++;
      begin2++;
    }
    else
    {
      if (begin2 == 0)
        begin1++;
      else
        begin2 = next[begin2];
    }
  }
  if (begin2 == len2)
    return &str1[begin1 - begin2];
  else
    return NULL;
}
int main()
{
  char str1[20] = "abcdfababcde" ;
  char str2[20] = "abcde"; 
  printf("%s\n", my_strstr(str1, str2));
  return 0;
}

strtok

char * strtok ( char * str, const char * delimiters);
  • delimiters参数是一个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或多个由delimiters字符串中一个或者多个分隔符分割的标记
  • strtok函数找到str中的下一个标记,并将其用‘\0’结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
  • strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
  • 如果字符串中不存在更多的标记,则返回NULL指针

具体使用:

#include<stdio.h>
#include<string.h>
void Text1()
{
  char str[] = "hhh333@qq.com";
  char seq[] = "@.";
  char _str[100] = { 0 };
  strcpy(_str, str);
  printf("%s\n", strtok(_str, seq));
  printf("%s\n", strtok(NULL, seq));
  printf("%s\n", strtok(NULL, seq));
}
void Text2()
{
  char str[] = "hhh333@qq.com";
  char seq[] = "@.";
  char _str[100] = { 0 };
  strcpy(_str, str);
  char* temp = strtok(_str, seq);
  for (; temp != NULL; temp = strtok(NULL, seq))
  {
    printf("%s\n", temp);
  }
}
int main()
{
  Text1();
  Text2();
  return 0;
}

模拟实现:

char* my_strtok(char* str, const char* delimiters)
{
  static char* temp = NULL;
  if (str != NULL)
  {
    char* head1 = str;
    while (*head1)
    {
      char* head2 = delimiters;
      while (*head2)
      {
        if (*head1 != *head2)
          head2++;
        else
        {
          *head1 = '\0';
          temp = head1 + 1;
          return str;
        }
      }
      head1++;
    }
    return str;
  }
  else
  {
    if (temp == NULL)
      return NULL;
    char* head1 = temp;
    char* cur = temp;
    while (*head1)
    {
      char* head2 = delimiters;
      while (*head2)
      {
        if (*head1 != *head2)
          head2++;
        else
        {
          *head1 = '\0';
          temp = head1 + 1;
          return cur;
        }
      }
      head1++;
    }
    temp = NULL;
    return cur;
  }
}
void Text2()
{
  char str[] = "hhh333@qq.com";
  char seq[] = "@.";
  char _str[100] = { 0 };
  strcpy(_str, str);
  char* temp = my_strtok(_str, seq);
  for (; temp != NULL; temp = my_strtok(NULL, seq))
  {
    printf("%s\n", temp);
  }
}
int main()
{
  Text2();
  return 0;
}

strerror

char * strerror ( int errnum );
  • 返回错误码所对应的错误信息
  • 这里有必要进行说明:
  • 库函数在执行的时候,如果发生了错误,会将一个错误码存放在errno这个自带的全局变量中
  • 我们可以来看看数字1~9所对应的错误信息(0表示正常):
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
  for (int i = 1; i < 9; i++)
    printf("%s\n", strerror(i));
  return 0;
}

output:

/*
Operation not permitted
No such file or directory
No such process
Interrupted function call
Input/output error
No such device or address
Arg list too long
Exec format error
*/

具体使用:

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
  FILE* fp = fopen("unexist.txt", "r");
  if (fp == NULL)
  {
    printf("Error opening unexist.txt: %s\n", strerror(errno));
        //errno: Last error number
  }
    fclose(fp);
  return 0;
}

字符分类函数

函数 如果它的参数符合下列条件就返回真
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 任何可打印字符,包括图形字符和空白字符

注:ASCII为0~31的字符均为不可打印字符

相关文章
|
6月前
|
算法 C语言 开发者
C语言精确统计字符串中的神秘字符
C语言精确统计字符串中的神秘字符
37 0
|
存储 安全 C语言
【C语言】字符分类函数、字符转换函数、内存函数
【C语言】字符分类函数、字符转换函数、内存函数
69 0
【C语言】字符分类函数、字符转换函数、内存函数
|
21天前
|
C++
字符类函数
字符类函数
13 4
|
5月前
|
安全 编译器 C语言
【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数
【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数
|
6月前
|
C语言
【C语言】字符分类函数与字符转换函数
【C语言】字符分类函数与字符转换函数
52 1
|
6月前
|
C语言
字符函数和字符串函数解析及模拟实现
字符函数和字符串函数解析及模拟实现
74 0
|
6月前
|
C语言
C语言字符分类函数汇总
C语言字符分类函数汇总
|
C语言 C++
C/C++字符函数和字符串函数详解————内存函数详解与模拟
C/C++字符函数和字符串函数详解————内存函数详解与模拟
49 1
|
存储
字符函数和字符串函数的使用及模拟实现(上)(1)
字符函数和字符串函数的使用及模拟实现(上)
60 0
字符函数和字符串函数的使用及模拟实现(上)(2)
字符函数和字符串函数的使用及模拟实现
87 0