richtige Verwendung von getline()



  • Hallo mal wieder!

    Ich habe folgendes Problem:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void CCrypt::WriteIn()
    {
    	getline( cin, In ); //laut meinem Buch sollte damit
     eine ganze Zeile eingelsesn 
    }
    

    Fehlermeldung: 1>d:\verschlüsselung\verschlüsselung\verschlüsselung\klasse.cpp(90) : error C3861: "getline": Bezeichner wurde nicht gefunden.



  • Sorry hab mich leider vertippt daher das Fragment da oben!

    Ich habe folgendes Problem:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    //Methode meiner Klasse
    void CCrypt::WriteIn()
    {
        getline( cin, In ); //laut meinem Buch sollte damit
                       //eine ganze Zeile eingelesen werden können
    }
    

    Allerdings bekomme ich diese Fehlermeldung:
    1>d:\verschlüsselung\verschlüsselung\verschlüsselung\klasse.cpp(90) : error C3861: "getline": Bezeichner wurde nicht gefunden.

    Eigentlich soll aber mehr als eine Zeile eingelesen werden.
    Wie muss ich getline() [oder etwas in der Art] richtig verwenden damit der Anwender einen beliebig langen Text eingeben kann, welcher dann in dem string In gespeichert wird?

    Falls mehr Infos benötigt werden kann ich auch noch was nach posten.
    Danke schon mal im voraus! 🙂



  • Öhm, cin.getline?

    Gruß



  • Der so gepostete Code ist komplett richtig. Der Fehler wird woanders sein.



  • Bei mir funkst es wie so oft wunderbar.

    string s;
    
    	std::getline(cin, s);
    
    	cout << s << endl;
    

    Von daher scheint das Problem woanders zu liegen.
    Vielleicht geht ja die von Crisber angegebene Methode.



  • Also bei dieser Variante:

    void CCrypt::WriteIn()
    {
    	cin.getline(In,2000);
    }
    

    diese Fehlermeldung:

    1>d:\verschlüsselung\verschlüsselung\verschlüsselung\klasse.cpp(90) : error C2664: 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::getline(_Elem *,std::streamsize)': Konvertierung des Parameters 1 von 'std::string' in 'char *' nicht möglich

    Ich nutze übrigens Visual Studio 2008 EE hat vllt schon mal jemand von euch diesen Fehler damit gehabt? 😕



  • diesen fehler?

    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      string out;
      getline(cin, out);
    }
    

    kompiliert bei dir nicht? das würd ich mal bezweifeln wollen...

    bb



  • @unskilled
    in der main klappt das aber in der Methode nicht...

    hier die Fehlermeldung:
    1>d:\verschlüsselung\verschlüsselung\verschlüsselung\main.cpp(9) : error C3861: "getline": Bezeichner wurde nicht gefunden.


  • Administrator

    @Guest Brain,
    Zeig mal einen kurzen Code, ähnlich wie unskilled es gemacht hat, wo du diesen Fehler erhalten hast.

    Ich würde ganz schlicht mal behaupten, dass du vergessen hast, ein #include <string> hinzuschreiben.

    Grüssli



  • Vielleicht solltest du mal deinen ganzen Klassencode posten.
    Vielleicht fehlt ne Header oder irgendwas wird an der falschen Stelle eingebunden 🙄



  • Die Header Datei, das Ganze soll ein Klasse werden mit der .txt Dateien ver- und entschlüsselt werden können:

    #ifndef CRYPT_H
    #define CRYPT_H
    
    using namespace std;
    
    class CCrypt
    {
    private:
    
    	string Status;  //String für Statusmeldungen
    	string Key;	//chiffrier Schlüssel
    	string In;	//eingelesener String 
    	string Out;	//ausgelesener String
    
    	FILE *InData;	//einzulesende Datei
    	FILE *OutData;	//auszugebende Datei
    
    	bool InDataFlag;	//Zum Prüfen der Dateizeiger
    	bool OutDataFlag;	
    
    public:
    	CCrypt();
    	CCrypt(string InPath, string OutPath);
    	~CCrypt();
    
    	void Menue();
    
    	void WriteIn();
    
    	int OpenInData(string sPath);	//Quelldatei öffnen
    	int OpenOutData(string sPath);	//Zieldatei öffnen
    
    	void CloseInData();		//InData schließen
    	void CloseOutData();	//OutData schließen
    
    	void ReadData();	//Daten aus InData nach In einlesen
    	void WriteData();	//Daten nach OutData von Out schreiben
    
    	void PrintIn();		//In und Out strings anzeigen
    	void PrintOut();
    
    };
    
    #endif
    

    Die Cpp Datei:

    #include <iostream>
    #include <string.h>
    
    #include "Klasse.h"
    
    using namespace std;
    
    CCrypt::CCrypt()
    {	
    	Status = "keine Meldung";
    
    }
    
    CCrypt::~CCrypt()
    {
    
    }
    
    void CCrypt::Menue()
    {
    	int x = 0;
    	int loop = true;
    	char Name[200];
    	string Str;
    
    	do
    	{
    
    		cout<<"Menue"<<endl
    			<<"Aktuelle Eingabe anzeigen...(1)"<<endl
    			<<"Aktuelle Ausgabe Anzeigen...(2)"<<endl
    			<<"Texteingabe.................(3)"<<endl
    			<<"Aus Datei einlesen..........(4)"<<endl
    			<<"Text in Datei speichern.....(5)"<<endl
    			<<"Ende........................(0)"<<endl;
    
    		cout<<endl<<"Aktuelle Statusmeldug: "<<Status.c_str()<<endl;
    		cin>>x;
    
    		switch(x)
    		{
    		case 1:
    			PrintIn();
    			break;
    
    		case 2:
    			PrintOut();
    			break;
    
    		//case 3:
    			//break;
    
    		case 4:
    			cout<<"Pfad/Dateinamen eingeben: ";
    			 //string out;
    			 getline(cin, In); 
    
    			cout<<"Status: "<<Status.c_str()<<endl;
    			OpenInData(Str);
    
    			cout<<"Status: "<<Status.c_str()<<endl;
    			if(InDataFlag == true)
    			{
    				ReadData();
    			}
    			break;
    
    		case 3:
    		case 5:
    			Status = "Menueauswahl noch nicht implementiert!";
    			break;
    
    		case 0:
    			loop = false;
    			break;
    		default:
    			Status = "Eingabe nicht erkannt!";
    			break;
    		}
    
    		system("cls");
    	}
    	while(loop);
    }		
    
    void CCrypt::WriteIn()
    {
    	//cin.getline(In,2000);
    }
    int CCrypt::OpenInData(string sPath)
    {
    	InData = fopen(sPath.c_str(),"r");
    
    	if(InData == NULL)
    	{
    		InDataFlag = false;
    		Status = "Fehler beim oeffnen der einzulesenden Datei!";
    		return 1;
    	}
    
    	else
    	{
    		InDataFlag = true;
    		Status = "Datei erfolgreich geoeffnet!";
    		return 0;
    	}
    
    }
    
    int CCrypt::OpenOutData(string sPath)
    {
    	OutData = fopen(sPath.c_str(),"a");
    
    	if(OutData == NULL)
    	{
    		OutDataFlag = false;
    		Status = "Fehler beim oeffnen der zuschreibenden Datei!";
    		return 1;
    	}
    
    	else
    	{
    		OutDataFlag = true;
    		Status = "Datei erfolgreich geoeffnet!";
    		return 0;
    	}
    }
    
    void CCrypt::CloseInData()
    {
    	if(InDataFlag)
    	{
    		fclose(InData);
    	}
    }
    
    void CCrypt::CloseOutData()
    {
    	if(OutDataFlag)
    	{
    		fclose(OutData);
    	}
    }
    
    void CCrypt::ReadData()
    {
    	string temp;
    
    	for(int i = 0; !feof(InData);i++)
    	{
    		fscanf(InData,"%s",temp);
    		//In = In +temp;
    	}
    	//	Status="Fehler beim lesen!";
    
    	/*
    	else
    	{
    		Status="Erfolgreich ausgelesen!";
    	}*/
    
    }
    
    void CCrypt::WriteData()
    {
    	if(feof(OutData)==fprintf(OutData,"%s",Out))
    	{
    		Status="Fehler beim schreiben!";
    	}
    
    	else
    	{
    		Status="Erfolgreich geschrieben!";
    	}
    }
    
    void CCrypt::PrintIn()
    {
    	cout<<In.c_str();
    }
    
    void CCrypt::PrintOut()
    {
    	cout<<Out.c_str();
    }
    

    In der main.cpp wird dann nur ein Objekt der Klasse erzeugt und dessen Menue() aufgerufen.
    Das ganze Projekt steht noch am Anfang, dies ist also nur ein Problem, von vielen die (bestimmt) noch kommen also reißt mir nicht gleich den Kopf ab, wenn etwas nicht perfekt ist ;). (Und wo ich schon dabei bin, welchen Wert gibt fscanf() zurück, wenn es nicht erfolgreich war?).
    Viel Erfolg bei der Fehlersuche!


  • Administrator

    @BasicMan01,
    Genau deshalb meinte ich ein kurzes Beispiel. Wer liest sich schon freiwillig all den Code durch, welcher Guest Brain nur gepostet hat? 🙄

    @Guest Brain,
    Dank dem, dass ich wusste, worauf ich schauen möchte:
    <string.h> != <string>
    Das sind zwei ganz verschiedene Header. <string.h> ist der Header für C String Operationen, während <string> der Header für C++ Strings ist.

    C++ Referenz: http://www.cplusplus.com/reference/

    Grüssli



  • Kopf -> Tisch -> Bämm -> Aua
    Nen ganzen Nachmittag wegen nem simplen .h verschwendet...
    Ich tauch unter und beschaffe mir eine neue Identität! Trotz dem Danke für die Hilfe!



  • Guest Brain schrieb:

    Kopf -> Tisch -> Bämm -> Aua
    Nen ganzen Nachmittag wegen nem simplen .h verschwendet...
    Ich tauch unter und beschaffe mir eine neue Identität! Trotz dem Danke für die Hilfe!

    Ein eigenes Verschlüsselungsverfahren zu entwickeln endet übrigens in 99,99% in einer Katastrophe. Im besten Fall kann man damit Dateien verschleiern, aber das war es dann auch schon. Aber als kleines Experiment ist das natürlich vollkommen okay. 🙂



  • bist du noch da?
    also hats sinn, dir hier zu posten, was an deinem code alles nicht so schön ist?
    falls ja, kannst ja noch mal schreiben und morgen noch mal vorbeigukcne oder so^^



  • Ja ich bin noch da. Klar würde ich mich über etwas konstruktive Kritik freuen.
    Fangen wir doch mal beim Einlesen der Dateien an, da gibt VC++ nämlich schon Warnungen aus.
    Wir haben es in der Schule aber nur so gelernt, dass dies aber nicht der richtige Weg ist weiß ich auch.
    Wie würdet ihr denn vorgehen?
    grüße Guest Brain 😃



  • Ach ja und das Ganze soll erst mal nur ein Konsolenprogramm sein.



  • Also zum einlesen würde ich ifstream benutzen:

    http://www.cplusplus.com/reference/iostream/ifstream/

    Wenn du da auf Memberfunktionen (wie z.B den Konstruktor) klickst, dann gibts auch überall Beispiele dazu.



  • In Headern nutzt man kein using namespace, da das den Sinn der namespaces komplett zerstört (und auch zu sehr doofen Fehlern führen kann)...

    FILE *InData;	//einzulesende Datei
    	FILE *OutData;	//auszugebende Datei
    

    das hier sieht sehr nach C aus
    in C++ gibts für so etwas Streams:
    http://www.cplusplus.com/reference/iostream/

    bool InDataFlag;	//Zum Prüfen der Dateizeiger
    	bool OutDataFlag;
    

    das hier sind zumindest komische Variablennamen...
    Könnte sein, dass sich das dann mit den Streams so und so erledigt - aber ich versteh als Ausenstehender zumindest an Hand des Namens oder des Kommentars nicht, was die Variablen anzeigen.

    CCrypt(string InPath, string OutPath);
    

    Nicht trivial-kopierbare Typen übergibt man nicht per value sondern per (const) reference:

    CCrypt(const std::String& InPath, const std::string& OutPath)
    

    das gleiche gilt auch bei Open...

    Im Allgemeinen solltest du die Schnittstellen deiner Klasse vll noch mal überdenken...
    Sieht ein wenig so aus, als ob es eine Art Superklasse ist, die nicht nur ver- und entschlüsselt, sondern auch noch in Dateien schreibt und daraus liest und außerdem noch irgendwas für den Nutzer hat(zumindest klingt Menue so^^)

    #include <string.h>
    

    das das der falsche Header ist, hatten wir ja schon geklärt - du solltest aber mal im Kopf behalten, dass die standard-C++-Header nie keine Endung haben:
    http://www.cplusplus.com/reference/

    CCrypt::CCrypt()
    {	
    	Status = "keine Meldung";
    
    }
    

    Für so etwas gibt es die Initialisierungsliste:

    CCrypt::CCrypt()
    :  Status("keine Meldung")
    {}
    
    CCrypt::~CCrypt()
    {
    
    }
    

    Wenn dein DTor nur so aussieht, brauchst du ihn auch gar nicht erst zu deklarieren - das übernimmt der Compiler schon für dich.
    Dein DTor sollte aber noch die Dateien schließen(apropos: du testest die Handles gegen 0, bevor du versuchst, sie zu schließen - im Konstruktor setzt du sie aber nicht auf 0 - dort steht also irgendwas drin - und deine CloseFile-Funktionen werden undefiniertes Verhalten zur Folge haben, wenn man sie falsch verwendet)

    void CCrypt::Menue()
    

    hat wie gesagt nix in der Klasse zu tun sondern sollte eher in der main-Funktion stehen oder so...

    cout<<endl<<"Aktuelle Statusmeldug: "<<Status.c_str()<<endl;
    

    Das .c_str() ist ein wenig Sinnlos. Lass das einfach weg.

    char Name[200];
    

    wieso dann auf einmal doch wieder char[]? Es ging doch die ganze Zeit so schön mit std::string - und jetzt auf einmal willst du wieder eine Fehlerquelle einbauen?

    if(InDataFlag == true)
    			{
    				ReadData();
    			}
    

    bools vergleicht man eigtl kürzer:

    if(x)
      ReadData();
    
    //für false dann entsprechend:
    if(!x)
      bla();
    

    Es geht zwar auch mit == true und == false, aber schöner Stil ist das nicht.

    InData = fopen(sPath.c_str(),"r");
    

    Wie weiter oben beschrieben: das hier ist kein C++ sondern C.

    int CCrypt::OpenInData(string sPath)
    {
      {//fehler
        return 1;
      }
    
      //alles ok
      return 0;
    }
    

    für so etwas nimmt man in C++ eigtl Exceptions.

    bb



  • Ja also das mit den FILE* wollte ich noch ändern (wir haben in der Schule aber nur damit gearbeitet deshalb kenn ich das nicht anders). Die DataFlag sollte eigentlich wie ein Schalter sein ob die Daten geöffnet sind oder nicht aber wo ich gerade noch mal darüber nachdenke... das geht eingentlich auch ohne bool Variable.

    Die leeren Konstruktoren sollen auch noch gefüllt werden und wegen der Sache mit der Superklasse öhm ja sie sollte erst mal Daten einlesen und Daten schreiben können. Danach wollte ich erst eine Methode hinzufügen die den Text auch verschlüsselt.

    Das Char Feld habe ich auch wieder entfernt nachdem es mit den Strings geklappt hatte.

    Wenn ich .c_str() weg lasse dann gibts ne Fehlermeldung, vermutlich kann cout nicht mit Strings umgehen.

    so weit so gut
    mfg Guest Brain


Anmelden zum Antworten