6 CPP之C风格字符串

news2025/1/10 21:41:54

CPP之C风格字符串

c++中的string类,封装了C风格的字符串。 使用方便,能自动扩展,不用担心内存问题

在某些场景中,C风格字符串更方便,更高效

C标准库、Linux系统和开源库,大部分开源库一定有C语言版本,但不一定有C++版本,还有数据库接口函数,例如MySQL,只有C语言版本,没有C++版本。

C语言约定:如果字符串(char)数组的末尾包含了空字符\0(也就是0),那么该数组中的内容就是一个字符串。

这是一个数组,不是字符串。

 这是一个字符串数组,也是一个字符串

 c++也遵守这个约定,string类中的字符串,最后也有一个空字符,只是没有显示出来而已。

#include <iostream>
using namespace std;

void test()
{
    string str = "abc";
    cout << "str[0]" << str[0] << endl;
    cout << "str[1]" << str[1] << endl;
    cout << "str[2]" << str[2] << endl;
    cout << "str[3]" << str[3] << endl;
}
int main()
{
    test();
    return 0;
}
str[0]a
str[1]b
str[2]c
str[3]
#include <iostream>
using namespace std;

void test()
{
    string str = "abc";
    cout << "str[0]" << (int)str[0] << endl;
    cout << "str[1]" << (int)str[1] << endl;
    cout << "str[2]" << (int)str[2] << endl;
    cout << "str[3]" << (int)str[3] << endl;
}
int main()
{
    test();
    return 0;
}
str[0]97
str[1]98
str[2]99
str[3]0

因为字符串需要用0结尾,所以在声明字符串数组的时候,要预留一个字节用来存放0.

例如:

char name[21]; //声明一个最多存放20个英文字符或10个中文的字符串(中文占两个字节)

1)初始化方法

#include <iostream>
using namespace std;

void test()
{
    char name1[11]; //可以存放1个字符,没有初始化,里面是垃圾值

    for (int i = 0; i < 11; i++)
    {
        cout << (int)name1[i] << " ";
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}
0 0 0 0 0 0 0 0 0 0 0
只打印name1的时候,输出全部是11个0,看上去是没问题的,但是后面有例子(还有别的打印)就可以看出不初始化不全部都是0.

char name1[11]; //可以存放1个字符,没有初始化,里面是垃圾值,但不影响使用,如果单独打印的时候都是0

char name2[11] = "hello"; //初始化内容为 hello

char name3[] = {"hello"}; //初始化内容为 hello,系统会自动添加\0,数组长度是6.

char name4[11] = {"hello"}; //初始化内容为 hello

char name5[11]{"hello"}; //初始化内容为 hello

char name6[11] = {0}; //把全部的元素初始化为\0 这种方法用的最多

#include <iostream>
using namespace std;

void test()
{
//可以存放1个字符,没有初始化,里面是垃圾值,如果单独打印的时候都是0,
//但是在这个例子中,有别的打印就可以看出有问题了
    char name1[11];
    char name2[11] = "hello";   //初始化内容为 hello
    char name3[] = {"hello"};   //初始化内容为 hello,系统会自动添加\0,数组长度是6.
    char name4[11] = {"hello"}; //初始化内容为 hello
    char name5[11]{"hello"};    //初始化内容为 hello
    char name6[11] = {0};       //把全部的元素初始化为\0
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name1[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name2[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name3[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name4[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name5[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name6[i] << " ";
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}
0 0 0 96 24 64 0 0 0 0 0 
104 101 108 108 111 0 0 0 0 0 0 
104 101 108 108 111 0 104 101 108 108 111 
104 101 108 108 111 0 0 0 0 0 0 
104 101 108 108 111 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0

可以看出这个时候name1就有问题了

2) 清空字符串

#include <iostream>
#include <cstring>
using namespace std;

void test()
{
    char name[11] = {"hello"};

    //清空字符串

    name[0] = 0; //不规范 有隐患 不推荐
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name[i] << " ";
    }

    memset(name, 0, sizeof(name)); //把全部元素置为0
}
int main()
{
    test();
    return 0;
}
0 101 108 108 111 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 

3)字符串赋值或赋值 strcpy()

char *strcpy(char*dest,const char*src);

C++风格的字符串可以用等号赋值,很方便,但是C风格的不能用,只能用strcpy()

功能:将参数src字符串拷贝至参数dest所指的地址。

返回值:返回参数dest的字符串起始地址。

复制完字符串后,会在dest后追加0.

如果参数dest所指向的内存空间不够大,会导致数组的越界。

#include <iostream>
#include <cstring>
using namespace std;

void test()
{
    char name[11] = {"hello"};

    cout << endl;
    strcpy(name, "world");
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name[i] << " ";
    }
    cout << endl;
    strcpy(name, "worldworldworld");
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name[i] << " ";
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}
main.cpp: In function 'void test()':
main.cpp:16:11: warning: 'void* __builtin_memcpy(void*, const void*, long long unsigned int)' writing 16 bytes into a region of size 11 overflows the destination [-Wstringop-overflow=]
     strcpy(name, "worldworldworld");
     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
 
119 111 114 108 100 0 0 0 0 0 0 
119 111 114 108 100 119 111 114 108 100 119 

strncpy()

char* strncpy(char* dest,const char* src,const size_t n);

功能,把src前n个字符的内容赋值到dest中

返回值:dest字符串起始地址

如果src字符串长度小于n,则拷贝完字符串后,在dest后追加0,直到n个。

如果src的长度大于等于n,就截取src的前n个字符,不会在dest后追加0。

如果参数dest所指的内存空间不够大,会导致数组的越界

#include <iostream>
#include <cstring>
using namespace std;

void test()
{
    char name[11];

    memset(name, 0, sizeof(name));

    // strncpy(name, "hello",8);//会自动补0
    strncpy(name, "hello", 3); //不会自动补0,可以用memset(name,0,sizeof(name))先清空name;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name[i] << " ";
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}
这里有个坑,就是src小于n的时候,不会自动补0,可以先用memset清空
#include <iostream>
#include <cstring>
using namespace std;

void test()
{
    char name[11];

    memset(name, 0, sizeof(name)); //打开注释,name打印,除了hel则3个字符,后面就全部是0了

    // strncpy(name, "hello",8);//会自动补0
    strncpy(name, "hello", 3); //不会自动补0,可以用memset(name,0,sizeof(name))先清空name;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name[i] << " ";
    }
    cout << endl;
    char name2[11] = "hello";   //初始化内容为 hello
    char name3[] = {"hello"};   //初始化内容为 hello,系统会自动添加\0,数组长度是6.
    char name4[11] = {"hello"}; //初始化内容为 hello
    char name5[11]{"hello"};    //初始化内容为 hello
    char name6[11] = {0};       //把全部的元素初始化为\0    这种方法用的最多
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name2[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name3[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name4[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name5[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 11; i++)
    {
        cout << (int)name6[i] << " ";
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}
104 101 108 0 0 0 0 0 0 0 0 
104 101 108 108 111 0 0 0 0 0 0 
104 101 108 108 111 0 104 101 108 108 111 
104 101 108 108 111 0 0 0 0 0 0 
104 101 108 108 111 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 

5)获取字符串长度 strlen();

 

#include <iostream>
#include <cstring>
using namespace std;

void test()
{
    char name[11] = {"hello\0f"};
    cout << strlen(name) << endl;
    char name1[11] = {"hello"};
    name1[1] = 0;
    cout << strlen(name1) << endl;
}
int main()
{
    test();
    return 0;
}
5
1

6)字符串拼接 strcat()

 

 

 

11)

可以把C风格的字符串用于包含了string类型的赋值拼接等表达式中。

注意事项:

1 字符串的结尾标志是0,按照约定,在处理字符串的时候,会从起始位置开始搜索0,一直找下去,找到为止(不会判断数组是否越界)

2 结尾标志0后面的都是垃圾内容

3 字符串在每次使用前都要初始化,减少入坑的可能,是每次,不是第一次。

4 不要在子函数中对字符指针用sizeof运算符,所以,不能在子函数中对传入的字符串进行初始化,除非字符串的长度也作为参数传入到子函数中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/94967.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue前端浏览器链接/接口参数实现加密

场景 由于项目创建之前后端设计不合理&#xff0c;导致详情页链接参数id为顺序序数(例&#xff1a;1,2,3…等等)&#xff0c;安全系数非常低&#xff08;虽然我们前端做了菜单权限、按钮权限、Api权限等等&#xff09;&#xff0c;现在要前端解决下浏览器链接/接口参数实现加密…

《Linux运维总结:基于xtrabackup8工具全量物理备份Mysql8数据自动化工具(方案一)》

一、背景信息 说明&#xff1a;由于业务系统的特殊性&#xff0c;对数据的备份要求非常高&#xff0c;且数据量非常大&#xff0c;所以这里采用xtrabackup工具来对Mysql数据库进行全量物理备份。由于xtrabackup工具操作复杂&#xff0c;这里为了简便&#xff0c;基于xtrabackup…

张驰咨询:快速提高流程效率的5个关键精益生产工具

精益&#xff0c;又称“精益制造”或“精益生产”&#xff0c;注重通过消除浪费、消除缺陷&#xff0c;实现客户价值最大化。精益工具是关于理解过程&#xff0c;发现浪费&#xff0c;防止错误和记录你所做的事情。 让我们来看看流程改进中使用的五种精益工具&#xff0c;它们…

建立企业数据共享机制,打破数据壁垒

很多人可能也比较疑惑&#xff0c;为什么数据这么重要&#xff0c;能够有着数据治理、数据标准、数据管理以及我们接下来要讲的数据共享&#xff0c;各种针对数据的机制体系。一方面是因为数据在数字经济和数字化转型进程中发挥了巨大作用&#xff0c;甚至可以称得上是两者的核…

RCNN网络源码解读(Ⅰ) --- 获取数据并预处理数据

目录 1.RCNN是什么东西 2.处理数据集 2.1 code&#xff1a;下载VOC数据集&#xff08;pascal_voc.py&#xff09; 2.2 code&#xff1a; 数据集预处理&#xff08;pascal_voc_car.py&#xff09; 3.code区域候选建议&#xff08;selectivesearch.py&#xff09; 1.RCNN是什…

Web(十)JavaScript知识训练-JS函数

1、下列选项中&#xff0c;&#xff08; B&#xff09;可用于检查某个值是否为无穷大的数。 A、 isNaN&#xff08;&#xff09; B、 isFinite&#xff08;&#xff09; C、 parseInt&#xff08;&#xff09; D、 parseFloat&#xff08;&#xff09; 2、函数parseInt(15.36)…

燕东微在科创板上市:市值263亿元,北京电控、亦庄国投等为股东

12月16日&#xff0c;北京燕东微电子股份有限公司&#xff08;下称“燕东微”&#xff0c;SH:688172&#xff09;在上海证券交易所科创板上市。本次在上市&#xff0c;燕东微的发行价为21.98元/股&#xff0c;募资总额约为39.53亿元&#xff0c;募资净额约为37.57亿元&#xff…

【Java寒假打卡】Java基础-方法

【Java寒假打卡】Java基础-方法一、定义二、方法的定义和调用三、方法调用过程四、带参数的方法和调用五、debug查看方法参数传递六、带返回值的方法的调用七、方法重载八、方法传递数据九、返回一个数组的最大值和最小值一、定义 方法就是一段具有独立功能的代码块&#xff0…

Java中的Set系列集合

Set系列集合Set系列集合Set系列集合概述HashSet元素的底层原理&#xff1a;哈希表HashSet元素去重复的底层原理实现类&#xff1a;LinkedHashSet实现类&#xff1a;TreeSetCollection体系的特点、使用场景终结补充知识&#xff1a;可变参数集合工具类CollectionsCollection体系…

Unity PolyNav2D(2D寻路) 插件

下载地址 https://download.csdn.net/download/qq_27461747/87300286 组件 PolyNav2D 寻路地图&#xff0c;一般来说 有且只有一个&#xff0c; 寻路的主要接口就在这个组件里PolyNavObstacle 障碍物PolyNavAgent 导航代理, 带有移动功能。这个可有可无&#xff0c;可以自己…

重点| 系统集成项目管理工程师考前50个知识点(6)

本文章总结了系统集成项目管理工程师考试背记50个知识点&#xff01;&#xff01;&#xff01; 帮助大家更好的复习&#xff0c;希望能对大家有所帮助 比较长&#xff0c;放了部分&#xff0c;需要可私信&#xff01;&#xff01; 40、冲突的下列特点&#xff1a; &#xff…

css知识复习点

四种css使用方式&#xff1a;内嵌式、外链式、行内式、导入式 复合选择器 后代选择器 选择器之间需要用空格隔开&#xff0c;后代不一定是儿子 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>复合…

渗透测试-crlf注入原理

目录 概念 HTTP报文结构与漏洞原理 漏洞检测 Bottle之CRLF漏洞 nginx配置错误之CRLF漏洞 漏洞危害 会话固定 修复建议 漏洞检测POC 概念 这个漏洞一般很少出现。 CRLF是CR和LF两个字符的拼接&#xff0c;它们分别代表”回车换行”&#xff08;\r\n&#xff09;。十六…

[附源码]Nodejs计算机毕业设计基于的学生事务管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

Java+mysql基于SSM的网上出差审批与费用报销系统 开题 毕业设计

本课题是一个基于SSM的管理系统,本网上出差审批与费用报销系统是在Windows7系统的环境下,利用Eclipse和Mysql工具开发的。在网上出差审批与费用报销系统中分为管理员和普通用户2个模块。其中网上出差审批与费用报销系统中的管理人员在登陆之后可以管理本系统内的部门信息管理,员…

性能测试场景:如何进行场景设计?

我们在前面屡次强调了场景的重要性,今天终于到了要把实际场景拿出来解析的时候了。 在本篇文章中,为了保证数据的连续性,我用之前的项目资料来作明确地说明。同时为了模糊关键业务信息,以及让场景的描述更通用性,我会把所有的业务名隐去。 根据之前我们所说的,基准性能…

【DevOps实战系列】第六章:详解Docker私服Nexus3篇

个人亲自录制全套DevOps系列实战教程 &#xff1a;手把手教你玩转DevOps全栈技术 概述/目标 私服我们很熟悉了&#xff0c;比如docker hub就是官方私服&#xff0c;而有些情况比如我们自建的镜像&#xff0c;不想往外传&#xff0c;就需要考虑内部搭建一个私有服务器来存放私有…

ELK 日志框架搭建 (springboot 接入 elk)

什么是ELK&#xff1f; ELK 是一个开源的实时日志分析平台&#xff0c;它主要由 Elasticsearch、Logstash 和 Kiabana 三部分组成。 Logstash Logstash 主要用于收集日志&#xff0c;它是一个开源数据收集引擎&#xff0c;具有实时管道功能。Logstash 可以动态地将来自不同数…

《大正野球娘》:棒球少女·棒球1号位

《大正野球娘。》是根据神乐坂淳的人气轻小说「大正棒球少女」及「大正棒球少女&#xff5e;沾满土与尘&#xff5e;」改编的电视动画。原作小说是神乐坂淳原作&#xff0c;小池定路插画的轻小说改德间书店出版&#xff0c;至2009年6月已发行三卷。此外&#xff0c;小说还被改编…

曙光超算平台如何使用以及常见问题

官方参考链接如下&#xff0c;有需要的自取&#xff1a; Notebook 计算服务 了解常用的E-shell命令 (1) squeue: 查看目前提交作业的信息 (2) salloc :抢占计算资源命令 salloc -p wzhdtest -N 1 -n 8 --gresdcu:1 &#xff08;部分地区有绑卡机制&#xff0c;比如乌镇&am…