C++中string转换为char*类型返回后乱码问题
问题来源:
在写二叉树序列化与反序列化时发现序列化函数为char* Serialize1(TreeNode *root) 其函数返回类型为char*,但是我在实现的过程中为了更方便的操作添加字符串使用的是C++中string类型的变量,这就导致我最后得到的结果res是string类型,若是要返回需要转化为char *类型。而等我将string类型转为char*后返回在主函数中就成了乱码。
先直接说最后的解决办法:
第一种:定义一个char数组,数组长度为stringlength+1,将string的内容依次赋值给char数组,最后加上'\0' ,然后返回char数组名就行了。
第二种:将string定义为类的成员变量
就贴第一种方法的代码
char *result = new char[res.length() + ]; //定义需要返回的result对象
for (int i = ; i < res.length(); ++i)
{
result[i] = res[i]; //将string类型的res内容都放到result内
}
result[res.length()] = '\0'; //加上结束符\0
再说说我尝试的方法
尝试1:
一开始我是直接定义char *result=&res[0];想要通过这个语句直接返回这个string类型变量的首地址,但是失败了,在主函数中的结果变量是乱码 "葺葺葺葺葺葺葺葺葺葺"
尝试2:
于是我开始思考可能的原因
1.考虑到局部变量可能随着函数释放,因此导致我返回的指针指向的内容随着函数一起释放导致了乱码,但一想到平时写的函数都是正常返回的,所以这个我很快否决了,但最后发现这个思路是对的。至于平常写的函数都是正常返回则是因为没有涉及到类型转换。
2.通过VS的调试发现我使用的char *result=&res[0]语句返回的是res的首个元素地址,并不是res的首地址,因为string作为std封装的数据结构除了char*这种从C吸收过来的结构还有内存分配allocate这些东西所以导致其内存地址并不像char数组那样是首个元素地址
所以我想干脆把整个string类型的res都赋值给char *类型的result
所以我尝试了char *result=(char*)res.data();语句,将res(res是string类型的结果)赋给result,转换是成功的,但返回值依旧失效(且这种转换需要自己加上\0结束符)
然后尝试char *result=(char*)res.c_str(); 结果也是成功的,但返回值依旧失效。
最后尝试,用new新建一个char数组,将res的内容全部拷贝到char数组内,然后将数组名返回,终于成功。
问题根源
通过VS调试我最终发现了问题根源所在:res所占内存随着函数结束而被释放
这是函数未执行完的调试界面

这是执行完调试界面

很明显:res没有了,在函数执行完毕后res内存也跟着被释放了而char数组result却仍然存在。他们的不同点在哪:result是返回值
我们知道函数的函数栈知识点,栈内存放着函数入口地址,局部变量,返回地址等,我猜测result作为要被返回的对象其内存空间应该是不随着函数一起被释放的,也就是主函数内的返回值应该还是用那块内存,经过测试这个结论是对的。主函数中的变量的确是使用返回值那块内存。
到这里就发现了,虽然执行char* result=(char*)res.c_str()语句能让result内是完整的结果内容(也就是转换完成),但result会随着string类型的res的释放而导致char*类型的result所指向的内存空间内容全部清空。最后虽然返回了result所指的空间但里面的内容早就被清空了。就好比把内存比作一块地,res先在其上面盖了一座房子,而使用上面转换语句后result也是房子的主人,这下房子有了两个主人,他们都能对房子进行操作。正因为他们都能进行操作,当他们所属函数结束也就是res大限到来之时,res将自己建立的房子销毁了。那么result也就没有房子可住了。也就是他们公用的那片内存被初始化,这时主函数虽然收到了返回地址但那片地址已经没有内容了。也就导致乱码了。
到这里,问题的根源就知道了,那么解决方法也就很明显了:1.内存分离,将res和result的所属内存地址分开。2.或者想办法让res所在内存不随着函数结束而释放.
具体实现:
第1种.上面那段new新建char*变量的代码。为result重新开辟一段空间。
第2种.i:若在类里:将res设为类的成员变量或者static成员变量(最好不要,能成功但会有新问题出现),他们都不会随着成员函数的结束而释放。区别就是普通成员变量会随着对象的释放而释放,static不会,它是存放在静态存储区
ii:若是像C这类面向过程代码就是将res设为全局变量即可
C++中string转换为char*类型返回后乱码问题的更多相关文章
- c++ string类型转换为char *类型
string 是c++标准库里面其中一个,封装了对字符串的操作 把string转换为char* 有3中方法: 1.data 如: string str="abc"; char *p ...
- C++中string、char *、char[]的转换
头段时间有人问过我这个问题,可是我一点头绪都没有,直接说不会.现在从网上找了点资料,看了看,知道点东西了. 一.string转char*. 主要有三种方法可以将str转换为char*类型,分别是:da ...
- C++ 将 std::string 转换为 char*
参考: std::string to char* C++ 将 std::string 转换为 char* 目前没有直接进行转换的方法.必须通过string对象的c_str()方法,获取C-style的 ...
- C++中string和char字符串的异同与使用方法
C++中string和char声明字符串的异同和使用 string类 必须在头文件中包含<string> 隐藏了字符串的数组性质,可以像处理普通变量那样处理字符串 string类位于名称空 ...
- 关于==和equals()方法&Java中string与char如何转换&String,StringBuffer
1.对于基本数据类型,可以直接使用==和!=进行内容比较 如:int x=30; int y=30; x==y; //true 基本数据类型 简单类型(基本类型) bo ...
- JS中String类型转换Date类型 并 计算时间差
JS中String类型转换Date类型 1.比较常用的方法,但繁琐,参考如下:主要使用Date的构造方法:Date(int year , int month , int day)<script& ...
- C++11中string与数值类型的转换
C++中string与数值类型的相互转换记录 string转int.double.long string s = "123.456"; // string -> int co ...
- Java中String转换Double类型 Java小数点后留两位
Java中String转换Double类型 double num1 = 0.0; String qq = "19.987"; num1 = Double.valueOf(qq.to ...
- 如何把string转换char*类型
需要调用string头文件 ( #include<string> ) 用string里的函数c_str()可以把string转换为char* 例如 char * c_str2=str1. ...
随机推荐
- /etc/alternatives
如何安装一个可执行程序 一般来说我们一个可执行程序,可能在多个路径下,比如在opt路径下,或者在自己的home下. 当要达到在系统的任意路径下敲击该命令,都可执行的话,一般要将该可执行命令的路径加入到 ...
- 关于linux免密登录及ssh客户端的使用
操作系统环境: CentOS Linux release 7.7.1908 (Core) 1.首先在linux服务器上,使用ssh-keygen命令生成密钥对文件(一直回车即可,默认使用rsa算法), ...
- lambda表达式操作DataTable
using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Text; ...
- python—异常处理
一:什么是异常? (异常就是程序运行时发生错误的信号) 错误分两种: 1.语法错误 2.逻辑错误 二:异常的种类? (在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类 ...
- webtatic源
我们在安装php时,系统的yum源中php版本太老,但是编译安装又太烦,这时我们可以使用webtatic源来yum安装较新版本的php. webtatic源: https://mirror.webta ...
- 2019-02-09 python爬取mooc视频项目初级简单版
今天花了一下午时间来做这东西,之前没有自己写过代码,50几行的代码还是查了很多东西啊,果然学起来和自己动起手来完全是两码事. 方案:requests库+正则表达式提取视频下载链接+urlretriev ...
- 浅淡i.MX8M Mini处理器的效能以及平台对比
i.MX 8M Mini是恩智浦首款嵌入式多核应用处理器,定位在任何通用工业和物联网的应用,是一款针对边缘计算应用的芯片,也是恩智普i.MX系列中第一个加了机器学习核的产品线.这颗芯片采用先进的14L ...
- 【01JMeter基础】线程组
线程组 我们存在接口请求的地方,在JMeter中我们使用最多的模块,分为 setUp线程组.线程组.tearDown线程组 setUp线程组:不论如何排序,都会在所有的线程组中被最早执行,如果有多个s ...
- vue事件修饰符与按钮修饰符
事件修饰符:(当事件无需传参数时可直接写成以下形式,有参数时则为@click.stop="handleLiClick($event)") stop:阻止事件冒泡行为(子元素被点击, ...
- 6.kubernetes的GUI资源管理插件-dashboard
目录 1.准备dashboard镜像 2.创建资源配置清单 3.应用资源配置清单 4.查看创建的资源 5.解析域名 6.浏览器访问 7.令牌命令行获取方式 准备dashboard镜像 [root@hd ...