c++ - 从函数返回 const char* 数组
问题描述
所以我有一些 XML 文件,我想创建一个函数来读取 XML 文件并返回一个包含参数及其值等内容的数组。到目前为止,我能够读取正确的值。当我创建一个 const char* read() 函数并包含底部的代码并返回 const char* 时,就会出现我的问题。它必须是 const char*,因为解析 XML 文件的返回值是 const char*。如何创建一个返回数组的函数,该数组可以在不同的函数中读取?我尝试使用我阅读的示例中的指针,但它给了我:cannot convert 'const char*[3][2] to int* in assignement.
如何正确使用这些指向数组的指针而不会出现类型错误?
#include <QCoreApplication>
#include <iostream>
#include <stdio.h>
#include <tinyxml.h>
#include <sstream>
using namespace std;
int main (void)
{
const char* ptr;
ptr = read();
cout<<ptr[0][0]<<endl;
return 1;
}
const char* read()
{
//READING XML FILE
const char* pFilename = "Profile.xml";
TiXmlDocument doc (pFilename);
if(!doc.LoadFile()) return 1;
const char *xmlread [3][2] = {0};
TiXmlElement *pRoot, *pParm;
int i = 0;
pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
xmlread[i][0] = pParm->Attribute("name");
xmlread[i][1] = pParm->Attribute("value");
pParm = pParm->NextSiblingElement("Parameter");
cout<<xmlread[i][0]<<endl;
cout<<xmlread[i][1]<<endl;
i++;
}
}
return xmlread;
}
解决方案
你正在用 C++ 编写程序,而不是 C,所以你真的不应该使用原始指针!仅仅因为 XML 库返回值const char*
并不意味着您必须这样做。特别是当您试图返回一个 XML 文档所拥有的指针时,该指针在您的函数退出时被破坏,从而使您存储在数组中的任何指针无效。
如果你绝对需要使用原始指针返回一个字符串数组(你在 C++ 中没有!),它看起来更像这样:
#include <QCoreApplication>
#include <iostream>
#include <tinyxml.h>
#include <stdio.h>
using namespace std;
char* myStrDup(const char *s)
{
//return strdup(s);
int len = strlen(s);
char *ptr = new char[len+1];
memcpy(ptr, s, len);
ptr[len] = '\0';
return ptr;
}
char*** read(int *count)
{
*count = 0;
//READING XML FILE
TiXmlDocument doc ("Profile.xml");
if (!doc.LoadFile())
return NULL;
TiXmlElement *pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
TiXmlElement *pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
++(*count);
pParm = pParm->NextSiblingElement("Parameter");
}
}
char ***xmlread;
int i = 0;
try
{
xmlread = new char**[*count];
try
{
pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
xmlread[i] = new char*[2];
try
{
xmlread[i][0] = NULL;
xmlread[i][1] = NULL;
try
{
xmlread[i][0] = myStrDup(pParm->Attribute("name"));
xmlread[i][1] = myStrDup(pParm->Attribute("value"));
}
catch (...)
{
delete[] xmlread[i][0];
delete[] xmlread[i][1];
throw;
}
}
catch (...)
{
delete[] xmlread[i];
throw;
}
++i;
pParm = pParm->NextSiblingElement("Parameter");
}
}
}
catch (...)
{
for (int j = 0; j < i; ++j)
{
delete[] xmlread[j][0];
delete[] xmlread[j][1];
delete[] xmlread[j];
}
delete[] xmlread;
throw;
}
}
catch (...)
{
return NULL;
}
return xmlread;
}
int main()
{
int count;
char*** ptr = read(&count);
if (ptr)
{
for(int i = 0; i < count; ++)
{
cout << ptr[i][0] << endl;
cout << ptr[i][1] << endl;
}
for(int i = 0; i < count; ++)
{
delete[] ptr[i][0];
delete[] ptr[i][1];
delete[] ptr[i];
}
delete[] ptr;
}
return 0;
}
不太好,是吗?您可以通过返回一个数组,它的元素是一个结构类型来保存字符串指针,从而使它稍微好一点:
#include <QCoreApplication>
#include <iostream>
#include <tinyxml.h>
#include <stdio.h>
using namespace std;
struct NameValue
{
char *name;
char *value;
NameValue() : name(NULL), value(NULL) {}
~NameValue() { delete[] name; delete[] value; }
};
char* myStrDup(const char *s)
{
//return strdup(s);
int len = strlen(s);
char *ptr = new char[len+1];
memcpy(ptr, s, len);
ptr[len] = '\0';
return ptr;
}
NameValue* read(int *count)
{
*count = 0;
//READING XML FILE
TiXmlDocument doc ("Profile.xml");
if (!doc.LoadFile())
return NULL;
TiXmlElement *pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
TiXmlElement *pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
++(*count);
pParm = pParm->NextSiblingElement("Parameter");
}
}
NameValue *xmlread;
int i = 0;
try
{
xmlread = new NameValue[*count];
try
{
pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
xmlread[i].name = myStrDup(pParm->Attribute("name"));
xmlread[i].value = myStrDup(pParm->Attribute("value"));
++i;
pParm = pParm->NextSiblingElement("Parameter");
}
}
}
catch (...)
{
delete[] xmlread;
throw;
}
}
catch (...)
{
return NULL;
}
return xmlread;
}
int main()
{
int count;
NameValue* ptr = read(&count);
if (ptr)
{
for (int i = 0; i < count; ++i)
{
cout << ptr[i].name << endl;
cout << ptr[i].value << endl;
}
delete[] ptr;
}
return 0;
}
但是,在 C++ 中,最好的选择是让您的函数返回 a std::vector
,其中 struct 类型保存std::string
字符串的成员。让 C++ 标准库为您处理所有内存管理:
#include <QCoreApplication>
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <tinyxml.h>
using namespace std;
struct NameValue
{
string name;
string value;
};
vector<NameValue> read()
{
vector<NameValue> xmlread;
//READING XML FILE
TiXmlDocument doc ("Profile.xml");
if (doc.LoadFile())
{
TiXmlElement *pRoot = doc.FirstChildElement("PRO");
if (pRoot) //parsing
{
TiXmlElement *pParm = pRoot->FirstChildElement("Parameter");
while (pParm)
{
NameValue elem;
elem.name = pParm->Attribute("name");
elem.value = pParm->Attribute("value");
xmlread.push_back(elem);
pParm = pParm->NextSiblingElement("Parameter");
}
}
}
return xmlread;
}
int main()
{
try
{
vector<NameValue> elems = read();
for (vector<NameValue>::size_type i = 0; i < elems.size(); ++i)
{
cout << elems[i].name << endl;
cout << elems[i].value << endl;
}
/* or:
for (vector<NameValue>::iterator iter = elems.begin(); iter != elems.end(); ++iter)
{
cout << iter->name << endl;
cout << iter->value << endl;
}
*/
/* or:
for (auto &elem : elems)
{
cout << elem.name << endl;
cout << elem.value << endl;
}
*/
}
catch (const exception &e)
{
cerr << e.what() << endl;
}
return 0;
}
推荐阅读
- javascript - https.get 不保存到外部变量(绝对容易)
- angular - Ionic 中的电容器 CLI 版本错误。该怎么办?
- python - 有没有更快的方法从一维数组中的随机索引插入数据?
- wechat-miniprogram - 如何在微信小程序开发人员中编写代码以找到我的位置
- javascript - Shopify 结帐后管理产品数量
- macos - Homebrew 新安装占用多少空间?
- r - 在 R 中创建数据帧时出现错误消息
- node.js - 您可以在 express 中渲染模板,然后在满足条件时更改它吗?
- java - 无法解决 Spring 中 JPA 和 REST 控制器的循环引用问题
- c++ - 转置表使算法变慢(我做错了吗?)