Другое > Hard'n'Soft
Програмирование на C++
gepar:
Mr2,так а где ты нашёл return ( left * right)? Код всей функции приведи.
Mr2:
--- Цитата: gepar от 09 Мая 2011, 02:47:55 ---Mr2,так а где ты нашёл return ( left * right)? Код всей функции приведи.
--- Конец цитаты ---
Не, я поменял местами right и left, и код компилируется.
--- Код: ---Matrix operator*(const double left, const Matrix &right)
{
return (left* right);
}
--- Конец кода ---
но кто их перемножает если не friend Matrix &operator*(Matrix&, const double);? А она по идеи может перемножать только return ( right *left); И то надо уточнить реально ли это....
По идеи ты должен написать код перемножения(числа на данные класса), а не просто умножить объект на какое то число.
Вообщем я запутался. :'(
Надо самому что нибудь сворганить и разобраться что и как.Потому как надо тестировать все функции а не просто в компиляторе эксперементировать. :(
gepar:
Mr2,ну тогда ты меня окончательно запутал при этом мне теперь непонятно почему оно вообще скомпириловалось.
Вот смотри это у меня функция для умножения матрицы на число
--- Код: ---Matrix& operator*(Matrix &left,const double right)
{
//результат
Matrix& temp(left);
for (int i=0;i<left.row;i++)
for (int j=0;j<left.column;j++)
temp.matrix[i][j]*=right;
return temp;
}
--- Конец кода ---
А это матрици на число, логично что я не хотел бы писать всё заново и просто в реализации оператора поменять местами операнды и пусть используется прошлая перегрузка. Да вот только когда ты поменял местами left и right то мне теперь совсем непонятно где же оно нашло перегрузку числа на матрицу (ведь эта перегрузка и написана для этого случая!).
--- Код: ---Matrix operator*(const double left, const Matrix &right)
{
return (left* right);
}
--- Конец кода ---
Добавлено позже:
В общем вероятно код с такими исправлениями работать не будет либо работать будет не правильно, сейчас проверим.
Добавлено позже:
Нашёл ошибку в классе строка, хорошо бы было если бы оно и ругалось на него если в нём ошибка то была <_<
Добавлено позже:
Такс, после исправления в Row теперь хоть как-то компилируется ну и печатает саму матрицу (знать матрица создаётся по умолчанию/ с параметрами нормально и печатается тоже), умножение конечно же не работает (ещё бы ему работать, я пока не понял как компилятор вообще умудрился принять практически рекурсивный код при перегрузке умножения на число).
Mr2:
То есть ты хочешь в одном операторе использовать другой?(в операторе Matrix operator*(const double left, const Matrix &right) вызывается оператор Matrix& operator*(Matrix &left,const double right)?)
Честно сказать не в курсе можно ли проделывать такой фокус с операторами.
Как я понял оператор :
--- Код: ---Matrix operator*(const double left, const Matrix &right)
{
return (left* right);
}
--- Конец кода ---
вызывает сам себя. Но как он умножает я не понял. Может быть просто возвращяет Matrix &right без изменений.Это нужно программу тестировать.
Я перегружал:
--- Код: ---Matrix operator*( const Matrix &right,const float left,)
{
return ( right*left);
}
--- Конец кода ---
И return ( right*left);как у тебя было изначально компилировалась.
gepar:
--- Цитата: Mr2 ---Честно сказать не в курсе можно ли проделывать такой фокус с операторами.
--- Конец цитаты ---
А почему бы и нет? Это ведь логично и выглядит коротко, только где-то опять ошибка закралась, а компилятор уже как следствие её здесь видит.
Mr2:
--- Цитата: gepar от 09 Мая 2011, 15:05:55 ---А почему бы и нет?
--- Конец цитаты ---
А ты видел где либо чтоб оператор вызывал свою версию перегруженного оператора?(int*doubl вызывает double*int)
--- Цитата: gepar от 09 Мая 2011, 15:05:55 ---только где-то опять ошибка закралась, а компилятор уже как следствие её здесь видит.
--- Конец цитаты ---
--- Цитата: gepar от 09 Мая 2011, 15:05:55 ---Это ведь логично и выглядит коротко,
--- Конец цитаты ---
Видимо ты так укоротил что твоя логика неподсильна компилятору. :lol:
gepar:
Mr2,ну так это же не логично писать сначала перегрузку для Класс умножить на double, а потом ещё и отдельно полностью double умножить на Класс. Действие то тоже самое нужно провести только в первом случае класс слева , а во втором класс справа будет от double.
Добавлено позже:
Нашёл ещё ошибку в перегрузке умножения (логическую конечно), откуда их столько на закрадывалось то.
Mr2:
--- Цитата: gepar от 09 Мая 2011, 15:26:13 ---Mr2,ну так это же не логично писать сначала перегрузку для Класс умножить на double, а потом ещё и отдельно полностью double умножить на Класс.
--- Конец цитаты ---
Логика тут не причём. Как я понял для каждого оператора нужна своя реализация.Есть даже перегрузка для i++ и ++i и у каждой своя реализация.
Ты гдето видел такую перегрузку как у тебя?или это твои личные выдумки? ;)
--- Цитата: gepar от 09 Мая 2011, 15:26:13 ---Нашёл ещё ошибку в перегрузке умножения (логическую конечно), откуда их столько на закрадывалось то.
--- Конец цитаты ---
Я в коде менял местами:
--- Код: ---return right.inverted()* (*this);
*this= (right.inverted()* (*this));
--- Конец кода ---
HoRRoR:
Mr2, ну и я так делаю, и что? Это тоже мои личные выдумки?
gepar:
Mr2,нет, я там по строке не той матрицы пошёл под конец. То что ты менял я потом откатил если можно так назвать, тоесть я вернулся к своим старым исходниками.
Добавлено позже:
Тем не меннее я не понимаю почему я получаю ошибку здесь
--- Код: ---Matrix operator*(Matrix &left,const double right)
{
//результат
Matrix temp(left);
for (int i=0;i<left.row;i++)
for (int j=0;j<left.column;j++)
temp.matrix[i][j]*=right;
return temp;
}
Matrix operator*(const double left, const Matrix &right)
{
return (right*left); //ОШИБКА Matrix.cpp|164|error: no match for 'operator*' in 'right * left'|
}
--- Конец кода ---
HoRRoR,может ты ещё взгляни да скажи где я туплю, ну не понимаю я почему оно не видит перегрузку выше и всё тут.
Добавлено позже:
Блин, смешно же, как только написал HoRRoR'у только что так и заметил что у меня const во второй же перегрузке, а в первой нет
Matrix operator*(Matrix &left,const double right)
Matrix operator*(const double left, const Matrix &right)
Mr2:
--- Цитата: HoRRoR от 09 Мая 2011, 15:40:28 ---Mr2, ну и я так делаю, и что? Это тоже мои личные выдумки?
--- Конец цитаты ---
Не, я просто не в курсе о том можно ли так делать или нет. ;)
--- Цитата: gepar ---Блин, смешно же, как только написал HoRRoR'у только что так и заметил что у меня const во второй же перегрузке, а в первой нет
--- Конец цитаты ---
Даже и не думал что константа влияет на перегрузку. :blush:
gepar:
Задолбался я с этими const, там не хватает, там много, сделал всё что можно const и теперь всё множиться и складывается где нужно (дописывал только const, реализации не трогал), теперь осталось найти ошибку в детерминанте и написать функцию для вычисления ранга.
Добавлено позже:
Кстати вначале задание казалось легче :D
gepar:
В общем курсовую до чт. оформил, допилил и сдал. Получил в итоге 95 за курсовую (наверное преподша не хочет при сдаче ведомости писать max балл), хотя преподша сказала что мол всё идеально хорошо, и 100 за сам курс ООП. Курсовая в итоге получилась самая большая в группе так как с кодом она вышла в 62 страницы :) Теперь можно продолжить в свободное время допроходить Дейтела, я там остановился в последний раз на манипуляторах потока...
Добавлено позже:
Таааак, у меня чувство дежавю, но спрошу:
--- Код: ---# include <iostream>
using namespace std;
int main()
{
int ch;
int a=3;
cout<<"Before: "<<cin.eof()<<endl
<<"Enter sometging: "<<endl;
while((ch=cin.get())!=EOF)
cout.put(ch);
cout<<"\nEOF is: "<<ch<<endl;
cin>>a;
cout<<"\nFuck, A has not been changed: "<<a;
cout<<"\nAfter EOF is: "<<cin.eof()<<endl;
return 0;
}
--- Конец кода ---
Почему "убивается" последний cin и программа завершается? Я так понимаю символ конца строки у нас остался в потоке и при cin>>a он мешает, но как его убрать тогда? Добавление cin.ignore () перед cin>>a ничего не меняет, да и сколько cin'ов не делай он всё равно я вижу остаётся в потоке до завершения программы, но почему?
Добавлено позже:
Ещё непонятно почему gcount подсчитывает количество символов только при бесформатном вводе типа cin.read, было бы удобнее если бы он всегда считал.
ALEX_230_VOLT:
Я тут тоже курсовик здаю и такой довольно глупый вопрос:
вот допустим у меня переменная типа string. В ней текст
--- Цитата ---ID 100000 Фамилия: Иванов Имя: Иван Отчество: Иванович Улица: им. Пушкина Дом: 17 Квартира: 26 ID 100000 Фамилия: Иванов Имя: Иван Отчество: Иванович Улица: им. Пушкина Дом: 17 Квартира: 26 ID 100000 Фамилия: Иванов Имя: Иван Отчество: Иванович Улица: им. Пушкина Дом: 17 Квартира: 26
--- Конец цитаты ---
вот как мне посчитать сколько раз там встречается сочиатние символов "ID"? ну и на будущее - как научится извлекать из этого сам номер? ну то есть прога видит "ID" и после пробела берёт следующие 6 символов и заносит в новую переменную. кстатитут походу ещё конверсию из string в int придётся делать :-\
HoRRoR:
--- Цитата ---Почему "убивается" последний cin и программа завершается? Я так понимаю символ конца строки у нас остался в потоке и при cin>>a он мешает, но как его убрать тогда? Добавление cin.ignore () перед cin>>a ничего не меняет, да и сколько cin'ов не делай он всё равно я вижу остаётся в потоке до завершения программы, но почему?
--- Конец цитаты ---
Не понял ни кода, ни вопроса.
--- Цитата ---вот как мне посчитать сколько раз там встречается сочиатние символов "ID"? ну и на будущее - как научится извлекать из этого сам номер? ну то есть прога видит "ID" и после пробела берёт следующие 6 символов и заносит в новую переменную. кстатитут походу ещё конверсию из string в int придётся делать
--- Конец цитаты ---
--- Код: ---#include <cstring>
#include <cstdlib>
#include <vector>
void findIDs(const char *str, vector<int>& ids)
{
char buf[7] = "";
while(str = strstr(str, "ID"))
{
str += 3;
strncpy(buf, str, 6);
ids.push_back(atoi(buf));
}
}
--- Конец кода ---
gepar:
ALEX_230_VOLT,элементарно, Ватсон. Даже писать ничего толком не надо :)
--- Код: ---# include <iostream>
using namespace std;
int main()
{
char a[]="ID 1043500 bla bla ID 10235400 bla bla ID 12340"; //наша строка
char *b;
int n; //сколько всего таких ID
b=strtok(a,"ID");
cout<<"Our id is: "<<atoi(b);
n++;
while(b=strtok(NULL,"ID"))//пока у нас ещё есть в строке сочетания символов ID
{
cout<<"\nOur id is:"<<atoi(b);//Выводим этот ID на печать
n++;//увеличиваем счётчик
}
return 0;
}
--- Конец кода ---
Собственно алгоритм я написал, не забудь учесть что ID то может и не быть вообще в строке твоей то.
Добавлено позже:
HoRRoR,а если ID больше 6 цифр? Хотя это я думаю уже пусть ALEX_230_VOLT учитывает.
--- Цитата: HoRRoR ---Не понял ни кода, ни вопроса.
--- Конец цитаты ---
Ну вот скомпилируй этот код, в итоге символ конца строки введённый чтобы пройти это
--- Код: --- while((ch=cin.get())!=EOF)
cout.put(ch);
--- Конец кода ---
застрянет и
--- Код: --- cin>>a;
--- Конец кода ---
выполняться не будет (оно сразу получает символ конца строки и пропускается). Убедиться в том что символ конца строки остаётся в потоке можно дописав в конце ещё cin.peek(), которая тоже возвращает код конца строки (-1). Как убрать символ конца строки из буфера чтобы можно было и дальше читать символы в таком случае? cin.ignore() не помогает.
Добавлено позже:
Ещё у меня тут было чудо задание написать на асме обработчик прерываний чтобы клава мигала,а спикер пк пищал. Сколько примеров не находил - не работали они у меня на пк и всё тут. Решил тогда взяться за написание на с++ и за инструмента от майкрософта под винду.
Что мы имеем: майкрософт предоставляет вот такие вот возможности, использовать можно где угодно по сути. Но я так до конца со всем и не разобрался: есть клавиша и есть её скан код и вроде бы всё логично, да толкьо в примере сканкод у намлока 0x45, а в таблице кодов на которую есть ссылка там же код 0x45 принадлежит одной из клавиш основного ряда клавиатуры что сразу же меня запутало. Методом тыка и смотря на тот пример создал тогда вот такую прогу и сдал
--- Код: --- #include <windows.h>
#include <iostream>
void SetNumLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_NUMLOCK] & 1)) ||
(!bState && (keyState[VK_NUMLOCK] & 1)) )
{
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
void SetCapsLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_CAPITAL] & 1)) ||
(!bState && (keyState[VK_CAPITAL] & 1)) )
{
keybd_event( VK_CAPITAL,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
keybd_event( VK_CAPITAL,
0x14,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
void SetScrLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_SCROLL] & 1)) ||
(!bState && (keyState[VK_SCROLL] & 1)) )
{
keybd_event( VK_SCROLL,
0x91,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
keybd_event( VK_SCROLL,
0x91,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
int main()
{
int count=1000;
do
{
SetNumLock( TRUE );
SetCapsLock(TRUE);
SetScrLock (TRUE);
SetNumLock( FALSE );
SetCapsLock(FALSE);
SetScrLock (FALSE);
if (count%50==0)
std::cout<<'\a';
count--;
}while(count);
return 0;
}
--- Конец кода ---
Но до конца так и не разобрался почему же она так странно работает. Вот например начальная версия программы на которой странности лучше заметны
--- Код: ---
#include <windows.h>
#include <iostream>
void SetNumLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_NUMLOCK] & 1)) ||
(!bState && (keyState[VK_NUMLOCK] & 1)) )
{
// Simulate a key press
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
// Simulate a key release
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
void SetCapsLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_CAPITAL] & 1)) ||
(!bState && (keyState[VK_CAPITAL] & 1)) )
{
// Simulate a key press
keybd_event( VK_CAPITAL,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
// Simulate a key release
keybd_event( VK_CAPITAL,
0x45,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
void SetScrLock( BOOL bState )
{
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_SCROLL] & 1)) ||
(!bState && (keyState[VK_SCROLL] & 1)) )
{
// Simulate a key press
keybd_event( VK_SCROLL,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
// Simulate a key release
keybd_event( VK_SCROLL,
0x45,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
}
int main()
{
SetNumLock( TRUE );
SetCapsLock(TRUE);
SetScrLock (TRUE);
int a;
std::cin>>a;
SetNumLock( FALSE );
SetCapsLock(FALSE);
SetScrLock (FALSE);
}
--- Конец кода ---
Если в коде оставить в конце SetScrLock (FALSE) то выключится только scrolLock, а если убрать то выключиться капс и нам лок. Почему так?
Я понял что там у нас вроде как идёт какой-то буфер в какой запихывая новые значения мы подпихиваем предыдущие, но всё же чего оно так странно работает-то ? :) Ну это я спрашиваю если кто пробовал таким баловаться, может там себе визуализатор музыки на индикаторы клавиатуры прикрутить пытались или ещё что :)
HoRRoR:
--- Цитата ---ALEX_230_VOLT,элементарно, Ватсон. Даже писать ничего толком не надо
--- Конец цитаты ---
Из пушки по воробьям.
--- Цитата ---HoRRoR,а если ID больше 6 цифр? Хотя это я думаю уже пусть ALEX_230_VOLT учитывает.
--- Конец цитаты ---
Тогда парсить. Что-то вроде
--- Код: ---int value = 0;
while(*str >= '0' && *str <= '9')
{
value *= 10;
value += (*str - '0');
str++;
}
--- Конец кода ---
--- Цитата ---Ну вот скомпилируй этот код, в итоге символ конца строки введённый чтобы пройти это
--- Конец цитаты ---
Ещё бы знать, чему у тебя равен EOF. У меня при #define EOF '\n' всё отлично срабатывает.
Добавлено позже:
Если EOF у тебя -1 и ты ожидаешь конца потока, то как можно что-то считывать после того, как всё закончилось?
Естественно, что при достижении конца потока попытка считать что-либо приведёт лишь к ошибке.
gepar:
--- Цитата: HoRRoR ---Из пушки по воробьям.
--- Конец цитаты ---
Ну почему же :) Вполне логично - ищем следующее вхождение ID преобразуем все цифры до первого символа в код ID, потом опять ... так не будем зависить от того сколько там цифр да и логично вроде, ну в общем я бы сделал так. Такую вещь как strstr я пока не использовал и не знал о ней, может с ней и правда удобнее.
--- Цитата: HoRRoR ---Ещё бы знать, чему у тебя равен EOF.
--- Конец цитаты ---
-1
--- Цитата: HoRRoR ---Если EOF у тебя -1 и ты ожидаешь конца потока, то как можно что-то считывать после того, как всё закончилось?
--- Конец цитаты ---
Я хочу сбросить это состояние потока (помоему я повторяюсь повторяюсь повторяюсь :) ).
Вот как пример будет надо сохранить два куска текста с пробелами и переводами каретки в два массива символов
--- Код: ---# include <iostream>
using namespace std;
int main()
{
int n=127;
char ch1[n];
char ch2[n];
cout<<"cin.get in ch1: ";
cin.get(ch1,n, EOF);
cout<<"/ncin.get in ch2: ";
cin.get(ch2,n, EOF);
cout<<"/n/nCh1 is: "<<ch1<<"\nCh2 is: "<<ch2;
}
--- Конец кода ---
Так вот закончив ввод первого куска текста через ctrl+Z ввод второго не начнётся (ctrl+Z останется в потоке же), как его убрать оттудова чтобы был возможен ввод и второго куска текста? Ну должен же быть какой-то способ.
Добавлено позже:
Разобрался что мне нужен не cin.ignore(), а cin.clear() в данной ситуации.
HoRRoR:
--- Цитата ---Вполне логично - ищем следующее вхождение
--- Конец цитаты ---
Ты не ищешь вхождение, ты разбиваешь на лексемы, что абсолютно не нужно в данном случае. Тем более что поиск подразумевает под собой неизменность текста.
--- Цитата ---Так вот закончив ввод первого куска текста через ctrl+Z ввод второго не начнётся (ctrl+Z останется в потоке же), как его убрать оттудова чтобы был возможен ввод и второго куска текста? Ну должен же быть какой-то способ.
--- Конец цитаты ---
Это не символ, это конец потока. Как ты из файла уберёшь конец файла, например?
ALEX_230_VOLT:
спасибо что откликнулись, но не сильно это помогло. дело в том, что у меня тип строки string, а НЕ массив из char. хотя покопавшись в инете я смог преобразовать string в char и код gepar заработал. а вот как использовать функцию HoRRoR я что то не понял. можно это сделать не в виде отдельной функции, а как кусок основной программы? ну или обьясни какие параметры ей задавать (ну первый то понятно, а вот второй)
Навигация
Перейти к полной версии