c语言学习第二十七课 ——一些内存函数与字符串函数

简介: c语言学习第二十七课 ——一些内存函数与字符串函数

strtok函数

592270ddb2704d8f8f43078def706205.png

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

返回的是分割符标记的起始位置

函数作用   给一个邮箱  kajsoijfdcoaioij@.com           @ 。被叫做分割符

该函数作用就是提取这些分割符。

第一的参数为字符串,sep参数是个字符串,定义了用做分割符字符的集合

53c130267e4c43a9ad9f1c35454ba4bb.png  例如

int main()
{
  char arr[] = " kajsoijfdcoaioij@.com ";
  const char* p = "@.";
  char bufer[30] = { 0 };
  char* str = strtok(bufer, p);
  strcpy(bufer, arr);
  //该函数会改变字符串中的分隔符为\0;
  strtok(bufer, p);
  //strtok传的第一个参数不为空指针时,读入,当遇到分割符时,变为\0,切割掉返回空指针,保c存分割符的位置,继续进行切割,寻找下一个分割符
  //常量i昂字符无法修改
  strtok(NULL, p);
  printf("%s\n", str);
  strtok(NULL, p);
  printf("%s\n", str);
  strtok(NULL, p);
  printf("%s\n", str);
  //
  char* str = NULL;
  for (str = strtok(bufer, p); str= NULL;str = strtok(NULL,p))
  {
    printf("%s\n", str);
  }
  return 0;
}

strerror函数

a7889810197540ebacdfe5a738be95e3.png

e9431c8cfe014b22b6b1e69a737ca884.png

返回错误码所对应的错误信息

char *strerror()

每一个错误码都有错误信息

c语言的库函数再调用失败的时候,会将一个错误码存放在一个叫error的变量中,当我们想知道调用库函数的时候发生了什莫错误,就可以把error里的错误码翻译为错误信息。 例

int main()
{
  char* p = strerror(0);
  printf("%s\n", p);
  char* p = strerror(1);
  printf("%s\n", p);
  char* p = strerror(2);
  printf("%s\n", p);
  char* p = strerror(3);
  printf("%s\n", p);
  return 0;
}

举例打印文件打开错误

int main()
{
  //打开文件
  FILE* p = fopen("text.txt", "r");//如果打开方式是“r”,若文件存在则打开成功,否则失败
  //这里未建立这样的文件
  if (p == NULL)
  {
    printf("打开失败,原因是%s\n",strerror(errno));//显示错误 errno中把错误码翻译成错误信息
    //perror函数  打印错误信息
    //perror("文件打开失败");把定义的错误信息后在打印错误信息,可以理解为printf+strerror结合函数。
  }
  //读写文件
  //关闭文件
  fclose(p);
  p = NULL;
  return 0;
}

这里还有许多常用的字符判断函数。其用法相似。

8abb01dd77c54e6d9777bfcbd7efd52a.png

df98fa0a714c4129accb92367c436ed2.png

isdigit

55cdf4f87d204a63920e9f76359ceea2.png

7abc8d39d13a4dbe8adab6fbba040be7.png

isspace     isxdigit   islower  issupper    isalpha   isaipha等的函数.

内存函数

不同于字符串函数,这里可以实现各种类型的数据的函数。

memcpy

3c22bd78b7b04080b9ab274467a1e733.png

fa4b2f4ee6864cc6a5bcdefdf7ca0c19.png

例如

int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8,9 };
  int arr2[] = { 0 };
  //memcpy,拷贝数据
  memcpy(arr2, arr1, 20);//把arr1中的5个整形拷贝到arr2中 , size_t num为所拷贝数据内存大小,
    float arr1[] = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
  float arr2[] = {0.0};
  memcpy(arr2, arr1, 12);//把arr1中的5个整形拷贝到arr2中 
  return 0;
}

函数实现

void* my_memcpy(const void*str,const void *ptr,size_t num)
{
  void* ret = str;
  assert(str && ptr);//断言判断是否为指针
  while (num--)
  {
       *(char*)str = *(char*)ptr;
     str = (char*)str + 1;
      ptr = (char*)str + 1;
  }
  return ret;
}

在内存重叠时使用memcpy可能出现其他结果,这时使用memmove,不会重现重叠,数据覆盖

例如  

memmove

2b8e13b8102648f8954b11bbd393a5a2.png

void* memmove(void* destinnation, void* source, size_tnum)

a3a9c6f54ea64672ba8ed97f93113954.png

int main()
{
  int  arr1[] = {1,2,3,4,5,6,7,8,9};
  int  arr2[] = { 1,2 };
  memmove(arr2+2, arr1, 12);//把arr1中的5个整形拷贝到arr2中 
  return 0;
}

函数实现

void* my_memmove(const void* str, const void* ptr, size_t num)
{
  //从前往后拷贝和从后往前拷贝
  //分情况讨论
  //当str<ptr  从前往后拷贝
  //当str>ptr  从后往前拷贝
  assert(str && ptr);
  void* ret = str;
  if (str < ptr)
  {   
    *(char*)str = *(char*)ptr;
    str = (char*)str + 1;
    ptr = (char*)str + 1;
  }
  else
  {
    //后->前
    while (num--)
    {
      *((char*)str + num) = *((char*)ptr + num);
    }
  }
  return ret;
}

这里存在分情况讨论是因为如图

4594c406215e4a9d8ce3d52eaea0227f.png

memcmp

1ce94f6f094245c1b653c0608a78c8d3.png

cecc5ab60d19407390cc9e9a703f98ab.png

void test()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9 };
  int arr1[] = { 1,2,4,6 };
  int ret = memcmp(arr,arr1, 16);
  printf("%d\n", ret);
}

memset

19e4e168727749e2abe076dbb114d88b.png

025bb07699cc4d7fb5ade84ab9c5ad09.png

相关文章
|
20天前
|
存储 人工智能 搜索推荐
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
Mem0 是专为 AI 代理设计的内存层,支持记忆、学习与进化。提供多种记忆类型,可快速集成,适用于开源与托管场景,助力 AI 代理高效交互与成长。
236 123
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
|
7天前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
323 0
|
2月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
126 26
|
2月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
241 15
|
7月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
194 1
一文彻底搞清楚C语言的函数
|
8月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
378 23
|
8月前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
310 15
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
|
8月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
151 24
|
8月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
370 16