c++ 为什么我不能把字符串放入字符串流对象?

niwlg2el  于 2023-03-05  发布在  其他
关注(0)|答案(3)|浏览(151)

我需要做一个C++程序来获取句子中的每一个单词,而不需要重复。我试着把每个单词都放到字符串流对象中,但是它根本就没有把它放在字符串流对象中。下面是代码:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

bool is_there_any(string word, stringstream& words)
{
    string w;
    while (words >> w)
    {
        if (!word.compare(w))
            return true;
    }
    words << word;//This one doesn't work for some reason...
    return false;
}

int main()
{
    string sentence, word;
    getline(cin, sentence);
    stringstream stream, words;
    stream.str(sentence);
    words.clear();
    while (stream >> word)
    {
        if (!is_there_any(word, words))
            cout << word << endl;
    }
    return 0;
}

我试着调试,发现这行代码words << word;不起作用,它没有在“words”中插入任何东西,而且word不是空字符串。

vhmi4jdf

vhmi4jdf1#

这种方法存在根本性的缺陷,你试图做一个O(N^2)的运算,对句子中的每个单词都要重新处理,然后再把单词塞回去。
这既不是直观的,也不是可执行的,它需要一些丑陋的黑客使它甚至工作在所有。
一个更好的方法是维护一个到目前为止遇到的单词集。然后,您只需读取单词并尝试将它们添加到该单词集中。您只输出那些不在该单词集中的单词。这段代码不仅更高效,而且更容易理解。

#include <iostream>
#include <sstream>
#include <string>
#include <unordered_set>

using namespace std;

int main()
{
    unordered_set<string> words;
    string sentence, word;

    while (getline(cin, sentence))
    {
        istringstream iss(sentence);
        while(iss >> word)
        {
            if (words.insert(word).second)
            {
                cout << word << "\n";
            }
        }
    }
}

输入:

This is a sentence
This is another sentence

输出:

This
is
a
sentence
another
dgiusagp

dgiusagp2#

正如您所读到的paddy以前的答案一样,您的方法并不是最好的;set类总是当你试图得到不重复的对象时的答案,在这个例子中你想要不重复的单词。
虽然你的方法是错误的,我会指出一些愚蠢的错误,也许对其他项目将帮助你,将不必被困扰的幽灵“我做错了什么,在这个函数”:

  • is_there_any()函数中,你使用>>操作符清空sstringstream,这就是为什么你不能得到流中未重复的单词,相反,你总是检查一个空流。

解决此问题的一种方法是在另一个sstringstream对象上实际复制以前的内容并使用它:

请注意,这不是最佳方法,因为您要为每个待检查的待定单词迭代每个未重复的单词(成本为O(n^2))

bool is_there_any(string& word, stringstream& words)
{
  string w;
  stringstream copyOfWords;
  copyOfWords.str(words.str());
  while (copyOfWords >> w)
  {
      if (!word.compare(w))
          return true;
  }
  words <<word <<" ";
  return false;
}
  • 你不应该使用sstringstream中的clear()函数,除非你产生了一些异常,并且你正在处理它,因为你仍然需要使用那个对象。

它不会影响您想要的输出,但它可能会让您在将来感到困惑(我认为您想从sstringstream中清除流缓冲区,但它根本没有这样做,它被用于清 debugging 误状态标志)。

bweufnob

bweufnob3#

我想感谢每一个花时间回答我问题的人。请注意,我只是一个初学者,最近遇到了这个任务,他们特别要求使用stringstream类来解决这个问题。我将测试你们所有的解决方案!再次感谢你们的详细解释。干杯!

相关问题