将字符串转换为 const char*

Joh*_*554 2 c++ arrays vector argv

我正在尝试修改程序,以便当参数传递到 argv 时可以修改它们,然后创建一个新数组并用于执行。目前,我正在创建一个 const char* 向量,以便在构建数组之前保存值。

当我构建向量时,我更改的任何值都会作为随机数据而不是我正在构建的字符串(我构建了一个字符串,然后使用 c_str() 将其传递给向量)。下面是代码:

int main(int argc, char const *argv[])
{
    std::vector<const char*> args;

    for(uint i = 0; i < (uint)argc; i++)
    {
        if(((string)argv[i] == "-t" || (string)argv[i] == "--test") && (uint) argc - 1 > i)
        {
            string testPath = test::testPath().lexically_normal().string();
            if (boost::filesystem::exists(argv[i+1]) && !strstr(argv[i+1], testPath.c_str()))
            {
                if (boost::filesystem::is_regular_file(argv[i+1]))
                {
                    boost::filesystem::path p(argv[i+1]);
                    boost::filesystem::path newPath = test::testPath().lexically_normal();
                    newPath /= "/ImportedTests";
                    if (!boost::filesystem::exists(newPath.lexically_normal()))
                    {
                        if(boost::filesystem::create_directory(newPath.lexically_normal()))
                            cout << "An error occurred creating the import directory for specified tests at " << newPath << endl;
                    }
                    
                    newPath /= p.filename();
                    cout << "newPath = " << newPath << endl;
                    
                    if(boost::filesystem::extension(newPath) == ".nuk" || boost::filesystem::extension(newPath) == ".div")
                    {
                        if (rename(argv[i+1], newPath.c_str()) != 0)
                            cout << "Error importing tests." << endl;
                    }

                    args.push_back(argv[i]);
                    args.push_back(newPath.c_str()); 
                    cout << "newPath.c_str() = " << newPath.c_str() << endl; // Prints readable output.
                    i++;
                }
                else
                {
                    boost::filesystem::path p(argv[i+1]);
                    boost::filesystem::path newPath = test::testPath().lexically_normal();
                    newPath /= "/ImportedTests";
                    if (!boost::filesystem::exists(newPath.lexically_normal()))
                    {
                        if(boost::filesystem::create_directory(newPath.lexically_normal()))
                            cout << "An error occurred creating the import directory for specified tests at " << newPath << endl;
                    }
                    
                    for (const auto & entry : fs::directory_iterator(argv[i+1]))
                    {
                        if (boost::filesystem::extension(entry.path()) == ".sol" || boost::filesystem::extension(entry.path()) == ".yul" )
                        {
                            if (rename(entry.path().c_str(), newPath.c_str()) != 0)
                                cout << "Error importing tests." << endl;
                        }
                    }

                    args.push_back(argv[i]);
                    args.push_back(newPath.string().c_str());
                    cout << "newPath.c_str() = " << newPath.c_str() << endl;
                    i++;
                }
            }
        }
        else
        {
            args.push_back(argv[i]);
        }
    }
    for(uint i = 0; i < args.size(); i++){
        cout << "element " << i << " = " << args[i] << endl; // when new path is printed here it is not readable. It's just random characters.
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有编写此应用程序,因此我无法更改 argv 传递到应用程序的方式而不引起问题。我只想构建相同类型的数组并根据需要修改值。

输出如下:

newPath.c_str() = /home/dev/Development/test/ImportedTests
element 0 = test/tools/isoltest
element 1 = --vm
element 2 = ../../evmone-0.8.0-linux-x86_64/lib/libevmone.so
element 3 = -t
element 4 = Dy8^
Run Code Online (Sandbox Code Playgroud)

如果我可以将此字符串正确地转换为 const char* 我想我可以使用 args.data() 从 args 向量中获取一个数组,然后将其传递给应用程序的其余部分。

如果这完全是愚蠢的,我提前道歉。

Sam*_*hik 8

args.push_back(newPath.c_str()); 
Run Code Online (Sandbox Code Playgroud)

返回的指针c_str()归其返回对象所有。在这里,这个对象是newPath。当该对象被销毁(或者该对象被修改)时,返回的值const char *不再有效。

newPath对象在其语句结束时if()、其范围结束时被销毁。newPath是在if()语句内声明的,因此它会在语句末尾被销毁。这就是 C++ 中所有对象的工作方式。

然后,显示的代码稍后会尝试取出const char *args当它拥有newPath,此时它的所有权只是一个遥远的记忆。

这就是未定义行为和观察到的垃圾的原因。

您必须完全重新设计并从根本上重构所显示代码的逻辑,以便const char *只要此字符指针存在,拥有所有这些的对象就不会被破坏。

一个更简单的解决方案是完全摆脱字符指针。制作args一个std::vector<std::string>, 并将args.push_back(newPath)其放入其中。每当需要使用底层const char *s 时,获取它们并仅根据需要使用它们,并且无需对底层向量进行任何更改。