Деление на ноль в моем коде

Hes мой код, и я не могу понять, где я получаю проблему деления на ноль.

mreviewApp.cpp

const int SIZE = 80;
const char DELIMIT = '|';

void parseLine(const char line[], string& title, int& rating);
void stringTrim(char st[]);
void printMrList(std::vector <Mreview> mrList);
Mreview searchTitle(std::vector <Mreview> &mrList, string title);


int main()
 {
  ifstream fin;

  fin.open("rating_list.txt");
  if (fin.fail()) {
    cerr << "Input file opening error.\n";
    exit(1);
  }

  char line[SIZE];
  string title;
  int rating;
  int lineCount = 0;

  std::vector <Mreview> mrList;

  /* Process one line at a time */
  // Read the first line
  fin.getline(line, SIZE);
  stringTrim(line);

  // Process loop
  while (strlen(line) != 0) { 
    parseLine(line, title, rating);
    lineCount++;

    Mreview review = searchTitle(mrList, title);
    review.addScore(rating);

    // Read the next line
    fin.getline(line, SIZE);
    stringTrim(line);
  }

  cout << "** PROCESS DONE. There were " << mrList.size() << " movie titles. **\n\n";

  printMrList(mrList);
  // Close the input file before exit.
  fin.close();

  system("Pause");
  return 0;
}

void parseLine(const char line[], string& title, int& rating)
{
  char s[SIZE], r[SIZE];
  const char *ptr, *temp1;
  char *temp2;

  ptr = strchr(line, DELIMIT);

  if (ptr != NULL) {
    // First grab the title string (until '|').
    temp1 = line;
    temp2 = s;
    while (temp1 != ptr)
      *temp2++ = *temp1++;

    *temp2 = '\0';

    stringTrim(s);
    title = s;

    // Second grab the rating number
    temp1 = ptr+1;
    temp2 = r;
    while (*temp1 != '\0')
      *temp2++ = *temp1++;

    *temp2 = '\0';

    stringTrim(r);
    rating = atoi(r);
  }
  else {
    title = "";
    rating = 0;
  }
}

void stringTrim(char st[])
{
  char* ptr;

  for (ptr = st; *ptr; ptr++) ;
  for (ptr--; *ptr == ' ' && ptr >= st; ptr--) ;
  ptr++;
  *ptr = '\0';

  for (ptr = st; *ptr && *ptr == ' '; ptr++) ;

  if (*ptr && ptr != st) {
    char* ptr2;
    for (ptr2 = st; *ptr; *ptr2++ = *ptr++) ;
    *ptr2 = '\0';
  }
}

void printMrList(std::vector <Mreview> mrList)
{
    std::vector<Mreview>::iterator itr;
    for(itr = mrList.begin(); itr != mrList.end(); itr++) {
        Mreview review = *(itr);
        cout << review.getTitle() << "\t\t" << review.getTotalScore() << "\t\t" << review.aveRating() << endl;
    }
}

Mreview searchTitle(std::vector <Mreview> &mrList, string title)
{
    Mreview review (title); 
    std::vector<Mreview>::iterator itr;
    for(itr = mrList.begin(); itr != mrList.end(); itr++) {
        Mreview r2d2 = *(itr);
        if(review.getTitle() == r2d2.getTitle())
            return r2d2;
    }
    mrList.push_back(review);
    return review;
}

mreview.cpp

Mreview::Mreview(string ttl)
  : title(ttl), totalScore(0), numRatings(0) {}

Mreview::Mreview(string ttl, int score)
  : title(ttl), totalScore(score), numRatings(1) {}
void Mreview::addScore(int score)
{
    this->totalScore += score;
    this->numRatings += 1;
}

double Mreview::aveRating() const
{
    double rating = totalScore/numRatings;
    return rating;
}

mreview.h

#ifndef MREVIEW_H
#define MREVIEW_H

#include <string>
using namespace std;

class Mreview
{
public:
  Mreview(string ttl = "N/A");
  Mreview(string ttl, int firstScore);

  string getTitle() const { return title; }
  int getTotalScore() const { return totalScore; }
  int getNumRatings() const { return numRatings; }

  void addScore(int score);
  double aveRating() const;

private:
  string title;
  int totalScore;
  int numRatings;
};

#endif

Моя проблема в том, что я не могу понять, что мне нужно сделать, чтобы решить проблему. Прочитал комментарии и до сих пор в недоумении.


person Community    schedule 27.02.2009    source источник
comment
Возможно, вы захотите исправить синтаксис вашего вопроса.   -  person Devin Jeanpierre    schedule 27.02.2009
comment
спросите Джона Скита или Скотта Хансельмана, у них нет проблем с этим   -  person Oscar Cabrero    schedule 27.02.2009
comment
Привет! Вы используете Dev-C++... угадайте, как я могу сказать?   -  person system PAUSE    schedule 24.03.2009


Ответы (6)


Вы выделяете (и копируете!) вектор из Mreview объектов, все они создаются с помощью ctor по умолчанию, поэтому numRatings по умолчанию равен 0, и вы ничего не делаете, чтобы гарантировать, что aveRating() никогда не будет вызывается для немодифицированных объектов или, по крайней мере, защищает себя от того, что numRatings равен 0.

Изменить: самое простое исправление:

double Mreview::aveRating() const { 
    if (numRatings == 0)
        return 0.;
    else 
        return static_cast<double>(totalScore)/numRatings;
}

Еще одним исправлением, IMO, будет сохранение Mreview указателей (в идеале, shared_ptr) в векторе и newing их когда должен быть добавлен первый счет, а не раньше.

person greyfade    schedule 27.02.2009
comment
Я просто запутался в том, как именно решить эту проблему. - person ; 27.02.2009
comment
Выполните предложение Пола. Это самое простое исправление. Лично я в любом случае не стал бы хранить такой класс в векторе без указателей: я бы сделал ctor по умолчанию явным и добавлял новый экземпляр класса в вектор‹› только тогда, когда у меня есть firstScore для его добавления. - person greyfade; 27.02.2009
comment
Э-э, скорее, Пол предложил тестировать numRatings вместо totalScore. Извини. - person greyfade; 27.02.2009

Не ошибка деления на ноль, а...

double Mreview::aveRating() const
{
    double rating = totalScore/numRatings;
    return rating;
}

Вы берете два целочисленных значения и сохраняете их в двойном без приведения типов... вам нужно привести либо totalScore, либо numRatings к двойному, например:

double Mreview::aveRating() const
{
    double rating = (double)totalScore/numRatings;
    return rating;
}
person DeadHead    schedule 27.02.2009

При поиске задач деления на ноль ищите операторы / и %. Я вижу только один / в вашем коде.

person Paul Beckingham    schedule 27.02.2009

Я вижу только одну реальную операцию по делению...

double Mreview::aveRating() const { 
   double rating = totalScore/numRatings; 
   return rating; 
}

...так это там?

person matt b    schedule 27.02.2009

Можете ли вы запустить его в отладчике и позволить ему сказать вам, где произошла ловушка?

person Matt J    schedule 27.02.2009

Похоже, что если после обрезки длина строки равна 0, то printMrList() можно вызвать без предварительного вызова review.addScore(). В этом случае printMrList() вызывает review.aveRating(), который пытается разделить totalScore на numRatings. Оба эти значения равны 0, поэтому возникает ошибка деления на ноль.

person jeffm    schedule 27.02.2009