Консультации по курсу ООП 2013

Задавайте здесь свои вопросы

Модератор: Преподаватели

Консультации по курсу ООП 2013

Сообщение Telnov » 05 сен 2013, 08:10

Учебные материалы, задания и литературу по курсу «Введение в ООП» смотрите в Облачном кабинете КССТ.

На этом форуме можно задавать вопросы и обмениваться мнениями. По мере сил буду отвечать.

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

97959392
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 21 сен 2013, 13:47

Доброго времени суток, Виктор Петрович.
Пишу по поводу условия моей ЛР про мультикарту.
Насколько я понял, этот контейнер работает с парами ключ+значение. Так вот в условии написано, что ключ должен быть целым, а значение представлено в виде строки. В моем коде все наоборот, т.е. ключ представлен в символьном(char) виде, а значение целочисленное(int).

Иван, "целый ключ" в задании - это была подсказка вам. Это индекс в массиве. Вы не воспользовались подсказкой. Теперь страдания.
В.Тельнов

------------>>>>>>>>>>>>>> Ниже ссылка на условие ЛР<<<<<<<<<<<<<<<<<<<<----------
https://docs.google.com/file/d/0B0jk0QU ... edit?pli=1
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 21 сен 2013, 13:51

Также воспользуюсь случаем показать вам то, что мне на данный момент удалось написать. Понятия извлечение и обход мне пока неизвестны.
Сохранение и восстановление (на диск)/(с диска) относятся к работе с текстовым файлом? Попрошу Вас высказать свои замечания в адрес написанного кода.
Благодарю за внимание.

// 1 Лаба.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

struct kont{
char key[10];
int value;
} *p , *p1 , *p3;


int n1 = 4 , n , pend = -1 ;



void sozdanie(kont* &p ){
if(p) printf("Контейнер уже существует.");
else{
n = n1;
p = new kont[n];
pend = -1;
printf("Контейнер создан.");
}
}

void dobavlenie(kont* &p , int &pend)
{
while(1){
pend++;
system("cls");

//УВЕЛИЧЕНИЕ РАЗМЕРА КОНТЕЙНЕРА
if ( pend == n ){
p1 = new kont[n];
for (int i = 0 ; i < n ; i++)
p1[i] = p[i];
delete []p;
n+=n1;;
p = new kont[n];
for (int i = 0 ; i < pend ; i++)
p[i]=p1[i];
delete []p1;
}


printf("Введите ключ(строку) -> ");
scanf("%s" , &p[pend].key);
int j = 0 , S = 0 ;
while (p[pend].key[j] != '\0'){
S+= p[pend].key[j];
j++;
};
p[pend].value = S ;
printf("\nЗначение=%d\n\n" , S);

int c = 0;

printf("\n1 - добавить еще один элемент.\n2 - Выйти в главное меню.\n -> ");
scanf ("%d" , &c);
if (c == 1 ) continue;
if (c == 2 ) break ;
else while (c != 2 ){
printf("Ошибка ввода! Попробуйте еще раз.\n");
printf("\n1 - добавить еще один элемент.\n2 - Выйти в главное меню.\n -> ");
scanf ("%d" , &c);
system("cls");}
}
}


void udalenie(kont* &p)
{
if(p) {delete []p; p = 0; printf("Контейнер удален.");}
else printf("Нечего удалять");
}

int kol_vo()
{
return(pend+1);
}

int main()
{
setlocale (LC_ALL , "Russian");
system("cls");
int Num ; //Номер операции
printf("\t\tВыберите одну из операций и введите ее номер.\n\n");
printf("1.Создать контейнер.\n");
printf("2.Удалить контейнер.\n");
printf("3.Добавить элементы в контейнер.\n");
printf("4.Извлечь элементы из контейнера.\n");
printf("5.Обход элементов контейнера.\n");
printf("6.Вычислить количество элементов в контейнере.\n");
printf("7.Выполнить объединение контейнеров.\n");
printf("8.Выполнить пересечение контейнеров.\n");
printf("9.Сохранить контейнер в дисковом файле.\n");
printf("10.Восстановить контейнер из файла.\n");
printf("11.Выход.\n\n");
fflush(stdin);
scanf("%d" , &Num); //Ввод номера операции

switch(Num){
case 1 : { sozdanie(p) ; break;}
case 2 : {udalenie(p); break;}
case 3 : {dobavlenie(p , pend); break;}
case 4 : printf("Выберите элемент, который необходимо извлечь"); break;
case 5 : printf("Обход совершен."); break;
case 6 : printf("Количество элементов -> %d" , kol_vo()); break;
case 7 : printf("Объединение контейнеров выполнено."); break;
case 8 : printf("Пересечение контейнеров выполнено"); break;
case 9 : printf("Контейнер сохранен."); break;
case 10 : printf("Контейнер восстановлен."); break;
case 11 : return 0 ;
default : printf("Ошибка ввода данных.");}
printf("\n\n");


char c;
printf("Чтобы выполнить еще одну операцию введите <Y>.\n");
fflush(stdin);
scanf("%c" , &c);
if ( c == 'Y') main();
else return 0;
}
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 21 сен 2013, 14:12

Еще мне думается, что нет смысла в передаче глобальных переменных в функции.
Библиотека <iostream> нужна мне только в процессе разработки для удобного отображения кириллицы без сохранения кода в блокнотах и т.п.
Если функция извлечения будет сносить элементы контейнера по следующей схеме {
1. Ввод строки.
2. Поиск совпадений в имеющемся контейнере.
3. Снос со смещением правой части на 1 шаг влево.
4. Запрос на доп. извлечение либо выход в главное меню.}, это не возбраняется?

Также имеется вопрос по поводу объединения контейнеров.
В моей работе ключи могут повторяться. Поэтому сравнивать придется пары. { Если (key1 == key2)&&(value1 == value2) то ничего не делаем.
Как-то это выглядит неделикатно. Можно для второго контейнера записать независимый от первого алгоритм вычисления значения?
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Также имеется вопрос...

Сообщение Telnov » 22 сен 2013, 11:13

Ответ на ваш вопрос положительный.
Всё изложенное вами можно рассматривать как первый шаг по данной л.р. Продолжайте работу.

Замечание: по условию задачи длина строки не ограничена числом 10, как в вашем коде, а является произвольной.
struct kont { char key[10]; ...

Более подробное обсуждение возможно на занятиях по лабораторному практикуму.

Чтобы узнать, как правильно выкладывать на данном форуме исходный код и другие объекты, посетите раздел: Как правильно делать вложения в посты. Примеры.
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 24 сен 2013, 14:37

Дописал код. Работает стабильно. Все требуемые операции выполняются корректно. В процессе разработки не обошлось без трудностей и многочисленных переработок уже написанных функций. Единственным вопросом остается массив char произвольной длины. Например char* a = new char[] будет создан, но когда выполнение программы дойдет до строчки delete []a; , произойдет вылет, т.к. не задан размер(например char*a = new char[n]). В таком случае непонятно, как высчитать то самое n. И корректно ли пройдет удаление ассоциативного массива в целом. При вводе и считывании из файла можно сначала задать максимальную длину в 256 и после записи вычислить количество символов. Записать в n это значение. И уже его передать в new char[n].
Выглядит очень громоздко. Есть ли другие способы задания произвольной длины для строки? В гугле сплошной мусор.

И второй вопрос важности того же уровня. Требуется ли для моего контейнера механизм сортировки(к примеру по алфавиту, или количеству символов в купе с алфавитным порядком)? Или же эту часть можно опустить?

Приступаю к подготовке отчета.

Код: выделить все
// 1 Лаба.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

struct kont{
   char key[10];
   int value;
} *p ;


int n1 = 4 , pn , pend = -1 ;



//ФУНКЦИЯ ЗАПРОСА НА ПРОДОЛЖЕНИЕ ДОБАВЛЕНИЯ ЭЛЕМЕНТОВ................................................................
int ZAPROS()
{   
   int c ;
   while(1)
   {
      printf("\n1 - добавить еще один элемент.\n2 - Выйти в главное меню.\n -> ");
      fflush(stdin);         
      scanf ("%d" , &c);         
      if (c == 1 )
      {
         system("cls");
         return 0;
      }
      if (c == 2 )
      {
         system("cls");
         return 1;   
      }
      else       
         printf("Ошибка ввода. Попробуйте еще раз.\n");   
   }
}


//СОЗДАНИЕ ПУСТОГО КОНТЕЙНЕРА, С КОТОРЫМ БУДУТ ОСУЩЕСТВЛЯТЬСЯ ВСЕ ОПЕРАЦИИ...........................................
void sozdanie(){
   if(p) printf("Контейнер уже существует.");
   else
   {
      pn = n1;
      p = new kont[pn];
      pend = -1;
   }
}

//УВЕЛИЧЕНИЕ РАЗМЕРА КОНТЕЙНЕРА......................................................................................
void PLUS(kont* &d , int END , int &n)
{

   kont* d1 = new kont[n];
   for (int i = 0 ; i < n ; i++)
      d1[i] = d[i];
   delete []d;
   n+=n1;;
   d = new kont[n];
   for (int i = 0 ; i < END ; i++)
      d[i]=d1[i];
   delete []d1;
}

//ДОБАВЛЕНИЕ ЭЛЕМЕНТОВ В КОНТЕЙНЕР...................................................................................
void DOBAVLENIE(kont* &d , int end , int &n)
{
   printf("Введите ключ(строку) -> ");
   scanf("%s" , &d[end].key);
   int j = 0 , S = 0 ;
   while (d[end].key[j] != '\0')
   {
      S+= d[end].key[j];
      j++;
   }
   d[end].value = S ;
   printf("\nЗначение=%d\n\n" , S);   
 }


//УДАЛЕНИЕ КОНТЕЙНЕРА
void udalenie()
{
   if(p)
   {
      delete []p;
      p = 0;
      printf("Контейнер удален.");
   }
   else printf("Нечего удалять");
}


//ВОЗВРАЩЕНИЕ КОЛИЧЕСТВА ЭЛЕМЕНТОВ
int kol_vo()
{
   return(pend+1);
}



//ФУНКЦИЯ, ИЗВЛЕКАЮЩАЯ ЭЛЕМЕНТЫ ПО ЗНАЧЕНИЮ КЛЮЧА, А ТАКЖЕ ЕГО ДУБЛИКАТЫ
void IZVLECH()
{
   while(1)
   {
      system("cls");
      printf("Введите ключ элемента, который необходимо удалить(вместе с дубликатами).\n\n->");
      char dkey[10];
      scanf("%s" , &dkey);
      kont* p1 = new kont[pend+1];
      int i , j = -1 ;
      for (i = 0 ; i <= pend ; i++)
         if ( strcmp(dkey,p[i].key) != 0 )
         {
            j++;
            p1[j] = p[i];
         }
      if (j == pend) printf("\nТакого ключа нет.\n");
      else
      {
         pend = j ;
         delete []p;
         p = new kont[pend+1];
         for ( i = 0 ; i <= pend ; i++)
            p[i] = p1[i];
      }
         delete []p1;
         printf("\nЧтобы извлечь еще один элемент, введите Y.\nВ противном случае вы вернетесь в главное меню.\n");
         char c ;
         fflush(stdin);
         scanf("%c" , &c);
         if ( 'Y' == c )
            continue ;
         else
            break ;
   }
}


//ОБХОД КОНТЕЙНЕРА И ВЫВОД ЕГО СОДЕРЖИМОГО НА ЭКРАН..........................................................................
void OB_HOD()
{   
   system("cls");
   int i = -1;
   printf(" №|___Key____|___value__|\n");
   printf(" _|__________|__________|\n");
   do
   {
      i++ ;
      printf("%2d|%10s|%10d|\n" , i + 1 , p[i].key , p[i].value);
      printf(" _|__________|__________|\n");
   }
   while(i != pend);
}


//ОБЪЕДИНЕНИЕ ДВУХ КОНТЕЙНЕРОВ................................................................................................
void OB_EDINENIE()
{
      int p1n = n1 , p1end = -1 ;
      kont* p1 = new kont[n1];
      while(1)
      {
         p1end++;
         if( p1end == p1n)
            PLUS(p1 , p1end , p1n);
         DOBAVLENIE(p1 , p1end , p1n);
         if(ZAPROS())
            break;
      }
   int l;
   for(int i = 0; i <= p1end ; i++)
   {
      l = 1 ;
      for(int j = 0 ; j <= pend ; j++)
         if (strcmp(p1[i].key , p[j].key) == 0)
            l = 0;      
      if(l)
      {
         pend++;
         if ( pend == pn )
            PLUS(p , pend , pn);
         p[pend]=p1[i];
      }
   }
   delete []p1;
}

//ПЕРЕСЕЧЕНИЕ ДВУХ КОНТЕЙНЕРОВ................................................................................................
void PERESECH()
{
   int p1n = n1 , p1end = -1 ;
      kont* p1 = new kont[n1];
      while(1)
      {
         p1end++;
         if( p1end == p1n)
            PLUS(p1 , p1end , p1n);
         DOBAVLENIE(p1 , p1end , p1n);
         if(ZAPROS())
            break;
      }
      int dn = n1 , dend = -1 ;
      kont* d = new kont[n1];
      int l;
      for (int i = 0 ; i <= p1end ; i++)
      {
         l = 0;
         for (int j = 0 ; j <= pend ; j++)
            if (strcmp(p1[i].key , p[j].key) == 0 )
               l = 1;
         if (l)
         {
            dend++;
            if( dend == dn)
               PLUS(d , dend , dn);
            d[dend] = p1[i];
         }
      }
      delete []p1;
      delete []p ;
      p = new kont[n1];
      pn = n1;
      for (pend = 0 ; pend <= dend ; pend++)
      {
         if (pend == pn)
            PLUS(p , pend , pn);
         p[pend] = d[pend];
      }
      pend--;
      delete []d;
}

//СОХРАНЕНИЕ КОНТЕЙНЕРА В ТЕКСТОВЫЙ ФАЙЛ...............................................................................
void SAVE()
{
   char* file = "D:\\multimap.txt" ;
   FILE* f = fopen(file , "w");
   for (int i = 0 ; i <= pend ; i++)
   {
      if (i == pend)   
      {
         fprintf( f , "%5s%10d" , p[i].key , p[i].value);
         break;
      }
      fprintf( f , "%5s%10d\n" , p[i].key , p[i].value);
   }
   fclose(f);
}

//ВОССТАНОВЛЕНИЕ КОНТЕЙНЕРА ИЗ ТЕКСТОВОГО ФАЙЛА.......................................................................
void LOAD()
{
   sozdanie();
   char* file = "D:\\multimap.txt" ;
   FILE* f = fopen(file , "r");
   while(!feof(f))
   {
      pend++;
      if (pend == pn)
         PLUS(p , pend , pn);
      fscanf (f , "%s%d" , &p[pend].key , &p[pend].value);
   }
   fclose(f);
}



int main()
{
setlocale (LC_ALL , "Russian");
system("cls");
int Num ; //Номер операции
printf("\t\tВыберите одну из операций и введите ее номер.\n\n");
printf("1.Создать контейнер.\n");
printf("2.Удалить контейнер.\n");
printf("3.Добавить элементы в контейнер.\n");
printf("4.Извлечь элементы из контейнера.\n");
printf("5.Обход элементов контейнера.\n");
printf("6.Вычислить количество элементов в контейнере.\n");
printf("7.Выполнить объединение контейнеров.\n");
printf("8.Выполнить пересечение контейнеров.\n");
printf("9.Сохранить контейнер в дисковом файле.\n");
printf("10.Восстановить контейнер из файла.\n");
printf("11.Выход.\n\n");
fflush(stdin);
scanf("%d" , &Num); //Ввод номера операции

switch(Num){
case 1 :
   sozdanie();   
   printf("Контейнер создан.");
   break;

case 2 :
   udalenie();
   break;

case 3 :
   if (p)   
   {   
      while(1)   
      {   
         pend++;
         system("cls");         
         if (pend == pn)      
            PLUS(p , pend , pn);      
         DOBAVLENIE(p , pend , pn);   
         if (ZAPROS()) break ;
      }   
   }   
   else       
      printf("Некуда добавлять!");
   break;

case 4 :
   if((pend >= 0) && p)    
      IZVLECH();   
   else       
      printf("Неоткуда извлекать!");break;

case 5 :
   printf("Обход совершен.\n\n");    
   OB_HOD();
   break;

case 6 :
   printf("Количество элементов -> %d" , kol_vo());   
   break;

case 7 :
   {
      system("cls");
      printf("Введите ключи для нового контейнера.\n\n");
      while(!getchar());
      OB_EDINENIE();
      printf("\nОбъединение контейнеров выполнено.");
      break;
   }

case 8 :
   system("cls");
   PERESECH() ;
   printf("Пересечение контейнеров выполнено");
   break;

case 9 :
   SAVE();
   printf("Контейнер сохранен.");
   break;

case 10 :
   if(p)
      {
         printf("Сначала удалите имеющийся контейнер.");
         break;
   }
   LOAD();
   printf("Контейнер восстановлен.");
   break;

case 11 :
   return 0 ;

default :
   printf("Ошибка ввода данных.");

}

printf("\n\n");

char c;
printf("Чтобы выполнить еще одну операцию введите <Y>.\n");
fflush(stdin);
scanf("%c" , &c);
if ( c == 'Y') main();
else return 0;
}
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: другие способы задания произвольной длины для строки

Сообщение Telnov » 24 сен 2013, 17:26

Есть ли другие способы задания произвольной длины для строки? - это тема ближайшей лекции.
Сортировка строк в лексикографическом порядке ("по алфавиту") легко выполняется с помощью стандартной библиотечной функции strcmp.
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 02 окт 2013, 17:36

И снова доброго времени суток. Меня интересуют различные сложные рекурсивные и прочие алгоритмы. К примеру, из упорядоченного массива построить сортирующее дерево. Ну и что-нибудь такое заковыристое. Не могли бы вы подсказать литературу, ориентированную именно на алгоритмическую составляющую программирования (язык не так важен, как сами принципы работы с различными данными)? Времени на поиски практически нет, готовлюсь к очередному экзамену. Спасибо за внимание.

    Эдсгер Вибе Дейкстра. Смиренный гений программирования. Внимательно читайте литературу к этой статье.
    Дональд Кнут. Искусство программирования, том 1. Основные алгоритмы. Также читайте тома 2-3.
    Норберт Вирт. Алгоритмы и структуры данных. Любое издание, но читайте полностью.
Попробуйте это: Материалы семинарских занятий (в Облачном кабинете) - Задачи по Си - Набор задач №3 - Простая грамматика. Лексический анализатор.

В.Тельнов
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Перенос занятий

Сообщение admin » 03 окт 2013, 15:42

Господа студенты, занятия с пятницы 04.10.2013г. переносятся на следующую неделю, по причине моей болезни.
Точную дату согласуем позже.

Зав. лаб. Рыков Евгений Александрович сегодня откроет для вас ауд. 2-510 и сделает сообщение.

Найдите окно в своём плотном расписании и предложите время для отработки данных занятий.

В.Тельнов
Администратор
Аватар пользователя
admin
Администратор
 
Сообщений: 13
Зарегистрирован: 18 июл 2011, 18:39
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 20 окт 2013, 14:04

Спасибо за ответ на предыдущий вопрос. Столкнулся с проблемой во время выполнения второй лабораторной.
Элементы в контейнер добавляются, функция size() успешно возвращает количество элементов. Но на извлечении и выводе столкнулся с грандиозным крахом всей своей работы. Прошу помощи в сложившейся ситуации. Представляю по кускам код.

Код: выделить все
class Polymorph {                       //Абстрактный класс
public:
virtual Polymorph& get() = 0 ;      //Виртуальная функция
};


class Int:public Polymorph {         //Класс целых чисел, потомок Polymorph
private:
   int X ;
public:
   Int(int &x ) {X=x;}
   Int& get(){return *this;}
};

class Str:public Polymorph {         //Класс строк, потомок Polymorph
   char* S;
public:
   Str(const char* &s) { S = new char[strlen(s)+1] ; strcpy(S , s);}
   Str& get(){return *this;}
};

class Struct:public Polymorph {         //Класс структур целых чисел, потомок Polymorph
   struct Node{
      int X ;
      int Y;
   };
   Node p;
public:
   Struct( int &x , int &y ) {p.X = x ; p.Y = y; }
   Struct& get(){return *this;}
};



Контейнер multimap<Polymorph* , int> . Задефайним в "Т".
Создаю через указатель, т.е. Т* с = new T.
Элементы, введенные в форму добавляю с помощью преобразований из System::String^ к более адекватным типам так:

1)int x = System::Convert::ToInt32(textBox1 -> Text);

2)const char* s = (const char*)(Marshal::StringToHGlobalAnsi(textBox2 -> Text)).ToPointer();

Получив нужный формат выделяется память под объект типа Polymorph(рассмотрим пример для целых числел):

Int *X = new Int(x);

И это ключ. Значение считается отдельно, это сейчас не важно.

Закладывем в контейнер пару: с -> insert( pair <Polymorph* , int> ( X , z) ) ;

Вроде бы все хорошо, но когда доходит до извлечения или хотя бы вывода целого числа получаем козу.
Вводим число, которое необходимо извлечь. Приводим к типу указателя на Polymorph. И все, приплыли.
Насколько я понял, то идет сравнение указателей, а не того, на что он указывает. Указывает он на Polymorph. Как реализовать человеческое сравнение и поиск? Стандартные операции над контейнером для указателей работать уже не будут? Выходит, что контейнер задан некорректно? И нельзя было использовать указатели на Polymorph? При выводе в окошке всплывает не число, а "true". Не знаю, как забраться дальше указателей.


Вот пример для извлечения элементов с "целыми" ключами. Естественно, что не работает.

Код: выделить все
int x = System::Convert::ToInt32(textBox1 -> Text);
                   Int *X = new Int(x);
                   T::iterator itl , itr , i ;
                   itr = c -> upper_bound(X);
                   itl = c -> lower_bound(X);
                   i = itl;
                   do
                   {
                      c -> erase(i);
                      i++;
                   }while(i != itr);
                                                textBox2 -> Text = System::Convert::ToString(x); //Эта строчка просто для проверки того, что же на самом деле там
//происходит.


Помогите разобраться. Очень много времени уходит на поиски нужной информации.

P.S. забыл добавить, что при вызове функции erase("итератор") программа летит. В скобки можно еще и сам ключ запихнуть, но это ничего не меняет. Подозреваю, что в основе всех проблем лежат указатели, которые никаким образом не способны совпасть, т.к. "смотрят" на разные участки памяти.
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 20 окт 2013, 16:37

Нашел способ вытаскивать наружу данные из полиморфного объекта, но не знаю, как обощить этот способ для всех потомков абстрактного класса.

Если Int *X = new Int(x), то Int A = *X; значит можно в классе целых объектов написать ф-ию int set(){return X;} и вытащить целое значение вот так:
int x = (A.set()); или просто int x = ((*X).set());

Но для полноценного перебора данных такой метод не годится.

Int A = *X;
Банальное сравнение if( A == *( (*i).first) ) объектов не проходит (first на ключ показывает...i - итератор).
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: проблемы с полиморфным контейнером

Сообщение Telnov » 21 окт 2013, 15:40

Из написанного видно, что с данной темой вы пока не разобрались. Предлагаю вам следующий пошаговый алгоритм работы:
  1. Создаете чистый проект и помещаете в него этот пример из лекции, ничего не меняя. Добиваетесь того, чтобы данный пример у вас работал.
  2. Внимательно читаете две последние лекции по ООП и главы из рекомендованной литературы (Страуструп). Добиваетесь полного понимания того, как работает данный пример.
  3. Опираясь на рабочий пример, аккуратно понемногу добавляете в него свой собственный код, избегая ошибок и добиваясь решения требуемой задачи.
Данный прием называется "от простого - к сложному". Рекомендуется всем студентам.
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 21 окт 2013, 17:32

С этого и начинал. В консоли все просто. Ничего не стоит вызвать не возвращающую значений функцию для вывода данных через cout.
А в лабораторной надо бы извлечь реальные данные.

Появилась идея. Возможно безумная. Подсчитывать размер(байты) скрытого поля объекта. Этого мне компилятор не запретит. Оттуда уже отталкиваться.
Придется 3 дополнительных виртуальных функции писать. И в каждом подклассе 2 из них будут бездействовать. А одна из трех выдавать то, что надо.
Надеюсь на ваше скорейшее появление здесь.
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 21 окт 2013, 17:45

Все гораздо проще. Вычислять размер необязательно) Достаточно виртуальной функции, возвращающей номер объекта. Неужели все так просто?)
Даже смешно немного)

P.S. Заработало.

Функцию сортировки уж как-нибудь напишу.

Вопрос по поводу вывода на экран. Вас устроит без выравнивания? А то у меня появляется чувство, что пишу социальную сеть, где юзерам дана возможность поставить лайк или дизлайк моей работе)
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Вопрос от пользователя Roman

Сообщение Telnov » 25 окт 2013, 00:40

Здравствуйте, Виктор Петрович.
Нужна ваша помощь в решение проблемы связанной с gets. При достижение строки где мне надо вводить в мой buffer строку, gets не срабатывает и записывает пустое значение.

Да, действительно, gets не оформляет конец строки надлежащим образом. Подробнее об этом читайте здесь.
Предлагаю вместо gets использовать fgets, как показано в примере ниже:

Код: выделить все
#include "stdafx.h"
#include <system_error>
#define SIZE_BUFFER 256

static char buf[SIZE_BUFFER];

int main() {
   do {
      puts("Enter number:");
      gets(buf);
      switch ( *buf ) {
         case '1' : puts("Enter string:"); fgets(buf, sizeof(buf), stdin); puts(buf);  break;
         case '2' : break; 
      }
   } while (*buf != 'q');
   system("pause");
}

Данное сообщение перенесено в тему "Консультации по курсу ООП 2013".
Вложения
lab_1_hesh_table.cpp [5.5 KiB]
Скачиваний: 120
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Домашние тренинговые задания 1

Сообщение Telnov » 29 окт 2013, 14:01

Домашние тренинговые задания 1: сегодня добавлены задания с номерами 55, 56, 57.
Чтобы увидеть их, зайдя в Облачный кабинет, очистите кеш браузера и обновите страницу.
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Обновлены задачи для семинаров

Сообщение Telnov » 12 ноя 2013, 17:47

В Облачном кабинете обновлены задачи для семинарских занятий.
По просьбе учащихся, добавлены задачи с макросами.
В.Тельнов
Аватар пользователя
Telnov
Преподаватель
 
Сообщений: 236
Изображения: 5
Зарегистрирован: 05 сен 2011, 00:19
Благодарил (а): 1 раз.
Поблагодарили: 6 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 28 ноя 2013, 18:07

Виктор Петрович, беда. Что уж тут сказать. Привожу код. Программа зацикливается и конец.
Или консоль не дружит с русскими символами(под Юникодом только стали читаться), или у я что-то не так делаю.
Порядок пробега вроде правильный.

Код: выделить все
#include "stdafx.h"
#include "stdlib.h"

int _tmain(int argc, _TCHAR* argv[])
{
   unsigned char ch ;
   printf("VVEDITE SIMVOL\n->");
   scanf( "%c" , &ch);
   unsigned char c;
   for ( c = 'а' ; c <= 'я' ; c++)
   {
   if ( c == ch) printf("rus\n\n");
   }
   system("pause");
   return 0;
}

Чтобы не гадать, выполните цикл по шагам, посмотрите значения кодов символов.
Должно быть простое объяснение происходящему.
В.Тельнов
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 28 ноя 2013, 21:59

Виктор Петрович, вы не могли бы привести самый простой пример, когда макрос что-то возвращает? Не совсем понятно. Как развалить стандартный тип на байты еще понятно. Объединения в помощь. А вот как вернуть что-то, не являющееся аргументом макроса, тут задача усложняется.

Сам макрос по определению ничего не возвращает. Но тело макроса может содержать произвольный текст. Например, код на Си. Например, такой: return 0;

По поводу предыдущего вопроса. Проблема в кодировке. Символы разбросаны не по порядку. Да так, между указанными мной еще и английские, и арифметические встречаются.
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 28 ноя 2013, 23:31

Т.е. предполагается, что такой макрос будет вызван в теле функции. Спасибо за исчерпывающий ответ. Сам бы долго возился.

Очень понравилась последняя задача из варианта №7. Там макросы пришлось задействовать для создания массива указателей на файлы.
Параметров произвольное количество.
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 30 ноя 2013, 22:28

Доброго времени суток, Виктор Петрович.
У меня вопрос по задаче из второго домашнего задания.

Для начала покажу условие.

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

А теперь, собственно, вопрос. Писать нужно с нуля без использования класса string?
Можно ли вложить в разрабатываемый класс String уже существующий string и определить только функцию выделения подстроки?

Во всех заданиях требуется самостоятельно решать задачи, не прибегая к готовым решениям (классам) и не ссылаясь на них.
В.Тельнов


В противном случае будет ли достаточно следующих пунктов в реализации: (?)
1. Создание объекта ;
2. Выделение подстроки.


Также еще один вопрос есть. В условиях некоторых заданий сказано с помощью, например, операции ++d=10 b d++=10 реализовать разные, но похожие по логике функции. Можно перегрузить "++" для постфикса и префикса, но операцию "=" перегрузить можно лишь один раз, я правильно понимаю?

В целом, понимаете правильно. Конкретную операцию для объектов конкретного класса перегрузить можно лишь один раз.
Однако "=" есть бинарная операция, и для второго операнда возможны варианты. Поэтому функция operator= тоже может быть перегружена.
Соответствующий пример смотрите в лекции по ООП "Перегруженные операции".
В.Тельнов
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 02 дек 2013, 14:21

И снова пишу по поводу домашнего задания. Пришла мысль в голову. При сдаче задания третью задачу представлю в 2х экземплярах:
1) С перегрузкой того самого "=", но с дополнительным полем-переключателем в классе. operator++ возвращает ссылку на объект.
2) Без перегрузки "=" и без переключателя. operator++ возвращает ссылку на выделенную в деке память под double, в результате чего происходит прямое присваивание.


Единственное, что я считаю нужным подчеркнуть, как разработчик - это правильное использование перегруженных функций. Т.е. для работы с классом необходимо использовать только указанные в условии операции. И ни в коем случае не пытаться писать что-то вроде d++; ++d; вот так просто отдельно.
Это не вызовет системной ошибки, но приведет к своеобразному(неправильному) заполнению дека. Когда человек забивает гвозди, он не прогоняет их сквозь свою руку. Не забивает туда свои пальцы и не использует вместо гвоздей иголки.

Вы согласны с такой логикой?

Только что перепрочел условие. Дек надо было реализовать, как одномерный массив. А я использовал контейнер из stl, даже механизм исключений задействовал. Переделывать теперь все)

Не огорчайтесь. Хорошо сделав работу, вы получаете, кроме высокого балла, ещё профессиональное удовлетворение и уверенность в себе.
В.Тельнов
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Иван » 02 дек 2013, 20:05

Виктор Петрович, у меня такой вот вопрос. Будет ли создан объект класса, если в конструктор были заданы неверные параметры и выброшено исключение?

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

Как это вижу я:

1) Создание объекта класса (конструктор по умолчанию и конструктор преобразования).
2) Допустим организую возможность присваивания строк друг другу.
3) Вывод в поток.

Еще нужно что-нибудь? Хотелось бы конкретизировать. А то нашел в интернете класс String самодельный. Полно лишних наворотов там, как мне кажется.

Если интересно, то вот он http://www.kselax.ru/2013/03/klass-string/ .
Я свой писать все же буду. Не доставляет что-то слизывать, тем более, когда все можно сделать гораздо проще и понятнее, как и завещал нам Страуструп.

Все подробные обсуждения и консультации давайте отложим до среды.
P.S. Бьерн Страуструп жив и здоров поныне.
Аватар пользователя
Иван
Студент
 
Сообщений: 49
Зарегистрирован: 06 сен 2013, 08:41
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Dmitriy » 10 дек 2013, 22:15

Здравствуйте,Виктор Петрович, у меня возникли некоторые вопросы по 2 идз:
Задача 4. Опишите абстрактный класс для работы с объектом типа «star» – звезда, с функциями создания звезды, изменения её размеров, перемещения по экрану, а также изменения длины лучей. Первоначальное количество и длина лучей задаются конструктором звезды.
Вопросы:1. Что имеется ввиду под перемещением по экрану,изменения координаты центра? Реализация необходима? Если да, то с помощью какой графической библиотеки?

Задача 23. Определите класс String таким образом, чтобы операцию выделения подстроки можно было применять к левой части присваивания. Вначале напишите вариант, в котором строку можно присваивать подстроке той же длины, а затем вариант с различными длинами строк.
Вопросы:"...операцию выделения подстроки можно было применять к левой части присваивания..." - что это означает? Нужен метод, реализующий выделение подстроки или что-то иное?

Задача 42. Определить класс битовой строки, состоящей из 64 бит. Конструктор строит битовую строку либо по числу с плавающей точкой, имеющему данное битовое представление, либо по длинному целому числу, либо по символьной строке, состоящей из нулей и единиц.
Вопросы:Реализовать собственный вариант хранения числа с плавающей точкой или один из общепринятых? Необходимо ли предусмотреть ситуацию, где число(строка) будет больше знаков, чем могут вместить в себя 8 байт?

Ответ на вопрос по задаче 4. Под перемещением имеется ввиду перемещение звезды по экрану целиком. То есть, звезда была в одном месте экрана, и вот целиком переместилась в другое место экрана. С какими конкретно координатами работать - это ваше решение. Реализация функций отрисовки звезды на экране (работа с библиотекой GUI) в задании не требуется.

Ответ на вопрос по задаче 23. Это значит, что нужно определить операцию присваивания для строк (см. Лекцию по перегруженным операциям). Но реализовать её так, чтобы правая строка присваивалась не всей левой строке, а только её заданной подстроке.

Ответ на вопрос по задаче 42. Вариант хранения задан в условии задачи - битовая строка. Т.е. строка, в которой записаны символы битов (справка: в языке Си строка - это массив символов). Необходимо предусмотреть все ситуации.

В.Тельнов
Аватар пользователя
Dmitriy
Студент
 
Сообщений: 2
Зарегистрирован: 06 сен 2013, 08:26
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Консультации по курсу ООП 2013

Сообщение Dmitriy » 12 дек 2013, 23:48

Здравствуйте, возникли еще пару вопросов по 2-му идз^
Задача 23. Определите класс String таким образом, чтобы операцию выделения подстроки можно было применять к левой части присваивания. Вначале напишите вариант, в котором строку можно присваивать подстроке той же длины, а затем вариант с различными длинами строк.
Вопрос:в каком стиле хранить строки ? допускается ли использование явного приведения char к string и обратно через метод c_str()?

Строки в языках Си и C++ - это массивы символов, оканчивающиеся специальным символом "конец строки". О каких "стилях" идет речь - не ясно.
Метод c_str() использовать можно (непонятно, зачем?), если вы его сами разработали.

В.Тельнов
Аватар пользователя
Dmitriy
Студент
 
Сообщений: 2
Зарегистрирован: 06 сен 2013, 08:26
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

След.

Вернуться в Консультации онлайн

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1