0

我正在尝试根据下面的提示创建一个程序,但我一直收到一个Caught std::exception, what(): basic_string::at: __n (which is 0) >= this->size() (which is 0)错误,虽然我在 C++ 方面很扎实,但我想时间会付出代价。我的代码在下面。基本上,首先我通过空格字符解析字符串,然后将它们保存在 avector<string>中,然后我检查一个单词是否大于 5,如果是则反转它,如果不是,则不执行任何操作。如果这不是最终话,我会在最后添加一个空格。砰砰砰,提示完成,至少我是这么想的。

std::string spinWords(const std::string &str)
    {
      std::vector<std::string> words;
      std::string spinnedWord;
      int count = 0;
      for(unsigned int i = 0; i < str.length(); i++)
      {
          char currentChar = str.at(i);

          if (currentChar == ' ')
          {
              count++;
              continue;
          }
          else if((int)words.size() == count)
          {
              words.push_back(&currentChar);
          }
          else
          {
              words[count] += currentChar;
          }
      }
      for(unsigned int i = 0; i < words.size(); i++)
      {
          if(words[i].size() >= 5)
          {

              for (unsigned int j = words[i].length() - 1; j >= 0; j--)
              {
                  spinnedWord += words[j].at(i);
              }
          }
          if(i + 1 != words.size())
          {
              spinnedWord += ' ';
          }
      }
      return spinnedWord;
    }// spinWords

编写一个函数,接收一个或多个单词的字符串,并返回相同的字符串,但所有五个或更多字母单词都颠倒了(就像这个 Kata 的名字一样)。传入的字符串将仅包含字母和空格。仅当存在多个单词时才会包含空格。

Edit1:我已更改words[j].at(i);words[i].at(j); ,我已更改words.push_back(&currentChar);words.push_back(std::string(1, currentChar));

据我目前的理解,当我推回时&currentChar,我导致了一个未定义的行为。我会研究如何在未来避免这种情况。但是,之前的错误仍然存​​在,因此问题仍未得到解答

4

3 回答 3

4
for (unsigned int j = words[i].length() - 1; j >= 0; j--)
{
   spinnedWord += words[j].at(i);
}

你在这里换j了一个i。一定是words[i].at(j)。这里也j可能不应该是无符号的,因为循环条件j >= 0对于无符号整数总是正确的。

编辑:对线路的 UB 关注words.push_back(&currentChar)也是有效的。修复它的方法是从char显式构造一个字符串:

words.push_back(std::string(1, currentChar));
于 2020-04-09T16:21:47.293 回答
1
          words.push_back(&currentChar);

您正在尝试std::string从指向单个字符的指针构造 a 。这可以编译,因为有一个匹配的构造函数,但它需要一个 C 样式的字符串,而指向单个字符的指针不是。

于 2020-04-09T16:18:50.897 回答
0

说真的,我什至不明白你的代码。例如变量count在程序中的作用。或者为什么您要使用其他容器,例如std::vector何时可以并且应该使用该类型的对象完成所有操作,std::string因为它具有执行任务的所有资源。

std::vector仅当分配是将字符串拆分为单词并返回类型对象中的单词时,才需要容器std::vector<std::string>。但你的任务完全不同。

请注意,通常单词之间可以有多个空格。即使不是这样,在任何情况下,您都应使用通用方法,而不是依赖于单词之间只有一个空格的方法。

例如,当原始字符串从空格字符开始时,您的函数没有意义。在这种情况下,由于这个 if 语句,count将等于1

      if (currentChar == ' ')
      {
          count++;
          continue;
      }

但是向量的大小将等于0,因此words.size()不等于count则将执行else语句

      else if((int)words.size() == count)
      {
          words.push_back(&currentChar);
      }
      else
      {
          words[count] += currentChar;
      }

这会导致未定义的行为。

我可以建议以下解决方案。在下面的演示程序中,我不使用标准算法 std::reverse 因为我认为您必须通过自己的代码来反转单词。

这个给你。

#include <iostream>
#include <string>
#include <utility>

std::string spinWords( const std::string &s, std::string::size_type length = 5 )
{
    std::string t( s );
    const char *delim = " \t";

    for ( std::string::size_type i = 0; i != t.size();  )
    {
        auto pos = t.find_first_not_of( delim, i );

        if ( pos != std::string::npos )
        {
            i = t.find_first_of( delim, pos );

            if ( i == std::string::npos ) i = t.size();

            if ( length < i - pos )
            {
                auto n = i - pos;

                for ( std::string::size_type j = 0; j < n / 2; j++ )
                {
                    std::swap( t[pos + j], t[i - j - 1] );
                }
            }
        }
        else
        {
            i = t.size();
        }
    }

    return t;
}

int main() 
{

    std::string s( "1 12 123 1234 12345 123456 1234567 123456789 1234567890" );

    std::cout << s << '\n';
    std::cout << spinWords( s ) << '\n';

    return 0;
}

程序输出为

1 12 123 1234 12345 123456 1234567 123456789 1234567890
1 12 123 1234 12345 654321 7654321 987654321 0987654321
于 2020-04-09T16:46:23.940 回答