【问题标题】:Cannot output vector<string> to a file无法将向量<string> 输出到文件
【发布时间】:2013-01-27 23:05:19
【问题描述】:

我是 C++ 新手。我无法将数据输出到文件。我正在使用迭代器打印出地图。 print 方法接受 i,一个键值,并打印出它对应的向量。现在,当我使用 cout

    public: void print(int i, vector<string> in, ostream& outfile) // print method for printing a vector and it's key
{

    sort(in.begin(), in.end()); // sort the vector alphabetically first

    vector<string>::iterator it; 

    it= unique(in.begin(), in.end()); // makes sure there are no duplicate strings

    in.resize( distance(in.begin(),it) );

    for( it = in.begin(); it != in.end(); it++ ) // iterate through it

    cout << i << ": "<< *it<<endl; // and print out the key value and each string in the vector
   // outfile<< i << ":" << *it<< endl; // prints to file
}

【问题讨论】:

  • 与错误无关,但您可以通过从std::vector:std::set&lt;string&gt; s(in.begin(), in.end()); 创建一个std::set 来节省一些排序和调整大小。
  • 在这个问题和this question 之间,你的作业中是否有任何部分来获取一个值向量并写出一个没有的唯一值列表你对吗?值得称赞的是,至少你写了一些代码,这比大多数人的尝试都要多。
  • @WhozCraig - 值得称赞的是,他尝试并遇到了一个他不知道的问题。通过这些天的一些教学,我并不惊讶有些人不知道正确的范围界定。
  • @slugonamission 我同意。老实说,我对他的导师印象深刻,因为他允许他使用标准库的工具。他已经为他准备好了,这也很高兴看到改变。
  • @user2016393: cout &lt;&lt; i ... 行是为了替换 outfile &lt;&lt; i ... 行只是为了调试目的,还是你真的想同时做这两件事?我的意思是同时写入标准输出和文件?

标签: c++ vector cout


【解决方案1】:

您是否同时使用cout 行?如果是这样,我想我知道它是什么。

for 循环,不带大括号将执行下一条语句作为其循环体。如果您同时使用cout 行和outfile 行,您将打印所有内容,然后在循环之后,it 将位于数组末尾的后面。然后,您尝试取消引用它并将其写入文件,这当然会失败,因为您取消引用无效的迭代器。

简短的回答,用大括号将语句包装在你的 for 循环中。

例如,您有以下内容(正确缩进时):

for( it = in.begin(); it != in.end(); it++ ) // iterate through it
    cout << i << ": "<< *it<<endl; 
outfile<< i << ":" << *it<< endl; // prints to file

在最后一行,it = in.end(),其中in.end() 是元素刚刚过去向量的末尾。然后,您尝试访问该位置不存在(并且无效)的元素,因此它失败了。相反,您需要将其移动到循环内,该循环应为

for( it = in.begin(); it != in.end(); it++ ) // iterate through it
{
    cout << i << ": "<< *it<<endl; // and print out the key value and each string in the vector
    outfile<< i << ":" << *it<< endl; // prints to file
}

【讨论】:

  • +1,不错。我自己在最后的评论上隔开,没有看到牙套增加了这种反射(至少对我来说)。
  • 非常感谢!我觉得很傻,我之前没有看到那个错误。最初我只有一个语句,所以当我添加第二个时,我只是忘记打扰我猜的大括号。
  • @user2016393 这是一个非常常见的错误;有些人觉得可以通过对使用{} 的宗教信仰来纠正,即使只有一个声明。一点都不难过;经验丰富的工程师也不能幸免于这些小事。
【解决方案2】:

@slugonamission 已经给了你正确的答案,所以我只想指出你的函数实际上可以被简化并且更不容易出错。我写这个作为答案只是因为需要代码格式化,否则我会在评论中发布:

void print(int i, vector<string> v, ostream& o)
{
    sort(begin(v), end(v));
    v.erase(unique(begin(v), end(v))); // Do this in one step, no iterator mess
    for (auto const& s : v) // Avoid manual iteration cycles if you can
    {
        o << i << ":" << s << endl;
        ...
    }
}

编辑:

正如@juanchopanza 正确指出的那样,实现相同目标的更快方法是将矢量的内容传输到关联容器中以确保唯一性。这将允许您通过const &amp; 传递向量:

void print(int i, vector<string> const& v, ostream& o)
{
    unordered_set<string> c(begin(v), end(v));
    for (auto const& s : c)
    {
        o << i << ":" << s << endl;
    }
}

【讨论】:

  • 可以通过从输入std::vector构造一个std::set来进一步简化。
  • @juanchopanza:只要主要工作负载不在于遍历集合的所有元素、执行基于位置的访问或修改集合中的值(使用关联容器)那么您是对的,您可以使用std::set 并避免每次执行输出时进行排序。让我补充一下。
  • 避免sortunique 意味着v 可以作为const&amp; 传递。我意识到这些细节对于这个问题来说可能过于精致了。
  • @juanchopanza:好吧,我的回答并没有严格解决这个问题,因为@slugonamission 已经发现了错误。我只是想提出一个替代的、不易出错的解决方案(“你做的越少,你f**k up 越少”)。所以我相信添加一些短的 cmets 并没有什么坏处。是的,您可以通过 const&amp;,尽管这意味着您的集合不能有重复项,这可能是该功能之外的不良限制。
  • 我意识到您解决了重要问题,我赞成您的回答。我对setconst&amp; 的意思是,该函数可以采用任意排序和重复的const vector&lt;string&gt;&amp;,从中生成set,而不是排序、唯一化、调整大小......所以函数签名保持原样。这只是一个实现细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
相关资源
最近更新 更多