簡體   English   中英

C ++:從stringstream到char **

[英]C++: From stringstream to char**

我有一個帶有parse(int argc, char* argv[])函數的類,我必須使用它來設置對象的所需狀態。 我使用stringstream從gui中獲取參數,然后嘗試將它們轉換為char **以將其傳遞給函數。 這是我得到的:

std::stringstream sstream;

sstream << "-clip" << " " << min_x_entry.get_text()
        << " " << max_x_entry.get_text(); // etc.

std::cout << sstream.str();    // All looks good here

std::vector<std::string> args;
std::vector<char*> argv;
std::string arg;

while (sstream >> arg)
{
    args.push_back(arg);
    argv.push_back(const_cast<char*>(args.back().c_str()));
}
argv.push_back(0);

int argc = args.size();

for (int i = 0; i < argc; ++i)
    std::cout << &argv[0][i];    // This outputs garbage

my_object.parse(argc, &argv[0])  // And this fails

我想念什么? 有沒有更好的方法來實現這一目標?

一個問題是args向量的重新分配,因為push_back()會在必要時增大向量的大小:

如果new size()不大於Capacity(),則沒有迭代器或引用無效。 否則,所有迭代器和引用都將無效。

argv向量在args存儲了指向元素內部的指針,因此這些指針將失效。

一種解決方案是先創建args向量,然后再創建argv向量:

while (sstream >> arg) args.push_back(arg);

for (auto i = args.begin(); i != args.end(); i++)
{
    argv.push_back(const_cast<char*>(i->c_str()));
}
argv.push_back(0);

打印出argv字符串的for循環不正確。 這個:

&argv[0][i]

是一個char*但從argv第一個條目的第i個元素開始。 例如,如果argv的第一個c字符串是"string"

&argv[0][1] is "tring"
&argv[0][2] is "ring"

改成:

for (int i = 0; i < argc; i++)
    std::cout << argv[i] << std::endl; // Added 'endl' to flush 'cout'.
std::vector<std::string> args;
std::vector<char*> argv;

/* ... */

    argv.push_back(const_cast<char*>(args.back().c_str()));

這里有很多問題。

  1. 在后續調用同一string的非const成員函數之后,不能保證c_str()返回的指針有效。 c_str()返回的指針通常不應該在以后存儲和使用,尤其是當您不確定其他代碼是否會調用string的非const成員時。
  2. const_cast荷蘭國際集團的const -nedd從返回的指針遠c_str() 演員表本身是合法的,如果不是反模式的話。 但是,如果以后再嘗試修改存儲在該指針處的數據,那就是未定義行為。

這是標准對c_str()

21.3.6 basic_string字符串操作[lib.string.ops]

const charT* c_str() const;

1 /返回:指向長度為size()+ 1的數組的初始元素的指針,其第一個size()元素等於* this控制的字符串的相應元素,而最后一個元素為charT()指定的空字符。

2 /要求:程序不得更改數組中存儲的任何值。 在隨后調用基本Basic字符串類的非常量成員函數並指定與此對象之后,程序也不會將返回值視為有效的指針值。 const charT * data()const;

3 /返回:如果size()不為零,則該成員返回一個指向數組初始元素的指針,該數組的第一個size()元素等於由* this控制的字符串的相應元素。 如果size()為零,則該成員返回一個非空指針,該指針是可復制的,並且可以添加零。

4 /要求:程序不得更改存儲在字符數組中的任何值。 在隨后調用basic_string的非const成員函數並指定與此相同的對象之后,程序也不會將返回的值視為有效的指針值。 allocator_type get_allocator()const;

5 /返回:用於構造字符串的Allocator對象的副本。

您忘記了在循環中初始化變量i 並且您試圖僅打印出矢量argv的第一項。

for (int i = 0; i < argc; ++i)
    std::cout << argv[i];

您可以擺脫const_cast而不必擔心parse()方法可能通過執行以下操作來修改參數:

std::vector<std::vector<char>> args;

std::for_each(std::istream_iterator<std::string>(sstream),
              std::istream_iterator<std::string>(),
              [&args](const std::string& str)
              {
                  std::vector<char> temp(str.begin(), str.end());
                  temp.push_back('\0');
                  args.push_back(temp);
              });

std::vector<char*> argv(args.size());

for (auto& v : args) argv.push_back(v.data());

my_object.parse(argv.size(), argv.data());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM