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

编程技能:字符串函数07,strncat

专栏导航

本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。

(一)WIn32 专栏导航

上一篇:编程技能:字符串函数06,strcat

回到目录

下一篇:无

(二)MFC 专栏导航

上一篇:编程技能:字符串函数06,strcat

回到目录

下一篇:无

本节前言

在上一节,我们讲解了 strcat 函数。本节,我们来讲解与之相近的 strncat 函数。

一.    strncat 基本介绍

想要使用 strncat 函数,如果是想要在 C 语言里面使用,那么,你需要有【#include <string.h>】一行。如果是想要在 C++ 里面使用,你需要有【#include <cstring>】一行。

下面,是 strncat 函数的原型声明。

char * strncat(char * dest,const char * src,int count);

我在这里所列的原型声明,它只是我从 Linux 0.12 内核中提取出来的一种声明而已。在 Visual Studio 里面,它的声明形式不是这样子的。但是呢,我在这里列举出来的声明,它是可用的。

此函数的功能是,将 src 所指向的源字符串的前 count 个字符,添加到dest所指字符串的结尾处。添加的时候,会覆盖掉 dest 所指字符串结尾的 '\0',并且会在最后添加一个 '\0',从而实现字符串的连接。函数的返回值为 dest 指针。

此函数有几个注意事项。

第一,dest 必须有足够的空间来容纳 src 的字符串的前 count 个字符。

第二,如果 count 大于字符串 src 的有效字符长度,那么仅将 src 指向的字符串内容追加到 dest 的尾部。

假定,有如下的几行代码。

char str02[100] = "abc";
char str01[] = "defghijkl";strncat(str02, str01, 3);

此函数给目的字符数组 str02 设置了足够大的缓冲区,所以,空间是够用的。

在执行拼接的时候,str01中的第 1 个字符 d 会覆盖 str02 字符串 "abc" 的结尾的 NUL 字符。然后呢,str01 的 e 和 f 字符会分别被赋值给 str02[4] 和 str02[5] 。最后呢,给 str02[6] 赋值 '\0' 。

以上的执行过程,属于是一板一眼的执行着。

而实际上,我们可以将这个执行过程简化理解。我们可以近似地认为,拼接过程是将 str01 的三个有效字符 d,e 和 f 插入到 str02 的末尾有效字符 'c' 和 str02 的 NUL 结束符之间。

我们来看注意事项中的第一点。它是说,目的字符数组中要有足够的空间来容纳源字符串的前 count 个字符。

在上面的代码块示例中,我们给 str02 设定的数组长度为 100,初始化字符串 "abc" 包含 3 个有效字符和 1 个 NUL 结束符,总共占去了 4 个位置,所以呢,str02 此时还剩下 96 个空位置。在上面的简化理解中,我们将 strncat 理解为,将 src 源字符串的前 count 个字符插入到 dest 字符串的末端有效字符 'c' 和 NUL 结束符之间。所以呢,str02 要想能够容纳 str01 的前 count 个字符,只要满足【count <= 96】就可以了。

进一步地,假定我们给目的字符数组 dest 设定的尺寸为 dest_size,初始化 dest 字符串的有效长度为 dest_init_len,包含 NUL 结束符的字符串长度为 dest_init_len+1,则 dest 的剩余可用长度为【dest_size - dest_init_len - 1】。此时,要想让 dest 能够容纳 src 的前 count 个字符,则需要满足的条件为:【count <= (dest_size - dest_init_len - 1)】。

当然了,对于第一个注意事项,你也可以换一种方式来理解。假定,dest 目的字符数组的尺寸为 dest_size,初始化 dest 字符串的不包含 NUL 结束符的有效字符长度为 dest_init_len,初始化 dest 字符串的包含 NUL 结束符的总字符长度为 dest_init_len+1。那么,要想让 dest 能够容纳 src 的前 count 个字符,需要满足的条件是,【dest_init_len + 1 + count <= dest_size】。

注意事项的第二点是比较容易理解的,我就不展开讲解了。还不懂第二点的,私聊啊。

二.    strncat 的 C 语言代码示例

#include <stdio.h>
#include <string.h>int main(void)
{char str02[100] = "Windows ";char str01[] = "Programing Designment";strncat(str02, str01, 7);printf("拼接后的字符串:%s\n", str02);return 0;
}

这一段代码,直接在较新版本的 Visual Studio 里面去编译,它是会报错的。想要在较新的版本的 Visual Studio 里面使用这段代码,需要在预编译器里面加入 _CRT_SECURE_NO_WARNINGS 参数。添加 _CRT_SECURE_NO_WARNINGS 参数的方法,可以参考下述链接所指示的文章。

编程技能:字符串函数04,直接使用 strcpy,解决报错-CSDN博客

三.    安全型函数 strncat_s

直接使用 strncat, Visual Studio 会报错,IDE 会建议我们使用安全型的 strncat_s 函数。它的一个声明形式如下。

errno_t __cdecl strncat_s(char * dest, const char *src, size_t count);

此函数的返回值是 errno_t 类型的。errno_t 类型,就是 int 类型。

此函数的返回值,我们先不去深究。

__cdecl,这个东西,此处我们先不用管。就目前的阶段来讲,你可以无视这个东西,而直接将此函数的原型声明看作是【errno_t strncat_s(char * dest, const char *src, size_t count);】。

size_t,就是 unsigned int 。

从函数声明格式来看,strncat 和 strncat_s 的调用方法是一样的。

假定,我们先进行了如下的声明语句。

char str02[100] = "LaLaLa ";
char str01[] = "abcdefghijkl";

然后呢,你使用 strncat 函数完成拼接。拼接代码为:【strncat(str02, str01, 3)】。那么,为了用 strncat_s 完成同样的拼接效果,你需要这样子来写代码:【strncat_s(str02, str01, 3)】。

从这样的案例可以看到,使用 strncat 和 strncat_s 相比,两者的参数都是一样的,包括顺序都是一致的。区别只在于函数名,一个是 strncat,一个是 strncat_s 。

无论是使用 strncat,还是使用 strncat_s,其实我们都需要保证目的字符数组 dest 的空间足够。在使用安全型函数 strncat_s 的时候,我们并未显式地指定目的字符数组的最大缓冲区长度,而 strncat_s 又是需要做一点。那么, Visual Studio 是怎么来确保目的字符数组的空间足够呢?

我不知道。不过,微软既然开发了 strncat_s 的这一声明形式,那么,微软肯定是有办法来保这一点。

我所能够想到的一个方法,就是使用 sizeof 操作符。sizeof 操作的参数若是为数组名,则它的返回值为整个数组的字节长度。在使用 sizeof 操作符确定了目的字符数组 dest 的总尺寸以后,在拼接的过程中,去比较 dest 的数组总长度,dest 的包含 NUL 结束符的初始化字符串的长度,以及 count,对这些个数值加以计算。若是能够容纳得了,则正常往下运行。若不能容纳,无法正常完成拼接,则抛出异常,阻止程序的继续运行。

这是我所想到的,用以实现 strncat_s 的思路。大家可以参考着吧。或许,以后,你还能想到比我所说的方法更厉害的方法。

好了,对 strncat_s 的讲解,到这里就完事儿了。

接下来,我们分别给出 strncat_s 的 C 语言代码示例和 C++ 代码示例。

四.    strncat_s 的 C 语言代码示例

#include <stdio.h>
#include <string.h>int main(void)
{char str02[100] = "Windows ";char str01[] = "Programing Designment";strncat_s(str02, str01, 7);printf("拼接后的字符串:%s\n", str02);return 0;
}

上述代码,是可以直接在 Visual Studio 里面运行的。

大家若是还不会使用 Visual Studio,可以参考下述链接所示的两篇文章,来学习使用 Visual Studio 来建立解决方案和编译运行解决方案的方法。

Windows编程:使用 VS2010 编写 C语言程序-CSDN博客

Windows编程:用 VS2019 编写C语言程序-CSDN博客

运行结果为如下。

图1

五.    strncat_s 的 C++ 代码示例

#include <iostream>
#include <cstring>
using namespace std;int main(void)
{char str02[100] = "Windows ";char str01[] = "Programing Designment";strncat_s(str02, str01, 7);cout << "拼接后的字符串:" << str02 << endl;return 0;
}

结束语

本节内容,到这里,又算是讲完了。希望大家已经学好了本节的内容。

个人觉得,讲起来,也会有点儿费劲儿。希望大家能学好吧。

本节结束。

专栏导航

本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。

(一)WIn32 专栏导航

上一篇:编程技能:字符串函数06,strcat

回到目录

下一篇:无

(二)MFC 专栏导航

上一篇:编程技能:字符串函数06,strcat

回到目录

下一篇:无

http://www.xdnf.cn/news/7277.html

相关文章:

  • C++跨平台开发经验与解决方案
  • Linux 文件(1)
  • 三维重建(二十三)——各种参数的测试(废案)
  • RV1126 + PCA9685实现7路舵机+2路减速电机控制
  • C++语法中的引用及其原理
  • 上位机知识篇---涂鸦智能云平台
  • Linux 线程(上)
  • Mamba LLM 架构简介:机器学习的新范式
  • SHAP分析图的含义
  • STM32F1软件调试详解
  • vLLM - LLM 类初始化参数
  • Addressable-加载指定资源
  • QT6 源(108)篇二:阅读与注释菜单栏里的菜单对象 QMenu,先是成员函数,后是信号函数的测试
  • Python 位运算:深入理解与实践应用
  • Linux开放访问端口
  • boost之signal2
  • 【ROS2】虚拟机使用fishros脚本一键安装humble
  • 我的创作纪念日——512天
  • 学习笔记:hspice仿真Verilog-a
  • ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
  • ET Attribute
  • 【Python 算法零基础 4.排序 ① 选择排序】
  • 深度剖析:YOLOv8融入UNetv2 SDI模块的性能提升之旅
  • 游戏服务器之聊天频道设计
  • 双紫擒龙紫紫红指标源码学习,2025升级版紫紫红指标公式-重点技术
  • transformer project tutorial
  • volatile
  • Python实例题:Flask开发轻博客
  • mybatis中的resultMap的association及collectio的使用
  • 【动态规划】状压dp