我正在尝试解析一个 std::string
,拆分它,然后将它存储在一个二维字符数组中。该数组的第一行将包含总行数。
我在 getC_strings()
函数内动态分配数组,当我打印它时,我得到了预期的结果。但是,当我再次从 main()
打印时,第 0、2 行出现垃圾。我做错了什么?
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp> // Include for boost::split
using namespace std;
/**
*
* @param input a string separated by spaces
* @param numArgs_ an int
* @param cargs a const char ** something. Pass it by its address aka &something.
*/
static inline void getC_strings(const std::string & input, int & numArgs_, const char *** cargs) {
std::vector<std::string> args;
boost::split(args, input, boost::is_any_of(" "), boost::token_compress_on);
numArgs_ = int(args.size());
*cargs = new const char* [numArgs_ + 1];
// store the number of rows at the first row
(*cargs)[0] = new char[to_string(numArgs_).size()];
(*cargs)[0] = to_string(numArgs_).c_str();
// write the characters from the vector per row
int ind = 0;
for(auto const &v:args) {
ind++;
(*cargs)[ind] = new char [int(v.size())];
if((*cargs)[ind] == NULL) std::cout << "OUT OF MEMORY! " << std::endl;
(*cargs)[ind] = const_cast<char*>(v.c_str());
}
for(int i = 0; i < numArgs_; ++i) {
std::cout << i << " " << (*cargs)[i] << std::endl;
}
}
int main () {
string arg = "test ./MyDirectoryName/OPQ_Arksoatn.txt 1 SOMETHING 1 2 3 4 5 6 7";
int numCargs = 0;
const char ** cargs;
getC_strings(arg, numCargs, &cargs);
cout << " ==============================================" << endl;
for(int i = 0; i < numCargs; ++i) {
std::cout << i << " " << cargs[i] << std::endl;
}
return 0;
}
输出:
0 11
1 test
2 ./MyDirectoryName/OPQ_Arksoatn.txt
3 1
4 SOMETHING
5 1
6 2
7 3
8 4
9 5
10 6
==============================================
0 ��`
1 test
2 `��
3 1
4 SOMETHING
5 1
6 2
7 3
8 4
9 5
10 6
最佳答案
你可以试试这个不泄漏内存的方法。它由溶液 found here 制成.
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp> // Include for boost::split
using namespace std;
class CharStarWrapper
{
private:
typedef std::vector<char> CharArray;
typedef std::list<CharArray> StringList;
typedef std::vector<const char *> ArgList;
const char** m_Args;
StringList m_sList;
ArgList m_cStrings;
public:
CharStarWrapper(const std::string & input) : m_Args(nullptr)
{
std::vector<std::string> args;
boost::split(args, input, boost::is_any_of(" "), boost::token_compress_on);
for (auto const &v : args)
{
// create an array of char and place on list
m_sList.push_back(CharArray(v.begin(), v.end()));
// null terminate this entry
m_sList.back().push_back(0);
// add the pointer to this entry to the vector of const char *.
m_cStrings.push_back(&m_sList.back()[0]);
}
m_Args = m_cStrings.data();
}
const char** getArgs() { return m_Args; }
int getArgCount() const { return static_cast<int>(m_cStrings.size()); }
};
void fake_main(int argc, const char **argv)
{
std::cout << "The number of arguments is " << argc << "\n";
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << "\n";
}
int main() {
string arg = "test ./MyDirectoryName/OPQ_Arksoatn.txt 1 SOMETHING 1 2 3 4 5 6 7";
CharStarWrapper wrapper(arg);
fake_main(wrapper.getArgCount(), wrapper.getArgs());
}
基本上,我们将 const char**
包装在一个类中。该类维护动态字符串数组,仅提供public
成员函数返回const char**
以及参数个数。对“假”main()
函数的调用演示了用法。
没有调用 new[]
、delete[]
、strdup
等需要调用释放例程避免内存泄漏。当包装器超出范围时,所有内存都会自动清理。
请注意,此解决方案依赖于在您将使用 const char **
值的生命周期内不超出范围的包装对象。原因是 CharStarWrapper
维护基础设施,在使用它的同时破坏基础设施是不正确的。
关于c++ - 试图传递二维字符数组,但得到垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42846490/