【问题标题】:Getting the words from a sentence and storing them in a vector of strings从句子中获取单词并将它们存储在字符串向量中
【发布时间】:2013-11-21 06:13:17
【问题描述】:

好吧,伙计们......

这是我的一套,里面有所有的字母。我将一个词定义为由集合中的连续字母组成。

const char LETTERS_ARR[] = {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
const std::set<char> LETTERS_SET(LETTERS_ARR, LETTERS_ARR + sizeof(LETTERS_ARR)/sizeof(char));

我希望这个函数能接收一个表示句子的字符串,并返回一个字符串向量,这些字符串是句子中的单个单词。

std::vector<std::string> get_sntnc_wrds(std::string S) { 
    std::vector<std::string> retvec;
    std::string::iterator it = S.begin(); 
    while (it != S.end()) { 
        if (LETTERS_SET.count(*it) == 1) { 
            std::string str(1,*it);
            int k(0);
            while (((it+k+1) != S.end()) && (LETTERS_SET.count(*(it+k+1) == 1))) { 
                str.push_back(*(it + (++k)));
            }
            retvec.push_back(str);
            it += k;
        }
        else { 
            ++it;
        }
    }
    return retvec;
} 

例如,以下调用应返回字符串“Yo”、“dawg”等的向量。

std::string mystring("Yo, dawg, I heard you life functions, so we put a function inside your function so you can derive while you derive.");
std::vector<std::string> mystringvec = get_sntnc_wrds(mystring);

但一切都没有按计划进行。我尝试运行我的代码,它将整个句子放入向量的第一个也是唯一一个元素中。我的函数是非常混乱的代码,也许你可以帮我想出一个更简单的版本。我不希望您能够在我编写该函数的可怜尝试中追踪我的思维过程。

【问题讨论】:

    标签: c++


    【解决方案1】:

    试试这个:

    #include <vector>
    #include <cctype>
    #include <string>
    #include <algorithm>
    
    // true if the argument is whitespace, false otherwise
    bool space(char c)
    {
      return isspace(c);
    }
    
    // false if the argument is whitespace, true otherwise
    bool not_space(char c)
    {
      return !isspace(c);
    }
    
    vector<string> split(const string& str)
    {
      typedef string::const_iterator iter;
      vector<string> ret;
      iter i = str.begin();
    
      while (i != str.end()) 
      {
        // ignore leading blanks
        i = find_if(i, str.end(), not_space);
        // find end of next word
        iter j = find_if(i, str.end(), space);
        // copy the characters in [i, j)
        if (i != str.end())
          ret.push_back(string(i, j));
        i = j;
      }
      return ret;
    }
    

    split 函数将返回 vectorstrings,每个元素包含一个单词。

    此代码取自Accelerated C++ 书,所以它不是我的,但它有效。本书中还有其他使用容器和算法解决日常问题的极好的例子。我什至可以在输出控制台上显示一个文件的内容。强烈推荐。

    【讨论】:

    • 可能有空格以外的字符用于分割(如逗号)。
    • 修改 find_if 算法中的谓词(空格和 not_space)来处理这个问题并不难。
    【解决方案2】:

    这只是一个括号问题,我的建议是(几乎)永远不要放入不必要的括号,这只会使事情变得混乱

           while (it+k+1 != S.end() && LETTERS_SET.count(*(it+k+1)) == 1) { 
    

    您的代码将字符与1 进行比较,而不是count 的返回值。

    虽然 count 在这种情况下确实返回一个整数,但我会进一步简化并将返回视为布尔值

           while (it+k+1 != S.end() && LETTERS_SET.count(*(it+k+1))) { 
    

    【讨论】:

      【解决方案3】:

      您应该像这样使用string steamstd::copy

      #include <iostream>
      #include <string>
      #include <sstream>
      #include <algorithm>
      #include <iterator>
      #include <vector>
      
      int main() {
          std::string sentence = "And I feel fine...";
          std::istringstream iss(sentence);
          std::vector<std::string> split;
          std::copy(std::istream_iterator<std::string>(iss),
                    std::istream_iterator<std::string>(),
                    std::back_inserter(split));
      
          // This is to print the vector
          for(auto iter = split.begin();
              iter != split.end();
              ++iter)
          {
              std::cout << *iter << "\n";
          }
      }
      

      【讨论】:

      • 虽然我也想过类似的方法,但是除了空格之外可能还有其他字符可以用来分割(比如逗号)。
      • @AbhishekBansal 这是一个简单的解决方法,因为您可以在解析之前将字符串中的所有“,”替换为“,”。
      • 嗯,可能还有其他非字母字符,例如“。” '(' '*' 等。如果你需要替换那些字符,那么 IMO 使用 stringstream 的优势就失去了。
      • @AbhishekBansal 不确定STD 库是否可以处理所有这些情况,我相信这是您无需编写自己的自定义方式即可获得的壁橱。此外,OP 目前正在使用isspace,它不处理这些情况。
      • OP 没有使用 isspace()。它用于发布的其他答案之一。 OP 定义了一组有效字符,如果该字符与该组中的任何字符都不匹配,则该字符串被拆分。
      【解决方案4】:

      我会使用另一种更简单的方法,基于类 std::string 的成员函数。例如

          const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
      
          std::string s( "This12 34is 56a78 test." );
      
          std::vector<std::string> v;
      
          for ( std::string::size_type first = s.find_first_of( LETTERS, 0 ); 
                first != std::string::npos; 
                first = s.find_first_of( LETTERS, first ) )
          {
              std::string::size_type last = s.find_first_not_of( LETTERS, first );
              v.push_back(
                  std::string( s, first, last == std::string::npos ? std::string::npos : last - first ) );
              first = last;
          }
      
          for ( const std::string &s : v ) std::cout << s << ' ';
          std::cout << std::endl;
      

      【讨论】:

        【解决方案5】:

        这里你犯了2个错误,我在下面的代码中更正了。

        首先应该是

        while (((it+k+1) != S.end()) && (LETTERS_SET.count(*(it+k+1)) == 1))

        并且,它应该移动到下一个

        it += (k+1);

        代码是

            std::vector<std::string> get_sntnc_wrds(std::string S) { 
            std::vector<std::string> retvec;
            std::string::iterator it = S.begin(); 
            while (it != S.end()) { 
                if (LETTERS_SET.count(*it) == 1) { 
                    std::string str(1,*it);
                    int k(0);
        
                    while (((it+k+1) != S.end()) && (LETTERS_SET.count(*(it+k+1)) == 1)) { 
                        str.push_back(*(it + (++k)));
                    }
                    retvec.push_back(str);
                    it += (k+1);
                }
                else { 
                    ++it;
                }
            }
            return retvec;
        }
        

        输出已经过测试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-12
          • 2015-05-07
          • 2014-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多