| Другое > Hard'n'Soft |
| Програмирование на C++ |
| << < (8/25) > >> |
| gepar:
Так, пробую дальше продвигаться по Дейтелу. Дальше у него тут перегрузка операторов, с перегрузкой ввода в поток и вывода из потока, которые были глобальными всё получилось, а вот дальше что-то я не так смотрю указываю когда операторы для перегрузки находятся в классе. Вообще это пример из Дейтела, только у него он как всегда разбит на кучу файлов, я же вот попробовал переделать чтобы всё было в одном и что-то упустил наверное, подскажите пожалуйста что именно. --- Код: ---# include <iostream> # include <iomanip> # include <cstdlib> using namespace std; class Array { friend istream &operator>>(istream &input, Array &a); friend ostream &operator<<(ostream &output, const Array &a); public: Array (int arraySize=10) { size=(arraySize>0 ? arraySize : 10); ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=0; } Array (const Array &arrayToCopy) :size (arrayToCopy.size) { ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=arrayToCopy.ptr[i]; } ~Array() { delete [] ptr; } int getSize() const { return size; } const &Array operator=(const Array &right) { if (&right!=this) { if (size!=right.size) { delete [] ptr; size=right.size; ptr=new int [size]; } for (int i=0;i<size;i++) ptr[i]=right.ptr[i]; } return *this; } bool operator==(const Array &right) const { if (size!=right.size) return false; for (int i=0;i<size;i++) if (ptr[i]!=right.ptr[i]) return false; return true; } bool operator!=(const Array &right) const { return !(*this==right); } int &Array operator [](int subscript) { if (subscript<0 || subscript >=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; } int Array operator[](int subscript) const { if (subscript<0 || subscript>=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; }; private: int size; int *ptr; }; istream &operator>>(istream &input, Array &a) { for (int i=0;i<a.size;i++) input>>a.ptr[i]; return input; }; ostream &operator<<(ostream &output, const Array &a) { int i; for (i=0;i<a.size;i++) { output<<setw(12)<<a.ptr[i]; if ((i+1)%4==0) output<<endl; } if (i%4!=0) output<<endl; return output; }; int main() { Array intgers1(7); Array integers2; return 0; } --- Конец кода --- Сорри комментариев не писал, но они я думаю не надо сейчас. Назначение класса - сделать свой массив с блекджеком и девушками с проверкой не был ли выход за границы массива и с возможностью печати/заполнения/сравнения массива int чисел. Ошибки компилятор выдаёт только в тех строчках где идёт объявление перегрузки операторов const &Array operator=(const Array &right) bool operator==(const Array &right) const int &Array operator [](int subscript) int Array operator[](int subscript) const Я что-то не дописал / написал лишнее в этих строчках? |
| HoRRoR:
Что есть &Array? Array& пиши, чтобы ссылку объявить. int Array - ещё лучше... Чего же тогда не int string double сразу? :D Определись уже с типом. |
| gepar:
HoRRoR,ну Array это и есть этот класс собственно, если убрать Array то компилятор говорит что я пытаюсь заменить оператор для непонятно чего. Инымы словами это const &Array operator=(const Array &right) должно позволить присваивать одному объекту класса Array значения другого объекта класса Array , при этом естественно просто будет сделана копия элементов из одного класса (того что будет справа от = (right) тому что будет слева от = ) в другой. |
| HoRRoR:
Ты вообще читаешь то, что я пишу? Замени &Array на Array&. |
| gepar:
Упростим задачу, вот код с дописанными комментариями :) --- Код: ---# include <iostream> # include <iomanip> # include <cstdlib> using namespace std; class Array { friend istream &operator>>(istream &input, Array &a); // ввод данных в класс Array через cin friend ostream &operator<<(ostream &output, const Array &a);// вывод данных класса Array через cout public: //конструктор выделяет место под нужное колличество элементов массива //по умолчанию на 10 элементов Array (int arraySize=10) { size=(arraySize>0 ? arraySize : 10); ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=0; } //конструктор копии Array (чтобы можно было сделать array1(array2)) Array (const Array &arrayToCopy) :size (arrayToCopy.size) { ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=arrayToCopy.ptr[i]; } //деструктор ~Array() { delete [] ptr; } //возвращает размер массива int getSize() const { return size; } //перегрузка оператора присваивания для класса Array Array operator=(const Array &right) { if (&right!=this) { if (size!=right.size) { delete [] ptr; size=right.size; ptr=new int [size]; } for (int i=0;i<size;i++) ptr[i]=right.ptr[i]; } return *this; } //определения равны ли два массива bool operator==(const Array &right) const { if (size!=right.size) return false; for (int i=0;i<size;i++) if (ptr[i]!=right.ptr[i]) return false; return true; } //определение не равенства двух массивов bool operator!=(const Array &right) const { return !(*this==right); } //возможность обращения к нужному элементу массива //возвращает указатель на этот элемент чтобы обеспечить присваивание //НЕ РАБОТАЕТ Array operator [](int subscript) { if (subscript<0 || subscript >=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; } //возможность обращения к нужному элементу массива для const даных Array operator[](int subscript) const { if (subscript<0 || subscript>=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; }; private: int size; //размер массива int *ptr; //указатель на данные массива }; istream &operator>>(istream &input, Array &a) { for (int i=0;i<a.size;i++) input>>a.ptr[i]; return input; }; ostream &operator<<(ostream &output, const Array &a) { int i; for (i=0;i<a.size;i++) { output<<setw(12)<<a.ptr[i]; if ((i+1)%4==0) output<<endl; } if (i%4!=0) output<<endl; return output; }; int main() { Array integers1(7); Array integers2; cout<<integers1; integers1[4]=100;//не изменяет integers1[4] так как функция получает копию cout<<integers1; return 0; } --- Конец кода --- Код компилируется, но беда в другом - при перегрузке операторов передаются копии. При попытке написать например Array& operator[](int subscript) const я получаю ошибку что у меня там мол дальше возвращается же ссылка на int данные и мол так нельзя. Пишу int &operator[](int subscript) const опять же таки всё компилируется но блин опять же таки нужный объект класса не модифицируется (это видно по выводу данных до и после попытки заменить 4 элемент массива в main). Добавлено позже: А, тьфу, я редактировал функцию что для const данных, тогда там просто int &operator[](int subscript) const и всё будет работать. Короче вот так тогда должно быть: --- Код: ---# include <iostream> # include <iomanip> # include <cstdlib> using namespace std; class Array { friend istream &operator>>(istream &input, Array &a); // ввод данных в класс Array через cin friend ostream &operator<<(ostream &output, const Array &a);// вывод данных класса Array через cout public: //конструктор выделяет место под нужное колличество элементов массива //по умолчанию на 10 элементов Array (int arraySize=10) { size=(arraySize>0 ? arraySize : 10); ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=0; } //конструктор копии Array (чтобы можно было сделать array1(array2)) Array (const Array &arrayToCopy) :size (arrayToCopy.size) { ptr=new int[size]; for (int i=0;i<size;i++) ptr[i]=arrayToCopy.ptr[i]; } //деструктор ~Array() { delete [] ptr; } //возвращает размер массива int getSize() const { return size; } //перегрузка оператора присваивания для класса Array Array &operator=(const Array &right) { if (&right!=this) { if (size!=right.size) { delete [] ptr; size=right.size; ptr=new int [size]; } for (int i=0;i<size;i++) ptr[i]=right.ptr[i]; } return *this; } //определения равны ли два массива bool operator==(const Array &right) const { if (size!=right.size) return false; for (int i=0;i<size;i++) if (ptr[i]!=right.ptr[i]) return false; return true; } //определение не равенства двух массивов bool operator!=(const Array &right) const { return !(*this==right); } //возможность обращения к нужному элементу массива //возвращает указатель на этот элемент чтобы обеспечить присваивание int &operator [](int subscript) { if (subscript<0 || subscript >=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; } //возможность обращения к нужному элементу массива для const даных int operator[](int subscript) const { if (subscript<0 || subscript>=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; }; private: int size; //размер массива int *ptr; //указатель на данные массива }; istream &operator>>(istream &input, Array &a) { for (int i=0;i<a.size;i++) input>>a.ptr[i]; return input; }; ostream &operator<<(ostream &output, const Array &a) { int i; for (i=0;i<a.size;i++) { output<<setw(12)<<a.ptr[i]; if ((i+1)%4==0) output<<endl; } if (i%4!=0) output<<endl; return output; }; int main() { Array integers1(7); Array integers2; cout<<integers1; integers1[4]=100;//не изменяет integers1[4] так как функция получает копию cout<<integers1; return 0; } --- Конец кода --- Сейчас только в main протестирую всё ли работает теперь как положено. Добавлено позже: HoRRoR,читаю, просто этот совет твой не для всех функций помог, ну да я уже "добил" этот класс и теперь вроде перегрузка операторов стала понятнее. Добавлено позже: Небольшой вопрос на тему правильно ли я понял: если у меня идёт перегрузка оператора "внутри" класса и она возвращает что-то (в данном случае ссылку на данные типа int) то я пишу так: int operator[](int subscript) const { if (subscript<0 || subscript>=size) { cerr<<"\nError: Subscript "<<subscript <<" out of range"<<endl; exit (1); } return ptr[subscript]; }; А если ничего не возвращает или возвращает указатель *this то я вместо того чтобы написать void должен писать имя класса, так? |
| HoRRoR:
Ты в любом случае пишешь возвращаемый тип. *this - объект типа данного класса, т.е. да, ты должен писать имя класса в качестве типа возвращаемого объекта. Если ничего не возвращает (правда зачем тебе такой оператор?) - то void, естественно. --- Цитата ---(в данном случае ссылку на данные типа int) --- Конец цитаты --- У тебя тут не ссылка, а просто int. |
| gepar:
HoRRoR, ну как зачем? :) Ну вот набросок маленький опять на ту же самую тему (создание своего массива), фантазии что-то у меня вчера не хватило по поводу темы очередной программы-примера :) Здесь меньше проверок, но дело не в них, посмотри пожалуйста на перегрузку оператора присваивания, там я уже в комментарии расписал что получается если указать void (несмотря на то что класс ничего не возвращает) поэтому я оставил как тип название класса (Test). --- Код: ---# include <iostream> # include <iomanip> using namespace std; class Test { friend ostream &operator<<( ostream &output, Test &a);//перегрузка глобального оператора вывода public: Test(int a=10)//конструктор для нового "массива" { size=a; ptr=new int [size]; for (int i=0;i<size;i++) ptr[i]=0; } //перегрузка оператора = //по сути ведь нужен void так как вызов же будет //что-то типа xyz.operator=(abc) //+ ничего возвращать ведь не надо, но //если написать void то компилятор будет ругаться //на строку 24(где открывается { со сл. ошибкой: // 24|error: cannot declare reference to `void'| Test &operator=(Test b) { for (int i=0;i<size;i++) this->ptr[i]=b.ptr[i]; } int &operator[](int x)// перегрузка [] для обращения к нужному элементу "массива" { return this->ptr[x]; } private: int size;// размер массива int *ptr; // указатель на него (массив) }; ostream &operator<<( ostream &output, Test &a) { for (int i=0;i<a.size;i++) output<<a.ptr[i]<<" "; output<<'\n'; } int main() { Test abc(5);// новый "массив" размером 5 Test xyz(5); cout<<abc;//вывод abc abc[3]=100;//изменяем 3ий элемент на 100 xyz=abc;//присваиваем xyz значения abc cout<<xyz;//проверяем было ли присваивание cout<<abc;//проверяем равен ли 100 3ий элемент return 0; } --- Конец кода --- |
| HoRRoR:
Ну я думал ты это про [] говоришь. А ошибка у тебя потому что нехрен ссылку типа void делать. Вот читаешь ты учебник, а толку, если ляпы у тебя детские? Убери амперсант, тогда сможешь void написать. Вчитывался бы хотя бы в текст ошибок... |
| gepar:
--- Цитата: HoRRoR ---А ошибка у тебя потому что нехрен ссылку типа void делать. --- Конец цитаты --- :) Так я же думал что & относиться к operator=, а не к void. Всегда ведь & относиться к тому что за ним написано, а не перед. |
| HoRRoR:
Скажи мне, какой тогда, на твой взгляд, он нёс функционал? Ты всегда пишешь операторы с неизвестным тебе функционалом? int* - тип, звёздочка относится к инту. int& - то же самое. int *abc - объявление переменной, звёздочка относится к abc. |
| gepar:
HoRRoR,ну я считал что для перегрузки операции нужно чтобы она производилась по значению (те потому и &). Хотя я наверное мрачно объяснил что я хотел написать, ну да ладно, упустим это. --- Цитата: HoRRoR ---int* - тип, звёздочка относится к инту. int& - то же самое. --- Конец цитаты --- Я пока что не знаю что это такое и что так вообще можно :) Ну и вообще раздел по перегрузке операторов Дейтела я ещё не дочитал, то была проба пера. Добавлено позже: Встречный вопрос: а как же задать тип int*, компилятор же всегда думает что это указатель и что * относится к имени переменной следующей после int (например int* abc). |
| Mr2:
--- Цитата: gepar от 13 Февраль 2011, 16:53:38 ---Вопрос номер n+1: А как-то можно ограничить ввод? Только не по количеству символов, а чтобы когда я ожидаю что будет введено число то символы не вводились и наоборот? В многих приложениях я встречал что когда пытаешься ввести в поле для цифр символы то ввод не происходит, правда эти приложения не являлись консольными так что не знаю можно ли сделать что-то подобное здесь. --- Конец цитаты --- --- Код: ---//input check 12.03.2011 #include <iostream> using namespace std; int main(){ int input = 0; for(int i = 0; i < 10;++i){ cout << endl; cout << " Enter number: "; cin >> input; cout << endl; if(cin.fail()){ //если состояние входного потока ошибочное. cin.clear(); //сбросить поток... string garbage; getline(cin, garbage); //... и пропустить всю строку. cout << " This is not a number!!! " <<endl; } else cout << " You enter: " << input <<endl; } system("pause"); } --- Конец кода --- Вот нашёл сегодня. :) |
| gepar:
Mr2,во, круто! Попробую сегодня что-то написать маленькое с использованием этой проверки cin.fail. |
| HoRRoR:
--- Цитата ---Встречный вопрос: а как же задать тип int*, компилятор же всегда думает что это указатель и что * относится к имени переменной следующей после int (например int* abc). --- Конец цитаты --- What? int* или int *a или int *a, *b - чем не ответ на твой вопрос? На крайний случай - typedef или define. --- Цитата ---Вот нашёл сегодня. --- Конец цитаты --- Нажимаю, к примеру, f - вводится f. В чём соль, если речь шла об ограничении ввода, а не о проверке? Т.е. жму f - f не вводится и в консоли не появляется, жму 4 - 4 вводится. |
| gepar:
HoRRoR,ну да это не совсем то чего хотелось изначально, но это хоть что-то. Да в этом случае вводиться всё равно будет всё подряд, но будет хотя-бы проверка что данные соответствуют типу и "не совместимые" данные не будут сохраняться в переменную :) |
| Mr2:
--- Цитата: gepar от 12 Март 2011, 14:46:06 ---HoRRoR,ну да это не совсем то чего хотелось изначально, но это хоть что-то. Да в этом случае вводиться всё равно будет всё подряд, но будет хотя-бы проверка что данные соответствуют типу и "не совместимые" данные не будут сохраняться в переменную :) --- Конец цитаты --- Молодец! :) Правильно! |
| gepar:
Работает слегка непонятно, например я ввожу 121212abc23423 тоесть в input у меня должны быть неправильные данные (они ведь подряд записаны). Но при этом я сначала почему-то получаю выполнение того что по else (программа пишет что я ввёл 121212 (всё что до abc)) и потом тут же выполняется то что в if(cin.fail()) и пишет мол были введены не числа. Почему так? Кстати проверка идёт потока ,а не содержимого int переменной в которую был ввод из потока. Это что значит что поток "помнит" последние вводимые данные или я тут тоже что-то не так понял? Подскажите пожалуйста. Добавлено позже: Нашёл очередной способ вывода русского текста, этот совсем короткий - всего одна строчка: setlocale(LC_ALL, "Russian"); |
| Mr2:
--- Цитата: gepar от 13 Март 2011, 03:02:55 ---Работает слегка непонятно, например я ввожу 121212abc23423 тоесть в input у меня должны быть неправильные данные (они ведь подряд записаны). Но при этом я сначала почему-то получаю выполнение того что по else (программа пишет что я ввёл 121212 (всё что до abc)) и потом тут же выполняется то что в if(cin.fail()) и пишет мол были введены не числа. Почему так? --- Конец цитаты --- В подробности потоков пока не вникал. Видимо поток действительно всё помнит. Не с проста нужно пропускать строку.(getline(cin, garbage); //... и пропустить всю строку.) Но странно что продолжается вывод игнорируя ввод пользователя.(cin >> input; :?) --- Цитата: gepar от 13 Март 2011, 03:02:55 ---Кстати проверка идёт потока ,а не содержимого int переменной в которую был ввод из потока. Это что значит что поток "помнит" последние вводимые данные или я тут тоже что-то не так понял? Подскажите пожалуйста. --- Конец цитаты --- Тут главное что гарантируется что в int будет введено число а не символ. А уж какие значения допустимы решает сам программист. Подправил вывод. :) --- Код: ---//input check 13.03.2011 #include <iostream> using namespace std; int main(){ int input = 0; for(int i = 0; i < 10;++i){ cout << endl; cout << " Enter number: "; cin >> input; cout << endl; if(cin.fail()){ //если состояние входного потока ошибочное. cin.clear(); //сбросить поток... cin.ignore(); //string garbage; //getline(cin, garbage); //... и пропустить всю строку. cout << " This is not a number!!! " <<endl; } else cout << " You enter: " << input <<endl; string garbage; getline(cin, garbage); //... и пропустить всю строку. } system("pause"); } --- Конец кода --- |
| gepar:
Пытаюсь тут сделать свой двухмерный массив с обращением к элементам как в паскале (1,2) вместо [1] [2]. Да только чего-то мой конструктор копии рушит работу всей программы, притом даже если я его не использую, а только он присутствует в коде то тут же отваливается возможность проверки на равенство двух объектов классов o_0 --- Код: ---# include <iostream> # include <iomanip> using namespace std; class Array { public: //конструктор по умолчанию Array(int a, int b) { row=(a>0) ? a:1; column=(b>0)? b:1; ptr= new int [row*column+1]; for (int i=0;i<row*column+1;i++) ptr[i]=0; } //конструктор копии который не работает Array (const Array &abc) { if (*this!=abc); { if (row!=abc.row || column!=abc.column) { delete []ptr; row=abc.row; column=abc.column; ptr=new int[row*column+1]; } for (int i=0;i<row*column+1;i++) ptr[i]=abc.ptr[i]; } } //возможность обращения к нужному элементу массива int &operator()(int a, int b) { if ((a>0) && (a<=row) &&(b>0) && (b<=column)) if (a==1) return ptr[a+b]; else return ptr[(a-1)*column+b]; else exit(100500); } //возможность обращения к нужному элементу массива для const объекта класса int &operator()(int a, int b) const { if ((a>0) && (a<=row) &&(b>0) && (b<=column)) if (a==1) return ptr[a+b]; else return ptr[(a-1)*column+b]; else exit(100500); } //проверка на равенство bool operator==(Array test) { if ((row!=test.row) || (column!=test.column)) return false; for (int j=0;j<row*column+1;j++) if (ptr[j]!=test.ptr[j]) return false; return true; } //проверка на неравенство bool operator !=(Array test) { return !(*this==test); } private: int row; //колличество строк int column; //колличество столбцов int *ptr; //указатель на массив с элементами int }; int main() { Array a(5,5); Array b(5,5); cout<<boolalpha<<(a!=b);//без попытки их сравнить программа //в процессе работы ошибку возвращать не будет return 0; } --- Конец кода --- Добавлено позже: Тааак, в общем-то я напортачил с проверкой вначале не делаем ли мы самоприсваивание, уже понятно, осталось это исправить :) Добавлено позже: да только чего-то не получается, как бы её грамотно устроить? |
| Mr2:
--- Цитата: gepar от 16 Март 2011, 23:41:57 ---Пытаюсь тут сделать свой двухмерный массив с обращением к элементам как в паскале (1,2) вместо [1] [2]. --- Конец цитаты --- Фигнёй ты страдаешь. :) Не вникал в твои усовершенствования матрицы, но так делать незя. :D if (*this!=abc); |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |