I am new and really unexperienced with coding, but we got a task at the university where I ran into a problem I could not solve by myself. In one class a vector causes a problem I do not understand. After hours of trial and error I am a bit tired of guessing... So, I try it here and hope for some help.
The program is supposed to draw an diagram based on some Input variables the user can change. At the moment I am trying to implement the painting of the graph. The Input and the calculation of the data works.
One aspect of the task is that we have to safe the calculated data in a vector and pass this vector as a pointer to other functions, for example the painter.
Now, here the problem occures. Any interaction with the vector m_punkte I passed to paintEvent causes a crash of the program. I could narrow the problem down to commands like: vector->begin() or vector->end(). In the instant the program tries to execute them, windows stops the program.
At first I thought the vector could be somehow passed wrong and I am trying to call an empty vector or the address is undefined, but even commands like vector->emty() causing the crash. So I believe it is a more general error which is caused by the framework or something like that.
After running the debugging tool, it also told me that the error is caused by the mentioned commands and further more told me this:
Der Prozess wurde wegen eines Signals vom Betriebssystem angehalten.
Name des Signals : SIGSEGV
Bedeutung : Segmentation fault
I guess that's some kind of memory problem, right?
I would be really happy if someone could help me, so I can work again on the actual task and not guessing why this vector is somehow broken
What I can also tell is that I am working with Qt Creator and the program is running as an QtWidget program if that helps.
Dropbox link to a copy of the programm:
https://www.dropbox.com/sh/l5e220lk5y7jx2z/AAAdG7AjHiiKJxOKWT-zrP8ia?dl=0
I Hope now my question is clear and this helps more to find the origin of the error.
datenpunkt.h
#ifndef DATENPUNKT_H
#define DATENPUNKT_H
#include <vector>
struct datenpunkt
{
float temperatur;
float widerstand;
float laenge;
};
typedef std::vector<datenpunkt> PunktVektor;
#endif // DATENPUNKT_H
diagrammwidget.h
#ifndef DIAGRAMMWIDGET_H
#define DIAGRAMMWIDGET_H
#include "datenpunkt.h"
#include <QWidget>
namespace Ui {
class DiagrammWidget;
}
class DiagrammWidget : public QWidget
{
Q_OBJECT
public:
explicit DiagrammWidget( QWidget *parent = 0);
~DiagrammWidget();
void setPunkte (PunktVektor *punkte);
void setUntere_temp(int untere_temp);
void setObere_temp(int obere_temp);
void setAufloesung(int aufloesung);
PunktVektor *punkte() const;
protected:
void paintEvent(QPaintEvent *event);
private:
Ui::DiagrammWidget *ui;
PunktVektor *m_punkte;
int m_untere_temp = 0;
int m_obere_temp = 0;
int m_aufloesung = 0;
};
#endif // DIAGRAMMWIDGET_H
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include "datenpunkt.h"
#include <string.h>
#include <QDialog>
#include <QString>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
void werteberechnung(PunktVektor *m_PunktListe);
float untere_temp() const;
void setUntere_temp(float untere_temp);
float obere_temp() const;
void setObere_temp(float obere_temp);
int aufloesung() const;
void setAufloesung(int aufloesung);
QString werkstoff() const;
void setWerkstoff(QString werkstoff);
float materialkonstante() const;
void setMaterialkonstante(float materialkonstante);
float bezugswiderstand() const;
void setBezugswiderstand(float bezugswiderstand);
float wiederstand() const;
void setWiederstand(float wiederstand);
float temperatur() const;
void setTemperatur(float temperatur);
private slots:
void on_speichern_clicked();
void on_verwerfen_clicked();
void on_zuruecksetzen_clicked();
private:
Ui::Dialog *ui;
PunktVektor *m_PunktListe;
QString m_werkstoff = "A 34-2/30 (SIEMENS)";
float m_materialkonstante = 3440; // B/ K
float m_bezugswiderstand = 5000; // Rto/ Ohm
float m_untere_temp = 0 + 272.15;
float m_obere_temp = 300 + 272.15;
int m_aufloesung = 10;
float m_RT= 0; // Rt/ Ohm
float m_To = 20 + 272.15;
float m_T = 0; // T/ C°
float m_UD; //Untere Dekadengrenze
float m_OD; //Obere Dekadengrenze
};
#endif // DIALOG_H
diagrammwidget.cpp
#include "diagrammwidget.h"
#include "ui_diagrammwidget.h"
#include "datenpunkt.h"
#include <vector>
#include <QtCore>
#include <QtGui>
DiagrammWidget::DiagrammWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::DiagrammWidget){
ui->setupUi(this);
m_punkte = 0;
}
DiagrammWidget::~DiagrammWidget(){
delete ui;
}
void DiagrammWidget::setPunkte(PunktVektor *punkte){
m_punkte = punkte;
}
void DiagrammWidget::paintEvent(QPaintEvent *event)
{
QPainter myPainter (this);
/*if((m_punkte == 0|| m_punkte->size() == 0)){
myPainter.drawText(100,100,"No Points found!");
return;
}*/
datenpunkt ersterPunkt=*m_punkte->begin();
datenpunkt startPunkt = ersterPunkt;
PunktVektor::iterator it;
for( it = m_punkte->begin()++; it != m_punkte->end(); it++){
datenpunkt p = *it;
myPainter.drawLine(startPunkt.temperatur,startPunkt.laenge,
p.temperatur,p.laenge);
startPunkt = p;
}
}
PunktVektor *DiagrammWidget::punkte() const{
return m_punkte;
}
void DiagrammWidget::setAufloesung(int aufloesung){
m_aufloesung = aufloesung;
}
void DiagrammWidget::setObere_temp(int obere_temp){
m_obere_temp = obere_temp;
}
void DiagrammWidget::setUntere_temp(int untere_temp){
m_untere_temp = untere_temp;
}
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include "datenpunkt.h"
#include "diagrammwidget.h"
#include <QtCore>
#include <QtGui>
#include <QString>
#include <math.h>
#include <iostream>
using namespace std;
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
m_PunktListe = new PunktVektor;
//Standarteinstellungen
ui->werkstoff->setText("A 34-2/30 (SIEMENS)");
ui->materialkonstante->setValue(3440);
ui->materialkonstante->setSuffix(" K");
ui->bezugswiderstand->setValue(5000);
ui->bezugswiderstand->setSuffix(" Ω");
ui->unteretemperatur->setValue(0);
ui->unteretemperatur->setSuffix(" °C");
ui->oberetemperatur->setValue(300);
ui->oberetemperatur->setSuffix(" °C");
ui->aufloesung->setValue(10);
ui->aufloesung->setSuffix(" Δ°C");
ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
ui->oberetemperatur->setSingleStep(ui->aufloesung->value());
werteberechnung(m_PunktListe);
//Diagramm aktualisieren und Anzeigen
DiagrammWidget dg;
dg.setUntere_temp(m_untere_temp);
dg.setObere_temp(m_obere_temp);
dg.setAufloesung(m_aufloesung);
dg.setPunkte(m_PunktListe);
dg.show();
}
Dialog::~Dialog()
{
delete m_PunktListe;
delete ui;
}
void Dialog::werteberechnung(PunktVektor *m_PunktListe)
{
datenpunkt p;
float temp = m_untere_temp;
//Anzahl der zu bestimmenden Datenpunkte
int anzahl = (m_obere_temp-m_untere_temp)/m_aufloesung;
//Bestimmen der Dekadengrenzen UD und OD
m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante*
((1/m_obere_temp)-(1/m_To))));
m_UD = (int(log10(m_RT)));
m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante*
((1/m_untere_temp)-(1/m_To))));
m_OD = (int(log10(m_RT))+1);
//Füllen des Datenvectors
for (int i = 0; i <= anzahl; i++){
m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante*
((1/temp)-(1/m_To))));
p.widerstand = m_RT;
p.temperatur = temp;
float x = log10(m_RT);
if(m_UD != 0){
p.laenge = ((x-m_UD)*5);
}
else
p.laenge = x*5;
m_PunktListe->push_back(p);
temp = temp + m_aufloesung;
}
}
void Dialog::on_speichern_clicked()
{
setWerkstoff(ui->werkstoff->text());
setMaterialkonstante(ui->materialkonstante->value());
setBezugswiderstand(ui->bezugswiderstand->value());
setUntere_temp(ui->unteretemperatur->value()+ 272.15);
setObere_temp(ui->oberetemperatur->value()+ 272.15);
setAufloesung(ui->aufloesung->value());
ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
ui->oberetemperatur->setSingleStep(ui->aufloesung->value());
//Berechnung des Datenvectors
werteberechnung(m_PunktListe);
//Diagramm aktualisieren
DiagrammWidget dg;
dg.setUntere_temp(m_untere_temp);
dg.setObere_temp(m_obere_temp);
dg.setAufloesung(m_aufloesung);
dg.setPunkte(m_PunktListe);
dg.show();
}
float Dialog::temperatur() const{
return m_T;
}
void Dialog::setTemperatur(float temperatur){
m_T = temperatur;
}
float Dialog::wiederstand() const{
return m_RT;
}
void Dialog::setWiederstand(float wiederstand){
m_RT = wiederstand;
}
float Dialog::bezugswiderstand() const{
return m_bezugswiderstand;
}
void Dialog::setBezugswiderstand(float bezugswiderstand){
m_bezugswiderstand = bezugswiderstand;
}
float Dialog::materialkonstante() const{
return m_materialkonstante;
}
void Dialog::setMaterialkonstante(float materialkonstante){
m_materialkonstante = materialkonstante;
}
QString Dialog::werkstoff() const{
return m_werkstoff;
}
void Dialog::setWerkstoff(QString werkstoff){
m_werkstoff = werkstoff;
}
int Dialog::aufloesung() const{
return m_aufloesung;
}
void Dialog::setAufloesung(int aufloesung){
m_aufloesung = aufloesung;
}
float Dialog::obere_temp() const{
return m_obere_temp;
}
void Dialog::setObere_temp(float obere_temp){
m_obere_temp = obere_temp;
}
float Dialog::untere_temp() const
{
return m_untere_temp;
}
void Dialog::setUntere_temp(float untere_temp)
{
m_untere_temp = untere_temp;
}
void Dialog::on_verwerfen_clicked()
{
ui->werkstoff->setText(m_werkstoff);
ui->materialkonstante->setValue(m_materialkonstante);
ui->bezugswiderstand->setValue(m_bezugswiderstand);
ui->unteretemperatur->setValue(m_untere_temp);
ui->oberetemperatur->setValue(m_obere_temp);
ui->aufloesung->setValue(m_aufloesung);
ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
ui->oberetemperatur->setSingleStep(ui->aufloesung->value());
}
void Dialog::on_zuruecksetzen_clicked()
{
//Standarteinstellungen
ui->werkstoff->setText("A 34-2/30 (SIEMENS)");
ui->materialkonstante->setValue(3440);
ui->bezugswiderstand->setValue(5000);
ui->unteretemperatur->setValue(0);
ui->aufloesung->setValue(10);
ui->oberetemperatur->setValue(300);
setWerkstoff(ui->werkstoff->text());
setMaterialkonstante(ui->materialkonstante->value());
setBezugswiderstand(ui->bezugswiderstand->value());
setUntere_temp(ui->unteretemperatur->value()+ 272.15);
setObere_temp(ui->oberetemperatur->value()+ 272.15);
setAufloesung(ui->aufloesung->value());
ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
ui->oberetemperatur->setSingleStep(ui->aufloesung->value());
werteberechnung(m_PunktListe);
}
main.cpp
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
As noted in the comments, your example is not MCVE. But guessing, there are a couple of clues:
PunktVektor *m_punkte; //This is the mentioned vector
and
datenpunkt test = *m_punkte->begin(); <- //The programm crashs
Unless PunktVector overloads operator->(), your access of the vector should probably be
datenpunkt test = m_punkte->begin(); <- //no dereference (*)
REVISION:
With your updated example, the basic problem is dereferencing the end() iterator, which is a marker and does not refer to an element
datenpunkt test = *m_punkte->begin();
datenpunkt test2 =*m_punkte->end();
*m_punkte->empty();
m_punkte->begin() returns an iterator to the first element (if there is one; the vector could be empty). *( m_punkte->begin() ) accesses the element the iterator refers to.
m_punkte->end() return an iterator marking the end of the container. * (m_punkte->end() ) is undefined.
m_punkte->empty() returns a bool reflecting whether the container is empty or not. *( m_punkte->empty() ) will access either memory location 0 or 1 (both of which are likely to be very bad.
REVISION 2:
When working with containers, it is important to understand how you can hurt yourself. In particular, look here:
void DiagrammWidget::paintEvent(QPaintEvent *event)
{
QPainter myPainter (this);
/*if((m_punkte == 0|| m_punkte->size() == 0)){
myPainter.drawText(100,100,"No Points found!");
return;
}*/
datenpunkt ersterPunkt=*m_punkte->begin();
datenpunkt startPunkt = ersterPunkt;
PunktVektor::iterator it;
for( it = m_punkte->begin()++; it != m_punkte->end(); it++){
datenpunkt p = *it;
myPainter.drawLine(startPunkt.temperatur,startPunkt.laenge,
p.temperatur,p.laenge);
startPunkt = p;
}
}
If you are going to do this: datenpunkt ersterPunkt=*m_punkte->begin();
then you must first check to see of the container is empty.
Container.begin() returns an iterator to the first element of the container. If the container is empty, this iterator is equal to Container.end(). Dereferencing this iterator is a good way to crash your program.
Try refactoring your program like this:
void DiagrammWidget::paintEvent(QPaintEvent *event)
{
QPainter myPainter (this);
if( m_punkte == nullptr || m_punkte->empty() ){
// myPainter.drawText(100,100,"No Points found!");
return;
}
auto startPunkt = m_punkte->begin();
for( auto it = ++(m_punkte->begin()); it != m_punkte->end(); ++it){
auto const& p = *it;
myPainter.drawLine(startPunkt->temperatur,startPunkt->laenge,
p.temperatur,p.laenge);
startPunkt = it;
}
}
You see that this properly protects against your allowed condition of a null pointer or an empty container before making assumptions about the contents of the container. It also uses iterators as intended, rather than making unnecessary copies of the elements of the container.
Related
I have been working with a vector and I receive this error:
No matching member function for call to 'push back'
Can anyone take a look at my code to detect my mistakes?
bubble_jar.h
#include "abstract_bubble.h"
#include "bubbles.h"
#include <vector>
#include "cpputils/graphics/image.h"
#ifndef BUBBLE_JAR_H
#define BUBBLE_JAR_H
class BubbleJar : public graphics::MouseEventListener,
public graphics::AnimationEventListener {
public:
~BubbleJar();
void Initialize(int max_age);
void Start();
void OnMouseEvent(const graphics::MouseEvent& event) override;
void OnAnimationStep() override;
graphics::Image* GetImageForTesting() { return &image_; }
private:
graphics::Image image_;
int max;
std::vector<std::unique_ptr<AbstractBubble>> ab;
};
#endif // BUBBLE_JAR_H
bubble_jar.cc
void BubbleJar::OnMouseEvent(const graphics::MouseEvent& event) {
std::cout << "BubbleJar got a MouseEvent" << std::endl;
// Create a BigBubble on mouse press and a SmallBubble on mouse release
// and add them to the vector.
if (event.GetMouseAction() == graphics::MouseAction::kPressed) {
BigBubble b(event.GetX(), event.GetY(), &image_);
ab.push_back(b);
b.Draw();
}
else if ( event.GetMouseAction() == graphics::MouseAction::kReleased ) {
SmallBubble s(event.GetX(), event.GetY(), &image_);
ab.push_back(s);
s.Draw();
}
image_.Flush();
}
Your std::vector holds std::unique_ptr smart pointers to AbstractBubble-derived objects, but you are trying to push actual derived objects, not smart pointers to derived objects, hence the push_back() error due to a type mismatch.
Try this instead:
void BubbleJar::OnMouseEvent(const graphics::MouseEvent& event) {
std::cout << "BubbleJar got a MouseEvent" << std::endl;
// Create a BigBubble on mouse press and a SmallBubble on mouse release
// and add them to the vector.
if (event.GetMouseAction() == graphics::MouseAction::kPressed) {
auto b = std::make_unique<BigBubble>(event.GetX(), event.GetY(), &image_);
ab.push_back(std::move(b));
b->Draw();
}
else if ( event.GetMouseAction() == graphics::MouseAction::kReleased ) {
auto s = std::make_unique<SmallBubble>(event.GetX(), event.GetY(), &image_);
ab.push_back(std::move(s));
s->Draw();
}
image_.Flush();
}
Hi I have a class for generate MD5 of some file in Qt, (I use tuple to return multiple value from it), I want to run it on other thread because its possible that generate all file MD5s takes some time and its freeze gui
I decide to use QtConcurrentRun for run it on other Thread, but so far I don't have any Idea about How can I get all tuple return values
here is my code
HashGen.h
#pragma once
#include "stdafx.h"
class HashGen : public QObject
{
Q_OBJECT
public:
HashGen(QObject *parent = nullptr);
private:
QString Md5_gen(QString const& fname);
public slots:
std::tuple<int, int, int> check_sequential();
};
HashGen.cpp
#include "stdafx.h"
#include "HashGen.h"
HashGen::HashGen(QObject *parent)
: QObject(parent)
{
}
QString HashGen::Md5_gen(QString const& fname)
{
//Generate MD5 of giving file name
}
std::tuple<int, int, int> HashGen::check_sequential() {
QString file1[2] = { "8c0b1e6492078bdc113faae3d34fa5c5", "" }; // empty "" fill with other MD5 hash later
QString file2[4] = { "0547f42982dd9edb7b47931d00efff15", "", "", "" };
QString file3[2] = { "57f08e690e2655749291b2da4be8b021", "" };
QString file1_H = Md5_gen("/proj/file.zip");
QString file2_H = Md5_gen("/proj/file2.zip");
QString file3_H = Md5_gen("/proj/file3.zip");
int file1_status = 0;
int file2_status = 0;
int file3_status = 0;
for (int i = 0; i < 2; i++)
{
if (file1[i] != "nofile")
{
if (file1[i] == file1_H)
{
file1_status = i;
break;
}
else { file1_status = 422; } // Just a random number mean file doesn't match any MD5
}
else
{
file1_status = 404; // Just a random number mean file doesn't exist
break;
}
}
for (int i = 0; i < 4; i++)
{
if (file2[i] != "nofile")
{
if (file2[i] == file2_H)
{
file2_status = i;
break;
}
else { file2_status = 422; }
}
else
{
file2_status = 404;
break;
}
}
for (int i = 0; i < 2; i++)
{
if (file3[i] != "nofile")
{
if (file3[i] == file3_H)
{
file3_status = i;
break;
}
else { file3_status = 422; }
}
else
{
file3_status = 404;
break;
}
}
return { file1_status, file2_status, file3_status}; // Return all file status
mainwindow.cpp
void mainwindow::on_pushButton_clicked()
{
QFuture<std::tuple<int, int, int>> Hash = QtConcurrent::run(Gen, &HashGen::check_sequential);
QFutureWatcher<std::tuple<int, int, int>>* watcher = new QFutureWatcher<std::tuple<int, int, int>>;
connect(watcher, &QFutureWatcher<std::tuple<int, int, int>>::finished, this, &MafiaDEDLFox::AfterHash);
watcher->setFuture(Hash);
}
one other problem is I need to use QFuturewatcher to watch for QFuture, but I don't know where is best place to declare it (so its don't remove when function go out of scope)
sorry if I cant explain my problem right, but I hope someone help me, thanks
Instead of getting value from QFutureWatcher you can send it via signal. And we can create a disposable QFutureWatcher that delete itself when the job done.
class HashGen : public QObject
{
Q_OBJECT
public:
HashGen(QObject *parent = nullptr);
private:
QString Md5_gen(QString const& fname);
public slots:
std::tuple<int, int, int> check_sequential() {
...
// notify when completed
emit check_sequential_completed(file1_status, file2_status, file3_status);
return { file1_status, file2_status, file3_status}; // Return all file status
}
void async_check_sequential() {
// create future watcher as child
auto futureWatcher = new QFutureWatcher<void>(this);
// kill yourself when you done
connect(futureWatcher, &QFutureWatcher<void>::finished, futureWatcher, &QObject::deleteLater);
// Wait for finish of computation when HashGen about to die
connect(this, &QObject::destroyed, [futureWatcher](){ futureWatcher->waitForFinished(); });
// start check sequential in another thread
futureWatcher.setFuture(QtConcurrent::run(this, &HashGen::check_sequential));
}
signals:
void check_sequential_completed(int, int, int);
};
Connect check_sequential_completed to slot where you need.
connect(Gen, &HashGen::check_sequential_completed, this, &MafiaDEDLFox::AfterHash);
You don't have to make future watcher disposable of course. If you find it inefficient to create new object every time, you can keep it as member of HashGen.
Note:
Instead of passing 3 int atguments, it is possible to send std::tuple<int, int, int>. You have to register meta type for queued connections which is a connection type used in interthread connections.
Q_DECLARE_METATYPE(std::tuple<int, int, int>);
qRegisterMetaType<std::tuple<int, int, int>>();
Edit1:
QFutureWatcher<std::tuple<int,int,int>> replaced by QFutureWatcher<void>, no need store result in this solution.
Edit2:
Connection added that waits for asynchronous computation to finish, when HashGen object destroyed. So threads won't keep running on a dead object. But it will block the main thread for a while when HashGen destroyed. Actually that's the whole point of using QFutureWatcher, otherwise if you are sure there will be no asynchronous computation when destroying HashGen object, no need to use QFutureWatcher. Just QtConcurrent::run is suffice.
Example Using Only QtConcurrent::run
Following code snipped is from an actual working project.
class AddPrinterInvoker : public QObject
{
Q_OBJECT
public:
AddPrinterInvoker(QObject* parent = nullptr);
QStringList scanAddresses() {
...
emit addressListReady(addressList);
return addressList;
}
public slots:
void asyncScanAddresses() { QtConcurrent::run(this, &AddPrinterInvoker::scanAddresses); }
signals:
void addressListReady(QStringList addressList);
}
Connections
connect(scanButton, SIGNAL(clicked()), m_invoker, SLOT(asyncScanAddresses()));
connect(m_invoker, SIGNAL(addressListReady(QStringList)), this, SLOT(updateAddressList(QStringList)));
Im trying to write a class that stores an id and a value in an container class.
Im using an nested class as my data structure.
When im compiling the code sometimes it prints perfectly, sometimes it prints nothing and sometimes it prints half of the data then stops.
When i debug the code the same weird behavior occours, when it fails during debug it throws an error "Map.exe has triggered a breakpoint.", the Error occours in the print method when im using cout.
cmap.h
#pragma once
class CMap
{
public:
CMap();
~CMap();
CMap& Add(int id, int value);
void print() const;
private:
class container
{
public:
~container();
int container_id = 0;
int container_value = 0;
};
container* p_komp_;
int dim_ = -1;
void resize();
};
cmap.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
CMap::CMap()
{
p_komp_ = new container[0];
}
CMap::~CMap()
{
p_komp_ = nullptr;
cout << "destroy cmap";
}
CMap& CMap::Add(int id, int value)
{
resize();
p_komp_[dim_].container_id = id;
p_komp_[dim_].container_value = value;
return *this;
}
void CMap::resize()
{
container* temp_array = new container[++dim_];
if (dim_ == 0)
{
temp_array[0].container_id = p_komp_[0].container_id;
temp_array[0].container_value = p_komp_[0].container_value;
}
for (unsigned i = 0; i < dim_; i++)
{
temp_array[i].container_id = p_komp_[i].container_id;
temp_array[i].container_value = p_komp_[i].container_value;
}
p_komp_ = temp_array;
}
void CMap::print() const
{
for (unsigned i = 0; i <= dim_; i++)
{
cout << p_komp_[i].container_id;
cout << p_komp_[i].container_value;
}
}
CMap::container::~container()
{
cout << "destruct container";
}
Map.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
void main(void)
{
CMap m2;
m2.Add(1, 7);
m2.Add(3, 5);
m2.print();
}
These two things are a possible reason for your problem:
int dim_ = -1;
and
container* temp_array = new container[++dim_];
When you allocate, you increase dim_ from -1 to 0. That is you create a zero-sized "array", where every indexing into it will be out of bounds and lead to undefined behavior.
You also have memory leaks since you never delete[] what you new[]. I didn't look for more problems, but there probably a more.
And an "array" (created at compile-time or through new[]) will have indexes from 0 to size - 1 (inclusive). You seem to think that the "size" you provide is the top index. It's not, it's the number of elements.
It seems to me that you might need to take a few steps back, get a couple of good books to read, and almost start over.
Consider this problem.
I have a QLineEdit in my tool and I should organize a support as follows. The text of LineEdit must contain only double values, separated my comas.
F.e. 6.2 , 8, 9.0, 55
I also must validate, that user cannot input any other character but the numbers and comas. Also I should write a method which convert this text into vector.
Initially I thought about QRegExp and boost::spirit. But it can be hard using these technique.
Any ideas?
Use next custom Validator.
Header:
#ifndef VALIDATOR_H
#define VALIDATOR_H
#include <QValidator>
class Validator : public QValidator
{
Q_OBJECT
public:
explicit Validator(QObject *parent = 0);
signals:
public slots:
public:
QValidator::State validate(QString & input, int & pos) const;
};
#endif // VALIDATOR_H
Cpp:
#include "validator.h"
#include <QDoubleValidator>
#include <QDebug>
Validator::Validator(QObject *parent) :
QValidator(parent)
{
}
QValidator::State Validator::validate(QString &input, int &pos) const
{
qDebug() << input<< pos;
QDoubleValidator val;
val.setLocale(QLocale(QLocale::German,QLocale::Germany));
input.remove(" ");
QStringList list = input.split(",");
foreach ( QString var, list) {
int i = 0;
if(val.validate(var,i) == QValidator::Invalid)
return QValidator::Invalid;
}
return QValidator::Acceptable;
}
Usage:
ui->lineEdit->setValidator(new Validator);
Explanation about: val.setLocale(QLocale(QLocale::German,QLocale::Germany));
You said that you want use 6.2,... but . and , is different decimal point in different countries. So I wrote example accordingly to your question. German Locale always think that . is a correct point.
But I recommend you to use locale-specific decimal point and use for this Purpose ; as separator instead of coma.
There are mistakes, so try this. Edit(improved):
QValidator::State Validator::validate(QString &input, int &pos) const
{
qDebug() << input<< pos;
QRegExpValidator reg(QRegExp("[0-9]+(\\.[0-9]+)?$"));
input.remove(" ");
if(input.contains(",,") || input.startsWith(","))
return QValidator::Invalid;
QStringList list = input.split(",");
qDebug()<< list;
bool isOk = true;
foreach ( QString var, list) {
int i = 0;
if(reg.validate(var,i) == QValidator::Invalid)
return QValidator::Invalid;
if(reg.validate(var,i) == QValidator::Intermediate)
isOk = false;
}
if(isOk)
return QValidator::Acceptable;
else
return QValidator::Intermediate;
}
Hey guys I am trying to make the following slot: The user should input a sequence of numbers in a line edit with spaces between them (for example: 5 10 15 10 2) I want these numbers to be stored into a vector of integers. After they are all read, I want the values of the vector to be changed in the following way - starting from the second element up to the end, every element should be equal to the following: vector[i] = vector[i] - vector[i-1]. Again, this doesn't count for the first one. I will do some more computing, but It would appear that I can't get this done quite right yet.
The layout is the following: a button, a lineEdit and a Label.
This is the header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVector>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QVector<int> vec;
private slots:
void compute();
};
#endif // MAINWINDOW_H
And the implementation:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->lineEdit
, SIGNAL(editingFinished()), this, SLOT(compute()));
connect(ui->pushButton
, SIGNAL(pressed()), this, SLOT(compute()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow :: compute()
{
// Read user input
QString numbers = ui->lineEdit->text();
QString tmp; // create temp string which will be used to store the temp substrings of each int
numbers+=" ";
for(int i = 0; i < numbers.length()-1; i++)
{
if(numbers[i].isDigit())
{
tmp +=numbers[i];
}
else
{
bool ok = true;
int iTime = tmp.toInt(&ok, 10);
vec.push_back((iTime));
tmp="";
}
}
//compute the real vector that we will search the max subarray from
for(int i = 1; i < vec.size(); i++)
{
vec[i] = vec[i] - vec[i-1];
}
int tt = 0;
for(int z = 0; z != vec.size(); z++)
{
tt+= vec[z];
}
ui->label->setText( QString::number(tt));
}
I won't post the main function since it is the standard one when you create a Qt GUI aplication. So, the problem is, the following line: ui->label->setText( QString::number(tt)); always prints zero to the label. I made this program in code blocks, without the Qt GUI libraries and I got it working. I am intrigued where the problem is. Thanks in advance.
for(int z = 0; z != vec.size(); z++)
Should be:
for(int z = 0; z < vec.size(); z++)