【编织代码之纵横字符与绚丽字符串](下)

简介: 【编织代码之纵横字符与绚丽字符串]

【编织代码之纵横字符与绚丽字符串](中):https://developer.aliyun.com/article/1424777


1.11、字符分类函数:


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


1.12、字符转换:


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


我们来测试一下:


/* isupper example */
#include <stdio.h>
#include <ctype.h>
int main()
{
    int i = 0;
    char str[] = "Test String.\n";
    char c;
    while (str[i])
    {
        c = str[i];
        if (isupper(c))
            c = tolower(c);
        putchar(c);
        i++;
    }
    return 0;
}


运行结果:



1.13、memcpy - 拷贝任意类型的数据


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


  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。


#include<stdio.h>
#include<string.h>
int main()
{
  //void * memcpy ( void * destination, const void * source, size_t num );
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
  int arr2[10] = { 0 };
  double arr3[] = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };
  double arr4[10] = { 0.0 };
  //将arr1的内容拷贝到arr2中
  memcpy(arr2, arr1, 10 * sizeof(int));
  for (int i = 0; i < 10; i++)
  {
    printf("%d ", arr2[i]);
  }
  printf("\n");
  //将arr3的内容拷贝到arr4中
  memcpy(arr4, arr3, 10 * sizeof(double));
  for (int i = 0; i < 10; i++)
  {
    printf("%f ", arr4[i]);
  }
  return 0;
}


运行结果:



模拟实现mencpy:


void* my_memcpy(void* destination, const void* source, size_t num)
{
  void* dest = destination;
  assert(destination && source);
  while (num--)
  {
    *(char*)destination = *(char*)source;
    destination = (char*)destination + 1;
    source = (char*)source + 1;
    //这里不能使用*((char*)destination)++,因为强制类型转换只改变了看待的形式,
  }
  return dest;
}


如果source和destination有任何的重叠,复制的结果都是未定义的。


#include<string.h>
#include<string.h>
int main()
{
  //void * memcpy ( void * destination, const void * source, size_t num );
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  memcpy(arr+2, arr, 5 * sizeof(int));
  for (int i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}


运行结果:



解释:拷贝第一个数据arr[0] - 1时,arr[2]的位置会被修改为arr[0] - 1的值,拷贝第二个数据arr[1] - 2时,arr[3] - 2的位置会被修改为arr[1]的值,当拷贝第三个数据arr[2] - 1时,arr[4]的位置会被修改为arr[2]的值,但是此时的arr[2]的值已经被修改为arr[0]的值 - 1,不再是原数组的3.


1.14、memmove


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


  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。


#include<string.h>
#include<string.h>
int main()
{
  //void * memmove ( void * destination, const void * source, size_t num );
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
  memmove(arr1+2, arr1, 5 * sizeof(int));
  for (int i = 0; i < 10; i++)
  {
    printf("%d ", arr1[i]);
  }
  return 0;
}


运行结果:



模拟实现memmove:


void* my_memmove(void* destination, const void* source, size_t num)
{
  void* dest = destination;
  assert(destination && source);
  if(destination< source)
  {
    //从前向后
    while (num--)
    {
      *(char*)destination = *(char*)source;
      destination = (char*)destination + 1;
      source = (char*)source + 1;
    }
  }
  else
  {
    //从后向前
    while (num--)
    {
      *((char*)destination + num) = *((char*)source + num);
    }
  }
  return dest;
}


代码图解:



1.15、memcmp


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


  • 比较从ptr1和ptr2指针开始的num个字节
  • 返回值如下:


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


运行结果:



图解:



1.16、memset


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


  • 将指针ptr指向的内存块的前num个字节设置为指定的值(被解释为无符号字符)。


#include<stdio.h>
#include<string.h>
int main()
{
  int arr[10] = { 0 };
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    memset(arr + i, i, 1);//以字节为单位设置,修改1个字节
    printf("%d ", arr[i]);
  }
  return 0;
}


运行结果:



我们来看看修改4个字节的结果:


#include<stdio.h>
#include<string.h>
int main()
{
  int arr[10] = { 0 };
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    memset(arr + i, i, 4);//以字节为单位设置,修改4个字节
    printf("%d ", arr[i]);
  }
  return 0;
}


运行结果:


相关文章
|
9天前
|
人工智能 运维 安全
|
7天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
9天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
702 23
|
8天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。
|
人工智能 数据可视化 数据挖掘
Quick BI 体验&征文有奖!
瓴羊生态推出Quick BI 征文激励计划,鼓励用户分享数据分析实践经验与技术洞察,征集高质量原创文章。内容围绕AI功能体验与BI案例实践,设季奖、年奖及参与奖,优秀作者可获现金奖励、产品内测资格及官方认证形象。投稿截止至2026年3月31日。
Quick BI 体验&征文有奖!