Форум программистов
 
Регистрация на форуме тут, о проблемах пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail, а тут можно восстановить пароль.

Как купить рекламу на форуме


Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail


Ответ
 
Опции темы Поиск в этой теме
Старый 16.08.2009, 15:58   #1
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию Помогите найти ошибку: классы в С++

Задача: Требуется реализовать класс (набор классов) для универсального "счетчика".
Счетчик характеризуется "разрядностью" (количеством "цифр") и типом "цифр".
Примеры типов "цифр": обычная десятичная (0123...9), шестнадцатеричная (012...F), алфавитная (ABCD...Z), пользовательская (ваши варианты настройки для этого типа цифр).
Счетчик должен уметь:
- инициализироваться шаблоном задающим разрядность и тип цифр и текущим значением счетчика
- инкрементироваться, декрементироваться
- выводить текущее состояние в строку
Дополнительно:
тип каждой "цифры" в счетчике может быть своим, а не один и тот же для всего счетчика.

Для этого создаю два класса: Schetchik и UniSchet - массив Schetchik-ов. Проблема в конструкторах и деструкторах...

Код:
  class Schetchik
{ public:
    int a;   // номер цифры в массиве, которая в данный момент выбрана
    int n;  // количество цифр в типе
    char *A; // массив цифр типа
    Schetchik() {};
    Schetchik(int m, char *B, char b);
     ~Schetchik();
 };
Schetchik::Schetchik(int m, char *B, char b)
       { n=m;
         A= new char[n];
         for (int i=0; i<n; i++)
           A[i]=B[i];
         int i=0;
         while ((A[i]!=b)&&(i<n))
           i++;
         a=i;
       };

Schetchik::~Schetchik()
       { delete [] A;
        };
Код:
class UniSchet
{public:
    Schetchik *S;
    int m; //разрядность
    UniSchet(int k, int *n, char **A, char *a);
    ~UniSchet();
};

UniSchet::UniSchet(int k, int *n, char **A, char *a)
   { m=k;
     S=new Schetchik[m];
     for(int i=0; i<m; i++)
         S[i]=Schetchik(n[i], A[i], a[i]);
   };
UniSchet::~UniSchet()
   { delete [] S;
   };
Помогите, пожалуйста, найти ошибки...
Ok-ei вне форума Ответить с цитированием
Старый 16.08.2009, 16:30   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,574
По умолчанию

S=new Schetchik[m];
Создание массива элементов типа Schetchik с вызовом конструктора по умолчанию для каждого объекта, а у вас конструктора такого нет. Вру. Есть, но он пустой.
Для этой строчки:
S[i]=Schetchik(n[i], A[i], a[i]);
не реализован оператор присваивания.

Либо пишите:
Код:
Schetchik **S;
...
S = new Schetchik*[m];
for (int i = 0; i < m; ++i)
  S[i] = new Schetchik(n[i], A[i], a[i]);
Ну и деструктор соответствующим образом исправить нужно будет
pu4koff вне форума Ответить с цитированием
Старый 16.08.2009, 18:45   #3
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию

Спасибо за помощь...
Ok-ei вне форума Ответить с цитированием
Старый 17.08.2009, 10:07   #4
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию

Помогите, пожалуйста, еще...
Для вывода текущего состояния создаю функцию val. Она работает странно: кроме нужного значения выводит еще и пару странных символов...
Например: должна вывести s4a, а выводит s4a|...

В чем ошибка?

Код:
class UniSchet
{private:
    char *B; // для хранения значения счетчика
 public:
    Schetchik **S;
    int m; //разрядность
    UniSchet(int k, int *n, char **A, char *a);
    ~UniSchet();
    char* val(); // возвращает значение счетчика
}

UniSchet::UniSchet(int k, int *n, char **A, char *a)
   { if (k>0)
       {m=k;
        S=new Schetchik*[m];
        for(int i=0; i<m; i++)
           S[i]=new Schetchik(n[i], A[i], a[i]);
        B=new char [m];
       }
     else
        ShowMessage("Слишком маленькая разрядность. Счетчик создать не удалось");
   };

UniSchet::~UniSchet()
   { for (int i=0; i<m; i++)
        delete [] S[i];
     delete [] S;
     delete [] B;
   };

char*  UniSchet::val()
    {for (int i=0; i<m; i++)
         B[m-i-1]=S[i]->val();
     return B;
    };
Ok-ei вне форума Ответить с цитированием
Старый 17.08.2009, 10:50   #5
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,574
По умолчанию

Выделяйте в конструкторе под B m+1 символ и B[m] = '\0';
pu4koff вне форума Ответить с цитированием
Старый 17.08.2009, 11:57   #6
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию

Спасибо, помогло....
Теперь вопрос про переопределение операций...

Код:
class UniSchet
{.......
 public:
    ......
    UniSchet operator++();
  .......
};

UniSchet UniSchet::operator++()
    { int i=0;
      bool f=0;
      while ((i<m)&&(f==0))
         if ((S[i]->a)<(S[i]->n-1))
            {f=1;
             S[i]->a++;
            }
         else
            i++;
      if (f==0)
        ShowMessage("Счетчик заполнен. Значение счетчика увеличить не удалось");
      else
         for (int j=0; j<i; j++)
            S[j]->a=0;
      return *this;
    };
В чем тут ошибки?
Ok-ei вне форума Ответить с цитированием
Старый 17.08.2009, 13:33   #7
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,574
По умолчанию

Цитата:
Сообщение от Ok-ei Посмотреть сообщение
В чем тут ошибки?
Что именно не так? Может по ссылке возвращать
Код:
UniSchet& operator++();
? А то ведь нет соответствующего конструктора копии у UniSchet для работы
Код:
return *this
pu4koff вне форума Ответить с цитированием
Старый 17.08.2009, 13:42   #8
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию

Спасибо, & уже поставила....
Как сделать так, чтобы эта операция работала при таком вызове: S++, а не при S->operator ++()?
Ok-ei вне форума Ответить с цитированием
Старый 17.08.2009, 13:48   #9
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от Ok-ei Посмотреть сообщение
Спасибо, & уже поставила....
Как сделать так, чтобы эта операция работала при таком вызове: S++, а не при S->operator ++()?
Дело в том, что вы перегрузили префиксный ++, то есть использовать можно как ++S. Чтобы перегрузить постфиксный ++, необходимо определить метод operator++ (int);
Код:
class UniSchet
{.......
 public:
    ......
    UniSchet& operator++(int);    // Обратите внимание на тип в скобках, имя переменной не требуется, он необходим для указания, что оператор постфиксный
  .......
};

UniSchet& UniSchet::operator++(int)
    { int i=0;
      bool f=0;
      while ((i<m)&&(f==0))
         if ((S[i]->a)<(S[i]->n-1))
            {f=1;
             S[i]->a++;
            }
         else
            i++;
      if (f==0)
        ShowMessage("Счетчик заполнен. Значение счетчика увеличить не удалось");
      else
         for (int j=0; j<i; j++)
            S[j]->a=0;
      return *this;
    };
Ну и желательно придерживаться семантики: постфиксный ++ возвращает значение, а затем его увеличивает, а префиксный сначала увеличивает значение, а затем возвращает его

Последний раз редактировалось netrino; 17.08.2009 в 13:52.
netrino вне форума Ответить с цитированием
Старый 17.08.2009, 14:07   #10
Ok-ei
Пользователь
 
Регистрация: 29.03.2009
Сообщений: 22
По умолчанию

Спасибо за объяснение...
Только при вызове ++S, программа в UniSchet& UniSchet:: operator++() не заходит... Что не так?

И еще вопрос: а как написать это

Цитата:
постфиксный ++ возвращает значение, а затем его увеличивает
Ok-ei вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме 20000 рублей в месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите найти ошибку! frantic150 Microsoft Office Excel 0 26.06.2009 17:23
Помогите найти ошибку! Студентка@ Помощь студентам 3 21.05.2008 13:21
Помогите найти ошибку KnDmPetr Паскаль, Turbo Pascal, PascalABC.NET 1 11.04.2008 14:48


Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru
Пеллетный котёл Emtas
котлы EMTAS