QString als char* übergeben

Alles rund um die Programmierung mit Qt
Antworten
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

QString als char* übergeben

Beitrag von Marcus Breuer »

Hallo Programmierer,

ich habe eine für Euch wohl schon nervige Frage. Und zwar möchte ich aus einer Oberfläche einen QString den ich über QFileDialog::getOpenFileName(...)
erhalten habe in einen char* konvertieren.
Ich habe bereits versucht den QString file in einQByteArray zu überführen, jedoch klappte das mit Nichten. Ich habe zwar hier und da mal kompilierbaren Code erhalten, jedoch hat dieser auch nicht im geringsten das getan, was ich wollte.

Ich habe mir die Referenz des QByteArray angeschaut und dachte, da ein QString, so wie ich es gelesen und meine verstanden zu haben im Unicode als const char* gespeichert wird, dass ich auch den Konstrukter QByteArray ( const char * str ) benutzen könnte und diesem dann den QString file übergebe um dann mit data() entsprechend das QByteArray zu füllen. Kein Erfolg.

Ich bitte Euch daher um Hilfe, die ich auch als Programmierneuling verstehen kann.

Der Code um den es sich dreht:

Code: Alles auswählen

#include "mainwindow.h"
#include <QByteArray>



Hauptfenster::Hauptfenster() {
    setupUi(this);


    //Signal-Slot-Verbindungen
    //Menü
    connect ( actionQuit, SIGNAL(triggered(bool)),
              qApp, SLOT(quit()));
    connect ( actionOpen, SIGNAL(triggered(bool)),
              this, SLOT(openFile()));
    //Button

    connect (OpenButton, SIGNAL(clicked()),
             this, SLOT(openFile()));
    connect ( QuitButton, SIGNAL(clicked()),
              qApp, SLOT (quit()));
    connect (OpenButton, SIGNAL (clicked()),
             this, SLOT(fill()));


}

//Funktionen
void Hauptfenster::openFile() {
    QString file = QFileDialog::getOpenFileName(
            this, "Please select datafile",
            QDir::homePath(), "Data(*.txt)");
//Hier habe ich Einiges probiert, jedoch nichts Sinnvolles scheinbar.
//Und von hier aus soll dann der file an die void::Atom Einlesen(char*)
//übergeben werden

}

und die Datei die ein char* übergeben bekommen soll:

Code: Alles auswählen

#include "Atom.hpp"

Atom::Atom() {}
void Atom :: Einlesen(char* dateiname){
double x;
string i;
ifstream infile(dateiname);
char c;

while(infile.get(c)){  //so lange,bis der Text vollständig eingelesen wurde

for(int k =0; k<2; k++){ 
infile >> i;}

// Zeitschritt einlesen
infile >> Timestep ;

for(int k=0; k<4; k++){
infile >> i;}
  
// Anzahl der Atome
infile >> Number;
  
//Überspringen unnötiger Wörter
for( int k=0; k<3; k++){
infile >> i;}

// Boxmaßen einlesen
infile >>BBX1;
infile >>BBX2;
infile >>BBY1;
infile >>BBY2;
infile >>BBZ1;
infile >>BBZ2;

 //Überspringen unnötiger Wörter
for( int k=0; k<10; k++){
	infile >> i;
}
int id;
int type;
double xs;
double ys;
double zs;
int ix;
int iy;
int iz;
for (int i = 0; i < Number; i++)
 {
	infile >> id;
	infile >> type;
	infile >> xs;
	infile >> ys;
	infile >> zs;
	infile >> ix;
	infile >> iy;
	infile >> iz;
	// Create position vector 
	vector<double> single_position;
	vector< vector<double> > all_positions;
	single_position.push_back(xs);
	single_position.push_back(ys);
	single_position.push_back(zs);
	single_position.push_back(ix);
	single_position.push_back(iy);	
	single_position.push_back(iz);
	
	//Typ speichern
	type_map.insert(pair<int,int>(id,type));
	
	// Wenn das Atom noch nicht existiert, dann häng es an die map
	if (atom_map.find(id) == atom_map.end())
	{
		all_positions.push_back(single_position);
		atom_map.insert(pair<int, vector< vector<double> > >(id, all_positions));
	}

	// Wenn es bereits existiert, muss es aktualisiert werden
	else
	{
		all_positions = atom_map.find(id)->second; // get vector of vectors out of map
		all_positions.push_back(single_position); // add new position to vector
		atom_map.erase(atom_map.find(id)); // Erase old vector of vectors
		atom_map.insert(pair<int, vector< vector<double> > >(id, all_positions)); // Add updated vector of vectors

	}
}

}
b = true;
};


int Atom::get_Number(){
if(b){
//cout << Number;
return Number;}
else{
cout << "read-in first" << endl;}
};


//evtl l&#154;schen
double Atom::get_box_min_x(){
if(b){
return BBX1;}
else{
cout << "read-in first" << endl;}
};

double Atom::get_box_max_x(){
if(b){
return BBX2;}
else{
cout << "read-in first" << endl;}
};

double Atom::get_box_min_y(){
if(b){
return BBY1;}
else{
cout << "read-in first" << endl;}
};

double Atom::get_box_max_y(){
if(b){
return BBY2;}
else{
cout << "read-in first" << endl;}
};

double Atom::get_box_min_z(){
if(b){
return BBZ1;}
else{
cout << "read-in first" << endl;}
};

double Atom::get_box_max_z(){
if(b){
return BBZ2;}
else{
cout << "read-in first" << endl;}
};

vector<int> Atom:: get_id(){
return v_id;

};
Ich habe eine Instanz von Atom, its_atom in einer anderen Datei angelegt, auf die ich über #include "mainwindow.h" zugriff habe.

Ich bedanke mich für jede Hilfe.

Besten Gruß,
Marcus
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

soweit ich sehe benötigst du keinen char*, sondern einen "const char *":

Code: Alles auswählen

void Atom :: Einlesen(const char* dateiname)
{
...
ifstream infile(dateiname); 
...
und danach der Aufruf:

Code: Alles auswählen

Atom a;
QString filename = .....
a.Einlesen(filename.toAscii().constData());
Das geht natürlich nur, weil der Pointer nur während des Einlesens benötigt wird.. der darf auf keinen Fall in der Atom-Klasse gespeichert werden..!

hth..
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Ich habe hier mal noch etwas, ich nehme es in Kauf, dafür sehr viel Schelte zu bekommen geschrieben, was sich zwar kompilieren lässt, aber scheinbar dennoch nicht das tut, was ich will. Könnt Ihr Euch das mal ansehen?

Code: Alles auswählen

void Hauptfenster::openFile() {
    QString file = QFileDialog::getOpenFileName(
            this, "Please select datafile",
            QDir::homePath(), "Data(*.txt)");
   const QChar* str_to_chr = file.data();
   char final = str_to_chr->toAscii();
   char * ptr_to_final = &final;
   its_atom.Einlesen(ptr_to_final);
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Hallo solarix,

habe deine Antwort leider erst nach meinem zweiten Post gesehen. Kannst Du mal einen blick darauf werden? Also liegt der hund wohl da begraben, dass das Argument in der Funktion void::Atom Einlesen(char* dateiname) ein const *char sein muss? Folge ich Dir richtig?

Danke für deine schnelle Antwort.
ScyllaIllciz
Beiträge: 200
Registriert: 9. Juli 2010 19:31

Beitrag von ScyllaIllciz »

Lies mal hier. Da sollte alles notwendige erklärt sein!
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Nein, du kannst schon auch mit char* arbeiten, aber das wird bei C++ nur so gemacht, wenn man in der Methode die Daten verändern möchte, was bei dir keinen Sinn macht... daher das "const".. es ist sauberer.

Code: Alles auswählen

QString file = QFileDialog::getOpenFileName(
            this, "Please select datafile",
            QDir::homePath(), "Data(*.txt)");
  
   its_atom.Einlesen(file.toAscii().data()); // char* - Variante (Einlesen(char*))
  
  oder 

  its_atom.Einlesen(file.toAscii().constData()); // const char* - Variante (Einlesen(const char*))
hth..
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Ok, super. Vielen Dank. Ich werde das jetzt mal umsetzen. Wenn ich Dir noch eine andere Funktion zeigen darf. Ich habe Sie selbst nicht geschrieben. Zum Kontext, wir erhalten eine Datei in der Atome mit den IDs bspw. von 25952 bis 25963 angelegt sind. Diese IDs sollen in einer QComboBox zur Auswahl stehen.
Wenn Ich nun den obigen Code, so wie Du ihn mir geschickt hast implementiere, liest er ja die Datei ein.

Wenn Du mir dies bezüglich nur einen Tipp geben kannst, keinen fertigen Quellcode, denn ich will mich dann selber dransetzen und ihn schreiben, ob
die ComboBox dann auch tatsächlich gefüllt wird, dann wüsste ich, wo ich bei einem Fehler weitermachen muss.

Die Funktion:

Code: Alles auswählen

void Hauptfenster::fill() {
    comboBox->clear();
    vector<int> atom_ids = its_atom.get_id();
    for(int i = 0; i < atom_ids.size(); i++) {
        QString f;
        QVariant var;
        var.setValue(atom_ids[i]);
        f.setNum(atom_ids[i]);
        comboBox->addItem(f, var);
    }
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Naja.. also wenn du den Code schon hier reinschreibst könntest du ebenso gut einfach das Programm starten und schauen, ob es funktioniert :wink:

Aber es sieht halbwegs sinnvoll aus.. ich würde es etwas knackiger schreiben

Code: Alles auswählen

for(int i = 0; i < atom_ids.size(); i++)
   comboBox->addItem(QString::number(atom_ids[i]),atom_ids[i]);
aber das muss jeder selbst entscheiden :)

hth!
Marcus Breuer
Beiträge: 113
Registriert: 31. März 2011 17:19
Wohnort: Aachen
Kontaktdaten:

Beitrag von Marcus Breuer »

Ok, das stimmt. Aber dennoch super, dass Du eine Einschätzung gemacht hast. Ich werde mir mal noch den Debug-Modus von Qt.

Habe es aber gerade mal probiert, aber leider füllt sich die ComboBox nicht. Dann kann es im Grunde nur daran liegen, dass die Datei, die ich ausgewählt habe nicht richtig eingelesen wurde.

So eine Tüftelei, nur um ein paar Professoren glücklich zu machen:)
Antworten