当前位置: 首页 > news >正文

【C语言】字符串与指针

字符串与指针

字符串的两种存储形式

C语言中并没有字符串这个特定类型,而是以字符数组的形式来存储和处理字符串,这种字符数组必须以空字符\0结尾,因此,也将这种特定字符数组称为C风格字符串。

  • 字符数组形式:char str[20]
  • 字符指针形式:char *pc
char str[20] = "hello";
str[0] = 'H';      // str是一个字符数组,字符串中的每个字符逐个存放,可以随意修改
str = "world";     // 但是str本身是一个常量,不能改变str(的指向)。char *pc = "hello";
pc[0] = '';        // pc是一个字符指针,如果指向的是常量区的字符串,这个字符串不能修改,只能访问
pc = "world";     //但是pc本身的指向可以修改。

字符串输入

gets()在C++14中已被彻底废弃。

fgets

char *fgets(char *s, int size, FILE *stream);
/* fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.  Reading stops after an EOF or a newline.  If a newline is read, it is stored into the buffer.  A terminating null byte ('\0') is stored after the  last  character in the buffer. */
// fgets遇到换行会将换行也读入
// fgets最多能输入size-1个字符,因为最后一位一定要留给\0

scanf

char str[10];
scanf("%s", &str);
// scanf不会读取换行符,换行符会被留在缓冲区中,并且scanf不会在最后加\0

strlen

size_t strlen(const char *s);
// 计算字符串 **str** 的长度,直到空结束字符,但不包括\0

实现strlen

// 遍历统计
int mystrlen1(const char *str)
{int res = 0;while(*str != '\0'){++str;++res;}return res;
}// 终点减起点
int mystrlen2(const char *str)
{const char *begin = str;const char *end = str;while(*end != '\0') ++end;return end - begin;
}
  • strcpy将src拷贝到dst(包括\0)
  • strncpy将src前n个字符拷贝到dst(最多拷贝n个)
    • strlen(src) >= n, dst没有\0结尾, 拷贝n个
    • strlen(src) + 1 <= n, dst有\0结尾, 但只会拷贝strlen(src)+1个
  • strcat将src拼接到dst尾(覆盖dst尾的\0), 拼接完后再在dst尾添一个\0
  • strncat将src前n个字符拼接到dst尾
    • strlen(src) >= n, 将src的前n个字符拼接到dst尾,此时src可以没有\0结尾
    • strlen(src) + 1 <= n, 将src的所有字符拼接到dst尾,此时src要有\0结尾

strcpy strncpy

char *strcpy(char *dest, const char *src);
/* The  strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest.  The strings may not overlap, and the destination string dest must be large enough to receive the copy.  Beware of buffer overruns!  (See BUGS.) */char *strncpy(char *dest, const char *src, size_t n);
/* The  strncpy()  function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated. 
If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are  written. */

实现strcpy

char *mystrcpy(char *dst, const char *src)
{char *res = dst;while(*src != '\0')*dst++ = *src++;*dst = '\0';     // 将src中的\0也复制到dst中return res;
}

实现strncpy

char *strncpy(char *dest, const char *src, size_t n)
{size_t i;for (i = 0; i < n && src[i] != '\0'; i++)dest[i] = src[i];for ( ; i < n; i++)dest[i] = '\0';return dest;
}

strcat strncat

char *strcat(char *dest, const char *src);
/*  The  strcat()  function  appends  the  src string to the dest string, overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte.  
The strings may not overlap, and the dest string must have enough space for the result.  
If dest is not large enough, program behavior is unpredictable; buffer overruns are a favorite avenue for attacking secure programs.  */char *strncat(char *dest, const char *src, size_t n);
/* The strncat() function is similar, except that*  it will use at most n bytes from src;*  src does not need to be null-terminated if it contains n or more bytes.
As with strcat(), the resulting string in dest is always null-terminated. If src contains n or more bytes, strncat() writes n+1 bytes to dest (n from src plus the terminating null byte). Therefore, thesize of dest must be at least strlen(dest)+n+1.    */

实现strcat

char *mystrcat(char *dst, const char *src)
{char *res = dst;while(*dst != '\0') ++dst;  // 注意这个++不能写进while循环条件里,注意一下while(*src != '\0') *dst++ = *src++;*dst = '\0';return res;
}

实现strncat

char *mystrncat(char *dest, const char *src, size_t n)
{size_t dest_len = strlen(dest);size_t i;for (i = 0 ; i < n && src[i] != '\0' ; i++)dest[dest_len + i] = src[i];dest[dest_len + i] = '\0';return dest;
}

相关文章:

  • Mac/Linux类虚拟机_CrossOver虚拟机CrossOver 23.6正式发布2024全新功能解析
  • 实现基于 Azure DevOps 的数据库 CI/CD 最佳实践
  • Log4j-tag丢失
  • 力扣刷题 day61:10-31
  • 【10种排序算法总结】C++实现
  • AI:45-基于深度学习的声纹识别
  • Oracle数据库创建Sequence序列的基本使用
  • JAVA同城货运搬家小程序系统的开发优势
  • 什么是 CNN? 卷积神经网络? 怎么用 CNN 进行分类?(2)
  • 从零开始的目标检测和关键点检测(三):训练一个Glue的RTMPose模型
  • Serverless化云产品超40款 阿里云发布全球首款容器计算服务
  • rust 创建多线程web server
  • JavaScript重难点整理
  • Latex报错 “Paragraph ended before \Gin@iii was complete“
  • linux--线程共享内存
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【React系列】如何构建React应用程序
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Android框架之Volley
  • golang 发送GET和POST示例
  • iOS | NSProxy
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Vue--数据传输
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 欢迎参加第二届中国游戏开发者大会
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 前端工程化(Gulp、Webpack)-webpack
  • 前端学习笔记之观察者模式
  • 跳前端坑前,先看看这个!!
  • 新书推荐|Windows黑客编程技术详解
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • #13 yum、编译安装与sed命令的使用
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (差分)胡桃爱原石
  • (附源码)ssm高校实验室 毕业设计 800008
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (全注解开发)学习Spring-MVC的第三天
  • (三)elasticsearch 源码之启动流程分析
  • (一)Java算法:二分查找
  • (转) Face-Resources
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .net 托管代码与非托管代码
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET简谈设计模式之(单件模式)
  • .net解析传过来的xml_DOM4J解析XML文件
  • .py文件应该怎样打开?
  • .stream().map与.stream().flatMap的使用
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [ C++ ] 继承
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)