Проблема с программой кодирования длин серий c ++ - PullRequest
0 голосов
/ 01 октября 2018

Я пытаюсь создать код, который выполняет кодирование = длина на основе значения, введенного пользователем.Принимает только строчные буквы.Используя два вектора.Проблема заключается не во всех примерах: Пример: вывод zzzzzzzz: (завершить вызов после бросания экземпляра 'std :: out_of_range' what (): basic_string :: at: __n (который равен 8)> = this->size () (то есть 8) статус выхода -1)

Как это можно решить?

    #include <iostream>
    #include <string>
    #include <vector>

    using namespace std;

     bool is_small_letter(char c){
      return c >= 'a' && c <= 'z';
    }

    void runLength(string str, vector<char>& charachters, vector<int>& length) {
      int count;
      int i;

      for (i = 0; i < str.size(); i++) {
        if (!is_small_letter(str.at(i))) {
          throw runtime_error("invalid input");
        }

        **count = 1;
        if (i == str.size() -1) {
          // do nothing
        } else {
          while (str.at(i) == str.at(i + 1)) {
            count++, i++;
          }**  //changed following one answer advice.
        }
        charachters.push_back(str.at(i));
        length.push_back(count);
      }
    }

    int main() {
      string str;
      vector<char>charachters;
      vector<int>length;

      cout << "Enter the data to be compressed: ";
      cin >> str;
      try {
        runLength(str, charachters, length);

        cout << "The compressed data is: ";
        for (int i = 0; i <= length.size() - 1; i++){
          cout << length.at(i) << charachters.at(i);
        }

      } catch (runtime_error &excpt) {
         cout << endl << "error: " << excpt.what();
      }

      return 0;
    }

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

к сожалению, ответ mbonness только задержит вашу кончину.

Это происходит потому, что не учитывается случай, который случится, если хотя бы последние 2 символа в строке будут одинаковыми.например, что произойдет, если игрок введет abcdd?поскольку цикл while выполняет итерацию i, он выходит за рамки цикла while.следовательно, произойдет сбой.

Однако есть и другая проблема, о которой вы еще не задумывались.что произойдет, если в строке будет несколько символов, которые не находятся рядом друг с другом?например абабаб?текущий код не будет обрабатывать такое senario.

Вот почему, к сожалению, вам приходится дважды зацикливать весь вектор str.и сохраняйте каждого персонажа по одному.и всякий раз, когда вы начинаете следующую итерацию, вы должны проверить, находится ли символ уже в векторе символов.если это так, вы игнорируете сканирование и переходите к следующему.

давайте посмотрим на тело функции;

  void runLength(string str, vector<char>& charachters, vector<int>& length) {
      int count;
      int i;

      for (i = 0; i < str.size(); i++) {

Так что же происходит в цикле for?мы продолжаем бежать, пока я меньше str.size().обратите внимание, что хотя str.size() не является индексом, начинающимся с нуля, он будет работать нормально.Зачем?потому что мы не используем <= операторы.мы используем < оператор.

далее нам понадобится переменная bool, чтобы проверить, добавлен ли текущий str.at(i) к vector<char>charachters.

bool charAlreadyExist = false;

. Давайте сделаем наш второй внутренний цикл, чтобы проверить,символы содержат текущий элемент строки.

 for(int l = 0; l < charachters.size(); l++)
    {
        if(charachters.at(l) == str.at(i))
        {
           charAlreadyExist = true;
           break;
        }
    }

следующий цикл начинается только в том случае, если charAlreadyExist is false

 if (charAlreadyExist == false)
        {
          for(int j = 0; j < str.size(); j++)
          {
              if (str.at(i) == str.at(j))
              {
                count++;
              }
          }

Обратите внимание, что в приведенном выше выражении мы больше не увеличиваем i.это было причиной того, что ответ mmbonnes'а потерпел бы неудачу

, остальная часть кода функции была бы аналогична той, что вы сделали.

Вот полный код функции.но попробуйте реализовать это, не смотря на это в первую очередь.это поможет вам лучше понять код

, поэтому теперь, когда вы печатаете abababab, он напечатает правильное количество букв a и b, даже если они не находятся рядом друг с другом.

следующая вещьдля вас это то, что делать, если пользователь вводит "abab ababab".Я оставлю это вам, чтобы выяснить.подсказка .. cin << не будет работать для получения нескольких слов в строке от пользователей. </p>

0 голосов
/ 01 октября 2018

Я думаю, что проблема в том, что ваш цикл for не взаимодействует по всей входной строке.Попробуйте это:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

 bool is_small_letter(char c){
  return c >= 'a' && c <= 'z';
}

void runLength(string str, vector<char>& charachters, vector<int>& length) {
  int count;
  int i;

  for (i = 0; i < str.size(); i++) {
    if (!is_small_letter(str.at(i))) {
      throw runtime_error("invalid input");
    }

    count = 1;
    if (i == str.size() -1) {
      // do nothing
    } else {
      while (i < str.size() - 1 && str.at(i) == str.at(i + 1)) {
        count++, i++;
      }
    }
    charachters.push_back(str.at(i));
    length.push_back(count);
  }
}

int main() {
  string str;
  vector<char>charachters;
  vector<int>length;

  cout << "Enter the data to be compressed: ";
  cin >> str;
  try {
    runLength(str, charachters, length);

    cout << "The compressed data is: ";
    for (int i = 0; i <= length.size() - 1; i++){
      cout << length.at(i) << charachters.at(i);
    }

  } catch (runtime_error &excpt) {
     cout << endl << "error: " << excpt.what();
  }

  return 0;
}
...