【C语言】字符函数和字符串函数(一)—>库函数的介绍与模拟实现(下)

简介: 【C语言】字符函数和字符串函数(一)—>库函数的介绍与模拟实现(下)

(六)字符操作

(11)字符分类函数

函数 如果他的参数符合下列条件就返回真
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的字符都是不可打印字符。

#include <ctype.h>
int main()
{
  printf("%d\n", isupper('a'));
  printf("%d\n", isdigit('2'));
  return 0;
}

注:有关字符分类函数和字符转换函数都需要引用头文件ctype.h。

(12)字符转换

int tolower ( int c );转换为小写字符

int toupper ( int c );转换为大写字符

应用:

#include <ctype.h>
int main()
{
  char arr[20] = { 0 };
  gets(arr);//遇到空格继续读
  char* p = arr;
  while (*p)
  {
    if (isupper(*p))// *p>='A' && *p<='Z'
    {
      *p = tolower(*p);//*p = *p+32;
    }
    p++;
  }
  printf("%s\n", arr);
  return 0;
}

(七)内存操作函数

(13)memcpy

void* memcpy( void* destination, const void* source, size_t num );

该函数从source的位置开始向后复制num个字节的数据到destination的内存位置。

  • 该函数在遇到'\0'的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的,即memcpy是用来处理不重叠的内存拷贝的。

请参考模拟实现部分方便理解。

(14)memmove

void* memmove( void* destination, const void* source, size_t num );

该函数的功能与memcpy相近,差别在memmove函数处理的源内存块和目标内存块是可以重叠的。

  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理,当然不重叠拷贝也可以使用memmove,在未来应用时,不管两空间重不重叠都是用memmove即可

那么为什么memmove可以处理重叠内存的数据呢,请以下图参考模拟实现代码理解:

(15)memcmp

int memcmp( const void* ptr1, const void* ptr2, size_t num );

该函数作用为比较从ptr1和ptr2指针开始的num个字节,返回值同strncmp。

(16)memset

void* memset( void* ptr, int value, size_t num);

该函数的作用为将ptr指针开始的num个字节的数据设置为value。

二、模拟实现

(一)strlen

(1)计数器

//计数器方式
int my_strlen(const char* str)
{
  int count = 0;
  while (*str)
  {
    count++;
    str++;
  }
  return count;
}

(2)递归

//不能创建临时变量计数器
int my_strlen(const char* str)
{
  if (*str == '\0')
    return 0;
  else
    return 1 + my_strlen(str + 1);
}

(3)指针-指针

//指针-指针的方式
int my_strlen(char* s)
{
  char* p = s;
  while (*p != '\0')
    p++;
  return p - s;
}

(二)strcpy

#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
  char* ret = dest;
  assert(dest && src);//断言两个指针都为非空指针
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}

(三)strcat

#include<assert.h>
char* my_strcat(char*dest, const char *src)
{
  assert(dest && src);//断言两个指针都为非空指针
  char* ret = dest;
  //1. 找目标空间中的\0
  while (*dest)
  {
    dest++;
  }
    //2. 赋值
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}

(四)strcmp

#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
  assert(str1 && str2);
    //断言两个指针为非空指针
  while (*str1 == *str2)
  {
    if (*str1 == '\0')
      return 0;
    str1++;
    str2++;
  }
  return (*str1 - *str2);
}

(五)strstr

char* my_strstr(char *str1, char* str2)
{
  char* cp = str1;
  char* s1 = cp;
  char* s2 = str2;
  if (*str2 == '\0')
    return str1;
  while (*cp)
  {
    //开始匹配
    s1 = cp;
    s2 = str2;
    while (*s1 && *s2 && *s1 == *s2)
    {
      s1++;
      s2++;
    }
    if (*s2 == '\0')
      return cp;
    cp++;
  }
  return NULL;
}

(六)memcpy

#include<assert.h>
void* memcpy(void* dest, const void* src, size_t num)
{
  void* ret = dest;
  assert(dst && src);//断言两个指针为非空指针
  while (num--) 
  {
    *(char*)dest = *(char*)src;//强制转化为char*为一个字节方便逐个赋值
    dest = (char*)dest + 1;
    src = (char*)src + 1;
  }
  return ret;
}

注意:

由于dest与src为void*类型,所以不能直接++或--,可以使用

dest = (char*)dest + 1;

src = (char*)src + 1;

而不是dest++;   src++

(七)memmove

#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
  void* ret = dest;
  assert(dest && src);//断言两个指针为非空指针
  if (dest < src)
  {
    //前->后
    while (num--)
    {
      *(char*)dest = *(char*)src;
      dest = (char*)dest + 1;
      src = (char*)src + 1;
    }
  }
  else
  {
    //后->前
    while (num--)
    {
      *((char*)dest + num) = *((char*)src + num);
    }
  }
  return ret;
}

本篇内容就到这里,下一篇文章仍然是对字符串的讨论,我会引入旋转字符串的两种巧妙方法,关注博主不迷路🔥🔥🔥

目录
相关文章
|
20天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
40 10
|
20天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
42 9
|
20天前
|
存储 Unix Serverless
【C语言】常用函数汇总表
本文总结了C语言中常用的函数,涵盖输入/输出、字符串操作、内存管理、数学运算、时间处理、文件操作及布尔类型等多个方面。每类函数均以表格形式列出其功能和使用示例,便于快速查阅和学习。通过综合示例代码,展示了这些函数的实际应用,帮助读者更好地理解和掌握C语言的基本功能和标准库函数的使用方法。感谢阅读,希望对你有所帮助!
32 8
|
20天前
|
C语言 开发者
【C语言】数学函数详解
在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
41 6
|
20天前
|
存储 C语言 开发者
【C语言】格式化输出占位符及其标志字符详解(基于ISO/IEC 9899:2024)
在C语言中,格式化输出通过 `printf` 函数等格式化输出函数来实现。格式说明符(占位符)定义了数据的输出方式,标准ISO/IEC 9899:2024(C23)对这些格式说明符进行了详细规定。本文将详细讲解格式说明符的组成部分,包括标志字符、宽度、精度、长度修饰符和类型字符,并适当增加表格说明。
39 6
|
20天前
|
存储 C语言
【C语言】输入/输出函数详解
在C语言中,输入/输出操作是通过标准库函数来实现的。这些函数分为两类:标准输入输出函数和文件输入输出函数。
116 6
|
20天前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
49 6
|
20天前
|
C语言 开发者
【C语言】断言函数 -《深入解析C语言调试利器 !》
断言(assert)是一种调试工具,用于在程序运行时检查某些条件是否成立。如果条件不成立,断言会触发错误,并通常会终止程序的执行。断言有助于在开发和测试阶段捕捉逻辑错误。
28 5
|
2月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
40 3
|
1月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
52 4