[英]Trying to pass 2D array of chars, but getting garbage
我正在尝试解析std::string
,将其拆分,然后将其存储在2D char数组中。 该数组的第一行将包含总行数。 我在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;
}
OUTPUT:
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
您可以尝试这种不会泄漏内存的方法。 它是根据此处找到的解决方案制作的。
#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
维护基础结构,并且在使用基础结构时将其破坏是不正确的。
在几个地方:
// store the number of rows at the first row
(*cargs)[0] = new char[to_string(numArgs_).size()];
(*cargs)[0] = to_string(numArgs_).c_str();
和
// Similar code that allocates then ignores some space
(*cargs)[ind] = const_cast<char*>(v.c_str());
您正在执行一个指向std :: string内部部分的指针。 您需要将其复制到数组中,才能在char数组结构中使用它。 (请参阅strdup)。
用。。。来代替:
(*cargs)[0] = strdup(to_string(numArgs_).c_str());
和
(*cargs)[ind] = strdup(v.c_str());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.