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() + 1];  //定义需要返回的result对象
for (int i = 0; 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*类型乱码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解c++中char*与wchar_t*与string以及wstring之间的相互转换

    复制代码 代码如下: #ifndef USE_H_      #define USE_H_ #include <iostream>      #include <windows.h>      #include <string>      using namespace std;      class CUser      {      public:          CUser();          virtual~ CUser();          char*

  • C++编程之CString、string与、char数组的转换

    C++编程之CString.string与.char数组的转换 虽然网上关于CString,string,char数组的转换的文章一大堆,但是感觉很乱很杂,而且许多并不能真正达到目的,在此,我把自己调试通过的转换方法贴到这里,做个笔记. 编译环境:vs2008, Use Unicode Character Set //----------------ANSI字符串转换为UNICODE字符串----------------------// // 待转换的数组 char szDCBparam[50]

  • C++中CString string char* char 之间的字符转换(多种方法)

    首先解释下三者的含义 CString 是一种很有用的数据类型.它们很大程度上简化了MFC中的许多操作(适用于MFC框架),使得MFC在做字符串操作的时候方便了很多.需要包含头文件#include <afx.h> C++是字符串,功能比较强大.要想使用标准C++中string类,必须要包含#include <string>// 注意是<string>,不是<string.h>,带.h的是C语言中的头文件.Char * 专门用于指以'\0'为结束的字符串. 以下

  • C++中string转换为char*类型返回后乱码问题解决

    问题来源: 在写二叉树序列化与反序列化时发现序列化函数为char* Serialize1(TreeNode *root)  其函数返回类型为char*,但是我在实现的过程中为了更方便的操作添加字符串使用的是C++中string类型的变量,这就导致我最后得到的结果res是string类型,若是要返回需要转化为char *类型.而等我将string类型转为char*后返回在主函数中就成了乱码. 先直接说最后的解决办法: 第一种:定义一个char数组,数组长度为stringlength+1,将stri

  • Java中Object转换为List类型的实现方法

    前言 在很多项目编写过程中会使用Map<?>类型来进行参数的传递.为了能够让更多的类型放入value中,实例化的类型往往是Map<String, Object>来存放数据. 解析数据的时候map.get(key)所获取到的类型为Object.此时,需要转换成我们所需要的数据类型进行使用. 类型转换 在类型转换工程中,常见的转换方式为强制转换.如(String)map.get(key),(int)map.get(key)等.在是如果接收的类型为List,此时强转(List<St

  • MySQL中varchar和char类型的区别

    目录 前述 VARCHAR类型 VARCHAR适用情况 CHAR类型 测试 VARCHAR(5)与VARCHAR(200)的区别 总结 前述 VARCHAR和CHAR是两种最主要的字符串类型.不幸的是,很难精确地解释这些值是怎么存储在磁盘和内存中的,因为这跟存储引擎的具体实现有关.下面的描述假设使用的存储引擎是InnoDB和/或者MyISAM.如果使用的不是这两种存储引擎,请参考所使用的存储引擎的文档. 先看看VARCHAR和CHAR值通常在磁盘上怎么存储.请注意,存储引擎存储CHAR或者VAR

  • Java中String类常用类型实例总结

    目录 1.创建字符串的方法 1.1构造 1.2引用对象  2.字符串的比较 3.字符串的不可改变性 4.数组转字符串  5.判断是否是数字字符串  isNumberChar(  )  6.字节变字符串  7.字符串的查找 8.字符的替换 9.字符串的分割 9.1以单个符号来分割  9.2多个分隔符分割  9.3特殊符号分割 10.提取子串str.substring(  )  11.去空格 12.字符串的拼接 13.StringBuffer   13.1字符串的拼接 13.2方法的返回类型 总结

  • golang 中string和int类型相互转换

    总结了golang中字符串和各种int类型之间的相互转换方式: string转成int: int, err := strconv.Atoi(string) string转成int64: int64, err := strconv.ParseInt(string, 10, 64) int转成string: string := strconv.Itoa(int) int64转成string: string := strconv.FormatInt(int64,10) 字符串到float32/floa

  • 浅谈char*类型返回值和字符串常量

    看这样一段简单的程序: #include <stdio.h> char* fun() { return "fun"; } int main() { printf("%s", fun()); return 0; } 这段程序可以正常run,但是最好不要这么做. 因为  直观上你返回了一个局部的东西出去.  你可以再外面定义这个常量,然后返回. 另外,字符串常量不可修改,而char*意味着要修改,故此最好加上const. 以上就是小编为大家带来的浅谈char

  • js中string和number类型互转换技巧(分享)

    1.string-->number string类型   *1  即可变成  number类型 2.number-->string number类型  +''  即可变成  string 类型 <script type="text/javascript"> function screenInfo() { var str = '012.8372'; var s = 0; str = str * 1; alert(typeof (str));//number s +

  • PHP中使用file_get_contents抓取网页中文乱码问题解决方法

    本文实例讲述了PHP中使用file_get_contents抓取网页中文乱码问题解决方法.分享给大家供大家参考.具体方法如下: file_get_contents函数本来就是一个非常优秀的php自带本地与远程文件操作函数,它可以让我们不花吹挥之力把远程数据直接下载,但我在使用它读取网页时会碰到有些页面是乱码了,这里就来给各位总结具体的解决办法. 根据网上有朋友介绍说原因可能是服务器开了GZIP压缩,下面是用firebug查看我的网站的头信息,Gzip是开了的,请求头信息原始头信息,代码如下: 复

  • 深入了解Java中String、Char和Int之间的相互转换

    在做在线编程题目的时候,需要了解一下数据的输入格式.这样可以对数据处理有比较好的把握,不需要把太多的时间放在这个上面,注重主要的算法逻辑即可.这里总结一下,为之后笔试做个准备. 1.从终端输入的方式 Scanner类的使用方法: Scanner scanner = new Scanner(System.in); 从终端获取输入流,输入流传入Scanner初始化对象时,作为参数传递进去. Scanner类的重要几个方法: next方法(读取一个字符) 1.一定要读取到有效字符后才可以结束输入(要是

  • c#中String类型的存储原理详解

    在我们正式了解c#中的String类型前,先来判断一下下面代码的结果吧~ String str1 = "123"; String str2 = str1; str2 = "321"; Console.WriteLine(str1); 上面代码的最终输出结果是123,如果有浅学过引用类型的同学一定会问:str2不是在存储的是str1的引用么?那么str2不是和str1指向堆中同一块内存空间么?为什么在引用了str2使其改变数据后再打印出str1最终还是打印出来123?

随机推荐