『C语言进阶』字符函数和内存函数(2)

简介: 『C语言进阶』字符函数和内存函数(2)

一、strtok函数

1.1 函数认识

函数功能:

字符串拆分为标记

strtok函数的应用:

#include<stdio.h>
#include<string.h>
int main()
{
  const char* p = "@.";
  char arr[] = "abcdefg@ighgl.whiss";
  char buf[100] = { 0 };//因为字符串会被修改,所以要把arr临时拷贝到buf里
  //保证arr不被修改
  strcpy(buf, arr);
  char* str = strtok(buf, p);
  printf("%s\n", str);
  str = strtok(NULL, p);
  printf("%s\n", str);
  str = strtok(NULL, p);
  printf("%s\n", str);
  return 0;
}

更方便的代码展示:

#include<stdio.h>
#include<string.h>
int main()
{
  const char* p = "@.";
  char arr[] = "abcdefg@ighgl.whiss";
  char buf[100] = { 0 };//因为字符串会被修改,所以要把arr临时拷贝到buf里
  //保证arr不被修改
  strcpy(buf, arr);
  char* str = NULL;
  for (str = strtok(buf, p); str != NULL; str = strtok(NULL, p))
  {
    printf("%s\n", str);
  }
  return 0;
}

1.2 注意事项

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

二、strerror函数

2.1 函数认识

函数功能:

返回错误代码,所对应的错误信息(把错误代码翻译成错误信息)

C语言中规定了一些信息

错误码——错误信息

0——No Error

1——……

2——……

当库函数使用的时候,发生错误的时候会把errno这个全局的错误变量设置为本次执行库函数产生的错误码。

errno是C语言提供的全局变量,可以直接使用,放在errno.h这个文件

所以要引用#include<errno.h>

strerror(errno);就会把错误显示出来

头文件:

#include<errno.h>
• 1

strerror函数的使用:

#include<stdio.h>
int main()
{
  FILE* pf = fopen("date.txt", "r");
  if (pf == NULL)
  {
    //printf("%s\n", strerror(errno));
    perror("fopen");
    return 1;
  }
  return 0;
}

2.2 注意事项

报错的是程序运行过程中的运行的错误


三、memcpy函数

3.1 函数认识

函数功能:

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

头文件:

#include<string.h>

memcpy函数的使用:

#include<stdio.h>
int main()
{
  char arr1[] = "abcdef";
  char arr2[50] = { 0 };
  strcpy(arr2, arr1);
  int arr3[] = { 1,2,3,4,5,6,7 };
  int arr4[5] = { 0 };
  memcpy(arr4, arr3, 20);
  for (int i = 0; i < 5; i++)
    printf("%d ", arr4[i]);
  return 0;
}

C语言只要求memcpy能拷贝不重叠的内存空间就足够了,memmove去处理那些重叠的内存空间,但是VS的memcpy可以处理重叠的内存拷贝,也可以处理不重叠的内存拷贝

3.2 注意事项

  • 这个函数在遇到’\0’的时候并不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。如果destination在source的后面,就可能导致刚改变的destination的内容,又变成了source,就会导致重复,这种情况建议使用memmove就不会发生

3.3 模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h> 
void* my_memcpy(void* dest, const void* src, int num)
{
  assert(dest && src);
  void* ret = dest;
  while (num--)
  {
    *(char*)dest =  *(char*)src;
    dest = (char*)dest + 1;
    src = (char*)src + 1;
  }
  return ret;
}
int main()
{
  int arr1[5] = { 0 };
  int arr2[] = { 1,2,3 };
  my_memcpy(arr1, arr2, 12);
  int i = 0;
  for (i = 0; i < 5; i++)
  {
    printf("%d ", arr1[i]);
  }
}

注意:

可以拷贝整型,也可以拷贝浮点型,所以用void*来接收


四、memmove函数

4.1 函数认识

函数功能:

从source的位置开始向后复制num个字节的数据到destination的内存位置,允许source和destination重叠

头文件:

#include<string.h>

memmove函数的应用:

#include<stdio.h>
#include<string.h>
int main()
{
  int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
  memmove(arr + 2, arr, 20);
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

4.2 注意事项

  • 为避免溢出,目标参数和源参数指向的数组的大小应至少为字节数
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理

4.3 模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h> 
void* my_memmove(void* dest, const void* src, int num)
{
  assert(dest && src);
  char* ret = dest;
  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; 
}
int main()
{
  int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
  my_memmove(arr + 2, arr, 20);
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

五、memcmp函数

5.1 函数认识

函数功能:

比较从ptr1和ptr2指针开始的num个字节

返回值:

返回值 表明
<0 两个内存块中不匹配的第一个字节在PTR1中的值低于PTR2中的值(如果评估为无符号字符值)
0 两个内存块的内容相等
>0 两个内存块中不匹配的第一个字节在PTR1中的值大于PTR2中的值(如果评估为无符号字符值)

头文件:

#include<string.h>

memcmp函数的应用:

#include<stdio.h>
#include<string.h>
int main()
{
  int arr1[] = { 1,2,1,5,4 };
  int arr2[] = { 1,2,257 };
  int ret = memcmp(arr1, arr2, 9);
  printf("%d\n", ret);
  return 0;
}

5.2 模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_memcmp(const void* s1, const void* s2, int num)
{
  assert(s1 && s2);
  char* str1 = (char*)s1;
  char* str2 = (char*)s2;
  int i = 0;
  for (i = 0; i < num; i++)
  {
    if (*(str1 + i) != *(str2 + i))
    {
      return (*(str1 + i) - *(str2 + i));
    }
  }
  return 0;
}
int main()
{
  int arr1[] = { 1,2,3,5,4 };
  int arr2[] = { 1,2,257 };
  int ret = my_memcmp(arr1, arr2, 9);
  printf("%d\n", ret);
  return 0;
}

六、memset函数

6.1 函数认识

函数功能:

将ptr指向的前num个字节设置为value值

头文件:

#include<string.h>

memset函数的应用:

#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "hello word";
  memset(arr, 'x', 2);
  printf("%s\n", arr);
  return 0;
}

6.2 注意事项

  • 要设置的值。该值作为 int 传递,但该函数使用此值的无符号char转换填充内存块
  • 以字节为单位来设置

七、字符分类函数

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

八、字符转换函数

int tolower(int c); 大写——>小写

int toupper(int c); 小写——>大写

#include<stdio.h>
int main()
{
  char ch = 0;
  ch = getchar();
  if (islower(ch))
    ch = toupper(ch);
  else
    ch = tolower(ch);
  printf("%c\n", ch);
  return 0;
}

本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位铁汁们的支持。文章有任何问题可以在评论区留言,小羊一定认真修改,写出更好的文章~~

相关文章
|
3月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
1016 0
|
5月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
209 26
|
5月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
328 15
|
10月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
421 1
一文彻底搞清楚C语言的函数
|
5月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1843 0
|
5月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
537 0
|
5月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
488 0
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
924 0

热门文章

最新文章