在最终迭代中简单的'for'循环崩溃程序

时间:2009-10-14 16:07:17

标签: c++ loops

以下程序似乎每次都在最后崩溃,我假设这是因为一旦我到达i =(size-1),那么wordList [i + 1]将不会返回任何内容,返回null或等效的东西。有什么方法吗?我是否认为这是我问题的根源?

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>

using std::cin;
using std::cout;            using std::endl;
using std::sort;
using std::string;          using std::vector;

// Obtain a list of words and return the de-duped list
// with an accompanying word count
int main()
{
    cout << "Enter a series of words separated by spaces, "
            "followed by end-of-file: ";

    vector<string> wordList;
    string x;
    while (cin >> x)
          wordList.push_back(x);

    typedef vector<string>::size_type vec_sz;
    vec_sz size = wordList.size();
    if (size == 0) {
       cout << endl << "This list appears empty.  "
                       "Please try again."  << endl;
       return 1;
    }

    sort(wordList.begin(), wordList.end());

    cout << "Your word count is as follows:" << endl;
    int wordCount = 1;
    for (int i = 0; i != size; i++) {
        if (wordList[i] == wordList[i+1]) {
           wordCount++;
           }
        else {
             cout << wordList[i] << "    " << wordCount << endl;
             wordCount = 1;
             }
         }
    return 0;
}

11 个答案:

答案 0 :(得分:7)

两个问题。

首先,通常最好循环,直到你的索引为&lt;你的尺寸,而不是使用!=。你有什么应该仍然在这里工作。

问题在于这一行:

if (wordList[i] == wordList[i+1])

您需要先提前停止循环(i&lt; size - 1)或更改if语句,以便在至少再有一个条目时检查wordList [i] == wordList [i + 1]在阵列中。

更简单的方法可能是从i = 1循环到i&lt;大小,并检查wordList [i-1] == wordList [i]:

for(int i = 1; i < size; i++) {
  if(wordList[i - 1] == wordList[i]) {
    /* same as before */
  }
  /* everything else the same */
}

这将阻止您需要额外的if语句,但仍然可以保护您不会离开数组的边界。

编辑:

正如评论中所提到的,如果您使用所有原始代码并且只是像我提到的那样更改循环,则会出现一个1分之一的错误,但它很容易修复。

将单词计数开始为1而不是0.您知道您将始终至少有一个唯一单词。这个循环会在它看到一个新单词时递增该计数,所以你最终会得到正确的计数。

你需要的唯一额外处理是当wordList为空时。因此,您需要快速检查单词列表是否为空,在这种情况下,计数为0。

答案 1 :(得分:3)

您需要进行两项更改。如前面的评论中所述,您的结束条件应为&lt; size-1以防止读出界限。你还需要打印最后一项的计数,这将是wordCount,因为如果它的唯一wordCount是1,如果没有,它已经被添加。更正后的代码:

for (int i = 0; i < size-1; i++) {
    if (wordList[i] == wordList[i+1]) {
       wordCount++;
       }
    else {
         cout << wordList[i] << "    " << wordCount << endl;
         wordCount = 1;
         }
     }
cout << wordList[size-1] << "    " << wordCount << endl;

答案 2 :(得分:2)

您应该将代码更改为for (int i = 0; i < size-1; i++) {,因为wordList[i+1] i+1的值必须小于size。结果意味着i < size -1

C / C ++数组是否可以包含从0size-1的索引。

答案 3 :(得分:1)

是。边界条件失败。 vector[size()]是未定义的值。

  if (wordList[i] == wordList[i+1]) ---> out of bounds

可以循环使用size()-1

答案 4 :(得分:0)

这正是问题所在。您的向量包含“大小”项,但您尝试访问向量的末尾。

你需要做的是在最后一项之前停止for循环,这样i + 1才能访问最后一项。

例如:

for (int i = 0; i < (size - 1); i++) {

答案 5 :(得分:0)

更改

for (int i = 0; i != size; i++) {

for (int i = 0; i != size-1; i++) {

答案 6 :(得分:0)

那是因为对于i == size-1,i + 1 == size。并且wordList [size]不在列表的末尾。您可能需要将for循环条件更改为“i&lt; size - 1”。

答案 7 :(得分:0)

它不是NULL,它超出了范围。你应该至少检查一下我是不是在进行比较之前的大小。

我不确定你在比较中想要做什么,但这是一个更广泛的问题。

答案 8 :(得分:0)

您可以检查i == wordList长度并退出/跳过if。

答案 9 :(得分:0)

有时只是代码可以更简单......如果您使用其他东西。

问题陈述:向每个单词返回一个带有关联的单词的已删除列表。

我个人会为std :: map寻找这样的声明。

// Yeah it feels stupid, but I want default construction to initialize...
struct MyCount
{
  MyCount() : _count(0) {}
  size_t _count;
};

std::ostream& operator<<(std::ostream& out, const MyCount& rhs)
{ 
  return out << rhs._count;
}

int main()
{
  cout << "Enter a series of words separated by spaces, "
          "followed by end-of-file: ";

  typedef std::map<std::string, MyCount> map_type;
  map_type wordList;
  std::string x;
  while (std::cin >> x)
    wordList[x] += 1; // This is why I have a struct instead of a plain size_t

  if (wordList.empty()) {
    cout << endl << "This list appears empty.  "
                    "Please try again."  << endl;
    return 1;
  }

  cout << "Your word count is as follows:" << endl;
  for (map_type::const_iterator it = wordList.begin(), end = wordList.end(); it != end; ++ it) {
    std::cout << it->first << "    " << it->second << std::endl;
  }
  return 0;
}

我知道std :: vector是默认容器,但是如果你要“关联”两个实体(这里是一个单词及其出现次数),那么你最好不要考虑关联容器。

答案 10 :(得分:-1)

您可能想尝试

for (int i = 0; i < size; i++)

这将阻止循环尝试寻址超出范围的索引。