[gelöst] Typprobleme mit ifstream

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
AQtNewbie
Beiträge: 23
Registriert: 1. Oktober 2012 13:03

[gelöst] Typprobleme mit ifstream

Beitrag von AQtNewbie »

Hallo!

Ich habe eine Klasse mit einem Setter namens setPath(const char* pathName);.
Ich möchte nun via Texteingabe vom Benutzer den Pfadnamen einlesen und anschließend "weiterverwenden" (z.B. nutzt eine andere Methode die Variable pathName um daraus die Dateien zu lesen und in eine Liste zu schreiben).

Mein Problem liegt hier:

Code: Alles auswählen

void eineKlasse::setPath(const char* pathName)
{
    std::ifstream path; //type of path for in-stream
    std::cout << "Dateipfad? ";
    std::cin >> pathName; // hier liegt das Problem
    path.open(pathName, std::ios::in);

    if (!path)
    {
    std::cerr << pathName << " unable to open!\n";
    exit(-1);
    }

    this->m_pathName = pathName;
    path.close();
}
Genau hier meckert der Compiler.
Er kann const char*nicht nehmen. Was auch irgendwie verständlich ist.
Das Problem ist nur, open(chonst char*, flags) ist so vorgegeben; Ich benötige folglich einen const char*.

Gibt es eine Möglichkeit (außer c_str()!! Da mein Programm auf "sehr viele Dateien" ausgelegt ist, erscheinen etliche Kopien dabei nicht unbedingt günstig) dieses Typproblem zu lösen?

Grüße
AQtNewbie
Zuletzt geändert von AQtNewbie am 9. November 2012 12:22, insgesamt 1-mal geändert.
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Typproblem mit ifstream

Beitrag von brax »

Du wirst einen const wohl kaum verändern können. Warum überhaupt der Parameter an setPath ist, wenn in der Methode der Pfad eh von der Konsole gelesen werden soll ist auch etwas zweifelhaft. Wenn Du open einen nicht const char* gibst, ist das auch voll ok (ein nicht const-Ding kann locker zu einem const-Ding gemacht werden, andersrum eher nicht...). Warum benutzt Du nicht einfach sowieso die Qt-API dafür? Da Du hier in einem Qt-Forum bist, nehme ich an, dass Du in Deinem Projekt auch Qt benutzt. Also benutze doch einfach das, was QFile Dir bietet und dazu dann QStrings und verzichte auf ifstream...

Das ganze in einen std::string zu lesen und dann c_str zu benutzen ist übrigens kein Overhead. Es ist zwar im Standard nicht festgelegt, aber alle gängigen Compiler (also gcc, MSVC und Clang) legen bei c_str ziemlich sicher keine Kopie an sondern geben direkt einen Zeiger auf den internen Puffer des std::strings zurück.
AQtNewbie
Beiträge: 23
Registriert: 1. Oktober 2012 13:03

Re: Typproblem mit ifstream

Beitrag von AQtNewbie »

Ich programmiere hauptsächlich mit C++, damit die Darstellung lediglich auf Qt fällt.
Ich dachte mir, wenn eine Methode (via Benutzereingabe) einen Pfad setzt, nur damit eine andere Methode ihn benutzt, muss ich kein Qt reinbauen... *am Kopf kratz*

Aber danke für den c_str()-Hinweis! Aus einigen Beschreibungen habe ich leider das mit der Kopie herausgelesen, und wollte diese Methode dahergehend nicht benutzten.
AQtNewbie
Beiträge: 23
Registriert: 1. Oktober 2012 13:03

Re: Typproblem mit ifstream

Beitrag von AQtNewbie »

Hier übrigends meine Lösung:

Code: Alles auswählen

void eineKlasse::setPath(std::string pathName)
{
    //define and open a path
    std::ifstream path; //type of path for in-stream
    std::cout << "Dateipfad? ";
    std::cin >> pathName;
    path.open(pathName.data(), std::ios::in);
    if (!path)
    {
    std::cerr << pathName << " unable to open!\n";
    exit(-1);
    }

    this->m_pathName = pathName;
    path.close();
}
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Typproblem mit ifstream

Beitrag von brax »

Wenn das so funktioniert ist ja schön, aber ein wichtiger Unterschied zwischen std::string::data() und std::string::c_str() ist, dass data() keinen Null-terminierten char* zurückgibt!
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Typproblem mit ifstream

Beitrag von RHBaum »

<klugescheissmodus on>
dass data() keinen Null-terminierten char* zurückgibt!
Ui, das ist boese !
Richtig ist:
Man darf sich nicht drauf verlassen, das data() einen Null-terminierten char* zurückgibt!

Ansonsten widerspricht Dir jeder Neueinsteiger in mindestens 80% der Fälle sofort ! weil data() kann einen Null-terminierten char* zurueckgeben, und in allen meinen Impls die ich hier hab, tut es das auch ^^
<klugescheissmodus off>

Iss auch leicht zu erklären, wenn data() keine \0 am ende haben darf, und c_str() eine am ende haben muss ... muss man 2 mal den string halten, oder expliziet cachen ...
Egal wie, c_str() wuerde damit zu unperformance führen ...

Ciao ...
AQtNewbie
Beiträge: 23
Registriert: 1. Oktober 2012 13:03

Re: Typproblem mit ifstream

Beitrag von AQtNewbie »

Ich habe leider nochmal ein Problem, diesmal mit dem Debugger in Qt und eben dieser Konvertierung :|
Ohne den Debugger wird alles gefressen und ausgegeben, wie ich es möchte, aber mit dem Debugger...

Code: Alles auswählen

//get user input
    QString path = ui->lineEdit->text();

    //there is a need to convert QString into const char* to use opendir(const char*);
    const char* newPath = (path.toStdString()).data(); // in dieser zeile habe ich bereits path.toAscii().data(); und path.toLatin1().data(); ausprobiert
    std::cout << newPath << std::endl;
cout Ausgabe (nur beim Debuggen!) immer :
îþîþîþîþîþîþîþîþîþîþîþîþîþîþ;È4 PÂ

:?: :?:
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Typproblem mit ifstream

Beitrag von RHBaum »

const char* newPath = (path.toStdString()).data();
path.toStdString() liefiert dir einen std::string
data holt dir den internen Zeiger aus dem String ...
Leider merkst du dir den std:string nicht, sondern verwendest den temporaer
D.H. wenn der Spuk deines Aufrufes zuende ist, ist dein temporaeres Objekt auch weg und dein Zeiger (newPath) zeigt ins Nirvana (in nen Object was es nicht mehr gibt) !

der unterschied in der laufzeit scheint daher zu kommen, das du einmal im Debug modus laeufst .... da wird der compiler dir deinen Freigegebenen speicher ueberschreiben und es sieht Sch.... aus.
Im Release Modus macht er das aus Performancegruenden nicht und es sieht aus als wuerde funktionieren, aber in Wirklichkeit ist dein verhalten unbestimmt !

Warum um Himmelswillen willst DU dir den rohen zeiger merken ??? zu einem Rohen zeiger gehoert immmer irgendwas, was die Daten auch halten muss !!!
besser DU haelst dir zeigs was daten auch halten kann und erzeugst den zeiger nur auf bedarf !!!

BTW. ists besser bei QString zu char * konvertierung QByteArray statt std::string als Holder zu verwenden ! STL Support muss nicht immer eingeschalten sein und ist in wenigen Fällen problematisch ....
Also besserer Weg !

Code: Alles auswählen

      QString path = ui->lineEdit->text();
      //there is a need to convert QString into const char* to use opendir(const char*);
      QByteArray newPath = path.toAscii(); // 
      std::cout << newPath.constData() << std::endl;
Und sag nich das funktioniert nicht, sonst muesste ich tonnenweisse code wegwerfen ! ^^

Ciao ...
AQtNewbie
Beiträge: 23
Registriert: 1. Oktober 2012 13:03

Re: Typproblem mit ifstream

Beitrag von AQtNewbie »

Vielen, vielen Dank!
Deine Erklärung hat mir sehr geholfen das Problem, das ich da angestellt habe, zu verstehen!
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Typproblem mit ifstream

Beitrag von RHBaum »

C/C++ ist ne Sprache wie Englisch ...
Man sagt, man hat Englisch einigermassen drauf, wenn man in englisch träumt.

mit C/C++ ist es ähnlich, nur wird man ned in C träumen, das sähe komisch aus :-) sondern das Unterbewusstsein greift da anders:
Immer wenn DU einen Zeiger siehst, müssen intuitiv die Fragen kommen,
- wo zeigt das Ding hin ?
- wer hält die Daten ?
- ergo: wie lange ist der Zeiger fuer mich gültig !

Ciao ...
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Typproblem mit ifstream

Beitrag von brax »

RHBaum hat geschrieben: Man darf sich nicht drauf verlassen, das data() einen Null-terminierten char* zurückgibt!
Hast recht, die Aussage war unzureichend genau. Im C++ Standard (sowohl 03 als auch 11) ist das nicht weiter spezifiziert und Du hast auch recht, dass wohl kaum ein Compiler einen Unterschied zwischen data() und c_str() macht.
Antworten