Russian Qt Forum

Программирование => Общий => Тема начата: vfrcbvrf23 от Апрель 11, 2016, 23:24



Название: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 11, 2016, 23:24
Возник вопрос при постройке графика при помощи qcustomplot. Она,проблема, заключается в том что, какой бы я график не пытался построить, всегда уходит в точку(0;0).
При постройке y=5, получаю вот такой результат:
http://c2n.me/3wNhOMT(не понял как вставить картинку)

И вот собственно код, как это происходит:
Код:
void MainWindow::on_pushButton_27_clicked()//кнопка построения первой производной введенной пользователем
{
    char* p = new char(ui->lineEdit_3->text().length() + 1);
    strcpy(p, ui->lineEdit_3->text().toUtf8().constData());
    functparcer funct1 = functparcer(p);
    double dlina = ui->lineEdit_2->text().toDouble();
    double a = -dlina; //Начало интервала, где рисуем график по оси Ox
    double b = dlina+1; //Конец интервала, где рисуем график по оси Ox
    double h = 0.001; //Шаг, с которым будем пробегать по оси Ox
    int n=10*((b-a)/h + 1); //Вычисляем количество точек, которые будем отрисовывать
    QVector<double> x(n), y(n); //Массивы координат точек
    //Вычисляем наши данные
    int i=0;
    for (double X=a; X<=b; X+=h)
    {
        x[i]=X;
        y[i]=funct1.getY(X);
        i++;
    }
    ui->widget->addGraph();
    ui->widget->graph(0)->setData(x, y);
    ui->widget->graph(0)->setPen(QColor(0, 0, 250, 255));
    ui->widget->xAxis->setLabel("x");
    ui->widget->yAxis->setLabel("y");
    ui->widget->xAxis->setRange(-dlina, dlina);//Для оси Ox
    ui->widget->yAxis->setRange(-dlina, dlina);//Для оси Oy
    ui->widget->replot();//И перерисуем график на нашем widget
}
как от этого избавиться?


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 09:52
наверно нужно разбираться вот с этим
functparcer funct1 = functparcer(p);
и с этим
funct1.getY(X);

из кода не видно, что строиться график у=5. попробуйте для начала так

Код:
    //Вычисляем наши данные
    int i=0;
    for (double X=a; X<=b; X+=h)
    {
        x[i]=X;
        y[i]=5;
        i++;
    }

Если график будет нормальный, то ковыряйте functparcer.


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: Old от Апрель 12, 2016, 09:54
наверно нужно разбираться вот с этим
Не, начать нужно еще с этого: :)
Код
C++ (Qt)
char* p = new char(ui->lineEdit_3->text().length() + 1);
 


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: Racheengel от Апрель 12, 2016, 10:46
Цитировать
    char* p = new char(ui->lineEdit_3->text().length() + 1);
    strcpy(p, ui->lineEdit_3->text().toUtf8().constData());

вообще адище :(

имхо хватит вызова functparcer(ui->lineEdit_3->text().toUtf8().constData());


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 12:29
Цитировать
   char* p = new char(ui->lineEdit_3->text().length() + 1);
    strcpy(p, ui->lineEdit_3->text().toUtf8().constData());

вообще адище :(

имхо хватит вызова functparcer(ui->lineEdit_3->text().toUtf8().constData());
При таком написании выдает ошибку:
D:\QT\kurc\mainwindow.cpp:129: ошибка: invalid conversion from 'const char*' to 'char*' [-fpermissive]
     functparcer(ui->lineEdit_3->text().toUtf8().constData());
Именно из-за этой ошибки все было сделано так как оно есть, ибо по другому реализовать не получалось

                                                           ^


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 12:30
наверно нужно разбираться вот с этим
functparcer funct1 = functparcer(p);
и с этим
funct1.getY(X);

из кода не видно, что строиться график у=5. попробуйте для начала так

Код:
    //Вычисляем наши данные
    int i=0;
    for (double X=a; X<=b; X+=h)
    {
        x[i]=X;
        y[i]=5;
        i++;
    }

Если график будет нормальный, то ковыряйте functparcer.

График не изменился, все осталось точно так же.(http://clip2net.com/s/3wOhAeR)


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 12:35
наверно нужно разбираться вот с этим
Не, начать нужно еще с этого: :)
Код
C++ (Qt)
char* p = new char(ui->lineEdit_3->text().length() + 1);
 
Что вы имеете ввиду? Я просто перепробовал уже уйму всего и все равно не могу понять в чем проблема.


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: Old от Апрель 12, 2016, 12:41
Что вы имеете ввиду? Я просто перепробовал уже уйму всего и все равно не могу понять в чем проблема.
Здесь вы выделяете в куче ОДИН байт и инициализируете его длиной строки.
Код
C++ (Qt)
char* p = new char(ui->lineEdit_3->text().length() + 1);
 

Следующее копирование разрушает (затирает) память кучи и включает "режим чудес". Дальше может происходит много странного: от падения программы и до вычисления неверных результатов.

Если вы хотели выделить буфер для хранения всей строки из lineEdit_3, то нужно делать так:
Код
C++ (Qt)
char* p = new char[ ui->lineEdit_3->text().length() + 1 ];
 

P.S. Вряд ли вы "далеко уедите" методом тыка. C++ это не тот язык. ;)


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 12:51
Что вы имеете ввиду? Я просто перепробовал уже уйму всего и все равно не могу понять в чем проблема.
Здесь вы выделяете в куче ОДИН байт и инициализируете его длиной строки.
Код
C++ (Qt)
char* p = new char(ui->lineEdit_3->text().length() + 1);
 

Следующее копирование разрушает (затирает) память кучи и включает "режим чудес". Дальше может происходит много странного: от падения программы и до вычисления неверных результатов.

Если вы хотели выделить буфер для хранения всей строки из lineEdit_3, то нужно делать так:
Код
C++ (Qt)
char* p = new char[ ui->lineEdit_3->text().length() + 1 ];
 

P.S. Вряд ли вы "далеко уедите" методом тыка. C++ это не тот язык. ;)
Это не дало никаких результатов, строится точно так же.

Я просто только начинаю изучать программирование, и меня привлекла сама среда Qt. А в плане обучения руководителем была поставлена задача реализовать построение графиков, вводимых пользователем. И вот я над ней бьюсь уже больше месяца, но сделать ничего самому не удалось с проблемой, поэтому решил вот попросить помощи у более умных людей.


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 13:21

от сюда  (http://www.qcustomplot.com/index.php/tutorials/basicplotting)взят пример. уберите весь бред в начале функции и сделайте так

Код:
void MainWindow::on_pushButton_27_clicked()//кнопка построения первой производной введенной пользователем
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)
{
  x[i] = i/50.0 - 1; // x goes from -1 to 1
  y[i] = x[i]*x[i]; // let's plot a quadratic function
}
// create graph and assign data to it:
ui->widget->addGraph();
ui->widget->graph(0)->setData(x, y);
// give the axes some labels:
ui->widget->xAxis->setLabel("x");
ui->widget->yAxis->setLabel("y");
// set axes ranges, so we see all data:
ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(0, 1);
ui->widget->replot();
}
будет парабола, изкаропки. потом сделайте ваш у=5

Код:
void MainWindow::on_pushButton_27_clicked()//кнопка построения первой производной введенной пользователем
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)
{
  x[i] = i/50.0 - 1; // x goes from -1 to 1
  y[i] = 5; // let's plot a quadratic function
}
// create graph and assign data to it:
ui->widget->addGraph();
ui->widget->graph(0)->setData(x, y);
// give the axes some labels:
ui->widget->xAxis->setLabel("x");
ui->widget->yAxis->setLabel("y");
// set axes ranges, so we see all data:
ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(0, 1);
ui->widget->replot();
}
Должны увидеть прямую без захода в 0,0. Дальше этот пример добавляйте вашим кодом....

Цитировать
Я просто только начинаю изучать программирование
вы меня извините, но как-то написано всё... неочевидно. индусский код, одним словом.
цикл заполнения
Код:
  //Вычисляем наши данные
    for (int i = 0; i<n; i++)
    {
        x[i] = a + h*i;//и вообще уберите a и b. они не нужны. сделайте так x[i] = h*i - dlina ;
        y[i] = 5;// или funct1.getY(x[i]);
    }

double dlina = ui->lineEdit_2->text().toDouble(); в Qt есть виджет для таких целей  QDoubleSpinBox и QSpinBox
double dlina = ui->doubleSpinBox->value();

Код:
int n=10*((b-a)/h + 1); //Вычисляем количество точек, которые будем отрисовывать
vs
Код:
for (double X=a; X<=b; X+=h)
допустим длинну ввели 10, т.е. dlina = 10.0. Считаем сколько будет n? n = 10*( 1 +   (11-(-10))/0.001)  ) = 210010. Далее создаются два вектора размером в 210 тыщ! но в цикле for вы всего заполняете первые 21000 элементов этих векторов. Судя по всему должно быть так
int n= dlina*2/h; ну или так int n= 1 + dlina*2/h;


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 13:33
Цитировать
char* p = new char ....
а тут утечка памяти.... где delete?


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 13:48
Цитировать
   char* p = new char(ui->lineEdit_3->text().length() + 1);
    strcpy(p, ui->lineEdit_3->text().toUtf8().constData());

вообще адище :(

имхо хватит вызова functparcer(ui->lineEdit_3->text().toUtf8().constData());
При таком написании выдает ошибку:
D:\QT\kurc\mainwindow.cpp:129: ошибка: invalid conversion from 'const char*' to 'char*' [-fpermissive]
     functparcer(ui->lineEdit_3->text().toUtf8().constData());
Именно из-за этой ошибки все было сделано так как оно есть, ибо по другому реализовать не получалось

                                                           ^
Как объявлена функция functparcer()? Очевидно, что в неё передается указатель на строку для разбора, а не для того, чтобы изменить эту строку. Поэтому нужно объявлять с константным аргументом functparcer(const char *p), тогда можно передать константный указатель functparcer(ui->lineEdit_3->text().toUtf8().constData());


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 13:55
Код:
void MainWindow::on_pushButton_27_clicked()//кнопка построения первой производной введенной пользователем
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)
{
  x[i] = i/50.0 - 1; // x goes from -1 to 1
  y[i] = x[i]*x[i]; // let's plot a quadratic function
}
// create graph and assign data to it:
ui->widget->addGraph();
ui->widget->graph(0)->setData(x, y);
// give the axes some labels:
ui->widget->xAxis->setLabel("x");
ui->widget->yAxis->setLabel("y");
// set axes ranges, so we see all data:
ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(0, 1);
ui->widget->replot();
}
будет парабола, изкаропки. потом сделайте ваш у=5

Код:
void MainWindow::on_pushButton_27_clicked()//кнопка построения первой производной введенной пользователем
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)
{
  x[i] = i/50.0 - 1; // x goes from -1 to 1
  y[i] = 5; // let's plot a quadratic function
}
// create graph and assign data to it:
ui->widget->addGraph();
ui->widget->graph(0)->setData(x, y);
// give the axes some labels:
ui->widget->xAxis->setLabel("x");
ui->widget->yAxis->setLabel("y");
// set axes ranges, so we see all data:
ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(0, 1);
ui->widget->replot();
}
Должны увидеть прямую без захода в 0,0. Дальше этот пример добавляйте вашим кодом....
Код:
  //Вычисляем наши данные
    for (int i = 0; i<n; i++)
    {
        x[i] = a + h*i;//и вообще уберите a и b. они не нужны. сделайте так x[i] = h*i - dlina ;
        y[i] = 5;// или funct1.getY(x[i]);
    }

double dlina = ui->lineEdit_2->text().toDouble(); в Qt есть виджет для таких целей  QDoubleSpinBox и QSpinBox
double dlina = ui->doubleSpinBox->value();


Сделал все как вы сказали вот тут.
При построении он выдал примерно следующее
http://c2n.me/3wOANdZ(вот синенькая черточка это результат)


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 13:57
а почему на картинке от -10 до 10 график? в коде рэндж ставиться ui->widget->xAxis->setRange(-1, 1);


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: __Heaven__ от Апрель 12, 2016, 13:58
Код
C++ (Qt)
char* p = new char[ ui->lineEdit_3->text().length() + 1 ];
 

Кажется, этого недостаточно для отключения "режима чудес". Там далее следует
Код
C++ (Qt)
strcpy(p, ui->lineEdit_3->text().toUtf8().constData());


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 14:03
а почему на картинке от -10 до 10 график? в коде рэндж ставиться ui->widget->xAxis->setRange(-1, 1);

Ренж выставил от -10 до 10 везде, ибо если ставить ренж (-1;1), то 5 туда точно не войдет.


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 14:04
ну так по х оставте -1,1, а по у -10, 10

ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(-10, 10);


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 14:08
Цитировать
   char* p = new char(ui->lineEdit_3->text().length() + 1);
    strcpy(p, ui->lineEdit_3->text().toUtf8().constData());

вообще адище :(

имхо хватит вызова functparcer(ui->lineEdit_3->text().toUtf8().constData());
При таком написании выдает ошибку:
D:\QT\kurc\mainwindow.cpp:129: ошибка: invalid conversion from 'const char*' to 'char*' [-fpermissive]
     functparcer(ui->lineEdit_3->text().toUtf8().constData());
Именно из-за этой ошибки все было сделано так как оно есть, ибо по другому реализовать не получалось

                                                           ^
Как объявлена функция functparcer()? Очевидно, что в неё передается указатель на строку для разбора, а не для того, чтобы изменить эту строку. Поэтому нужно объявлять с константным аргументом functparcer(const char *p), тогда можно передать константный указатель functparcer(ui->lineEdit_3->text().toUtf8().constData());
functparcer::functparcer(char* massiv)
Если я правильно понял о чем вы, могу вставить код парсера если нужно.


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 14:09
ну так по х оставте -1,1, а по у -10, 10

ui->widget->xAxis->setRange(-1, 1);
ui->widget->yAxis->setRange(-10, 10);
Стало вот так: http://c2n.me/3wODL3c


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 14:10
Цитировать
Стало вот так: http://c2n.me/3wODL3c
а парабола строиться нормально?


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 14:15
Цитировать
Стало вот так: http://c2n.me/3wODL3c
а парабола строиться нормально?
Да, парабола строится нормально. Даже в изначальном варианте она строилась нормально. Ведь в самом графике параболы есть точка с координатами (0;0).


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 14:21
functparcer::functparcer(char* massiv)
Если я правильно понял о чем вы, могу вставить код парсера если нужно.
У вас парсер должен модифицировать строку массив? по задумке - должен или нет? Могу предположить, что нет. Тогда нужно конструктор объявлять так
functparcer::functparcer(const char* massiv)

Если предполагается внунтри класса модифицировать строку во время парсинья.... то сделайте внутри конструктора копию строки

functparcer::functparcer(const char* massiv)
{
ownerStr = new char[strlen(massiv) + 1];
strcpy(this->ownerStr, massive);
...
}
в деструкторе зачистку с delete.
functparcer::~functparcer()
{
delete [] ownerStr;
} Вобщем тут от задумки зависит


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 14:27
Да, парабола строится нормально. Даже в изначальном варианте она строилась нормально.
т.е. меняете одну строчку y = x*x на y = 5 и  QCustomPlot перестает работать? странно. а если рэндж везде -1, 1 и y = 0.5?

Цитировать
Ведь в самом графике параболы есть точка с координатами (0;0).
а если y = x*x + 0.1, то не будет точки 0.0.

ps я бы сам поигрался бы с QCustomPlot, только эта библа у меня не установлена....


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 14:46
Да, парабола строится нормально. Даже в изначальном варианте она строилась нормально.
т.е. меняете одну строчку y = x*x на y = 5 и  QCustomPlot перестает работать? странно. а если рэндж везде -1, 1 и y = 0.5?

Цитировать
Ведь в самом графике параболы есть точка с координатами (0;0).
а если y = x*x + 0.1, то не будет точки 0.0.

ps я бы сам поигрался бы с QCustomPlot, только эта библа у меня не установлена....

Код:
for (int i=0; i<101; ++i)
    {
        x[i] = i/50.0 - 1 ; // x goes from -1 to 1
        y[i] = 0.5 ; // let's plot a quadratic function
    }
    // create graph and assign data to it:
    ui->widget->addGraph();
    ui->widget->graph(0)->setData(x, y);
    // give the axes some labels:
    ui->widget->xAxis->setLabel("x");
    ui->widget->yAxis->setLabel("y");
    // set axes ranges, so we see all data:
    ui->widget->xAxis->setRange(-1, 1);
    ui->widget->yAxis->setRange(-1, 1);
    ui->widget->replot();

Вот в таком варианте нормально все строится.

Код:
 x[i] = h*i - dlina ;
Когда меняем на это,уже не получается


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 12, 2016, 14:53
Код:
 x[i] = h*i - dlina ;
Когда меняем на это,уже не получается
чтобы получилось, должно в рандж попасть. сделайте  h = 0.02, а dlina = 1. тогда первая точка должна быть (-1, 0.5), последняя (1, 0.5)


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 15:10
Код:
 x[i] = h*i - dlina ;
Когда меняем на это,уже не получается
чтобы получилось, должно в рандж попасть. сделайте  h = 0.02, а dlina = 1. тогда первая точка должна быть (-1, 0.5), последняя (1, 0.5)

Я вот немного не пойму, а от куда из вот этого:
Код:
x[i] = i/50.0 - 1 ;
Получается вот это:
Код:
x[i] = h*i - dlina


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: vfrcbvrf23 от Апрель 12, 2016, 18:04
Код:
 x[i] = h*i - dlina ;
Когда меняем на это,уже не получается
чтобы получилось, должно в рандж попасть. сделайте  h = 0.02, а dlina = 1. тогда первая точка должна быть (-1, 0.5), последняя (1, 0.5)

Я вообщем решил проблему, но немного не тем путем.
Все решилось дописыванием 2х строчек:
Код:
 
x.resize(i);
y.resize(i);
Вот так вот


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: Igors от Апрель 12, 2016, 18:56
Вот так вот
Ну и слава богу что все порешали


Название: Re: Так и не понял куда задать свой вопрос, поэтому задам сюда.
Отправлено: juvf от Апрель 13, 2016, 05:47
Код:
 x[i] = h*i - dlina ;
Когда меняем на это,уже не получается
чтобы получилось, должно в рандж попасть. сделайте  h = 0.02, а dlina = 1. тогда первая точка должна быть (-1, 0.5), последняя (1, 0.5)

Я вот немного не пойму, а от куда из вот этого:
Код:
x[i] = i/50.0 - 1 ;
Получается вот это:
Код:
x[i] = h*i - dlina

Цитировать
сделайте  h = 0.02, а dlina = 1
i/50 -1 = i * 1/50 -1 = i * 0.02 -1 = i*h - dlina