[c++] Problem bei übergabe



  • Hallo Leute,

    ich habe folgendes Problem: Ich habe lese in der main eine Datei zeilenweise aus.
    Aus den extrahierten Variablen(string und int) möchte ich mir in der Funktion "Createfilename" einen Dateinamen zusammensetzen.
    Leider werden mir die String-werte(prozessname und zifferncode) zwar in die Funktion übergeben aber nicht an die Variable dateinamevar angehängt.
    Ich hatte selbiges schon in char-Feldern umgesetzt, was wunderbar funktionierte bis gestern. Dann hab ich es auf String umgemünzt, funkioniert leider auch nicht.

    Hier der Code:

    // sonstige Headerdateien
    #include <stdio.h>
    #include <iostream>
    #include<fstream>
    #include<iomanip>
    #include<cstring>
    #include<math.h>
    #include<sstream>
    #include<string>
    #include <vector>
    #include <limits>
    #include <time.h>		
    #ifdef __unix__				//Header für Auslesen der Dateizeit, Unterscheidet Unix und Windows Dateisystem
          #include <sys/stat.h>	
          #include <sys/types.h>
    #else
          #include <sys\stat.h>
    #endif
    
    #define cout STD_COUT   //da iostream hier nicht eingefuegt wurde.
    #define endl STD_ENDL   //an anderer Stelle wird das zu std::cout geaendert
    
    //Funktionsprototypen
    void createfilename (std::string& dateinamevar, std::string prozessname, std::string zifferncode, int gatyp, int genometyp, int testfkttyp); //char* ist Zeigervariable, 
    
    int  main(){
    					// \0 = leerer String
    
    char vardat[30]="Variableninput.dat";	//enthält Variablengrenzen
    		//Ergebnisdatei
    
    cout << "\n\nEinlesen der Parameter\n\n\n";
    cout << "*************************\n";
    
    //Einlesen der Variablen aus Datei vardat
    
    std::string dummy, val[6]; 			// dummy liest String bis : ein, val[] ist stringarray für die Werte, müssen aber noch gecastet werden
    
    std::string prozess;  				//Name des Prozesses
    std::string zifferncode;			//Zifferncodierung oder Datum
    int gatyp;					//zur Wahl des GA-Typs 
    int genometyp;					//zur Wahl des Genome-Typs
    int testfkttyp;					//zur Wahk der Testfkt
    int anzdurchlaeufe;				//Anzahl der Durchläufe
    
    std::ifstream in(vardat);     					// neuen Lese-Stream aus Datei vardat erzeugen
    if( !in.is_open() ) 						//Fehlerprüfung ob Datei geöffnet werden kann
    {
    std::cerr << "Fehler beim Oeffnen der Datei " << vardat << "\n";
    return 1;
    }
    
    //1. Zeile auslesen
    std::getline(in, dummy, ':'); 			// Einlesen bis :
    in.ignore(); 					// Leerzeichen ignorieren
    std::getline(in, val[0]); 			// Einlesen bis Zeilenende
    prozess = val[0];	
    
    //2.Zeile auslesen
    std::getline(in, dummy, ':'); 			
    in.ignore(); 					
    std::getline(in, val[1]); 			
    zifferncode = val[1];
    
    //3.Zeile auslesen
    std::getline(in, dummy, ':'); 			
    in.ignore(); 					
    std::getline(in, val[2]);
    std::istringstream invar(val[2]);
    invar >> gatyp; 
    
    //4.Zeile auslesen
    std::getline(in, dummy, ':'); 			
    in.ignore(); 					
    std::getline(in, val[3]);
    invar.clear();
    invar.str(val[3]);
    invar >> genometyp;
    
    //5.Zeile auslesen
    std::getline(in, dummy, ':'); 			
    in.ignore(); 					
    std::getline(in, val[4]);
    invar.clear();
    invar.str(val[4]);
    invar >> testfkttyp;
    
    //6. Zeile auslesen
    std::getline(in, dummy, ':'); 			
    in.ignore(); 
    std::getline(in, val[5]);
    invar.clear();
    invar.str(val[5]);
    invar >> anzdurchlaeufe;
    
    //Prüfung Ausgabe der eingelesenen Werte auf Screen
    cout << "prozess: " << prozess << "\n";
    cout << "zifferncode: " << zifferncode << "\n";
    cout << "gatyp: " << gatyp << "\n";
    cout << "genometyp: " << genometyp << "\n";
    cout << "testfkttyp: " << testfkttyp << "\n";
    cout << "anzdurchlaeufe: " << anzdurchlaeufe << "\n"; 
    
    std::string dateierg;
    // Namen der Dateien aus Zeichenkette zusammenbauen
    createfilename(dateierg, prozess, zifferncode, gatyp, genometyp, testfkttyp);		//generiert ersten Teil des Dateinamens
    dateierg += "_Erg.dat";									//generiert Endung
    cout << "\n" << dateierg << "\n";	
    
    }
    
    void createfilename (std::string& dateinamevar, std::string prozessname, std::string zifferncode, int gatyp, int genometyp, int testfkttyp){
    //fügt dateinamevar-string die übergebenen strings  aus Variableninput an
    cout << prozessname;
    dateinamevar += prozessname;
    dateinamevar+= zifferncode;
    
    switch(gatyp){
    case 1: dateinamevar += "Simp"; break; 
    case 2: dateinamevar += "Stea"; break;
    case 3: dateinamevar += "Inc"; break;
    }
    
    switch(genometyp){
    case 1: dateinamevar += "B2D"; break;
    case 2: dateinamevar += "Real"; break;
    }
    
    switch(testfkttyp){
    case 1: dateinamevar += "TF1"; break; 
    case 2: dateinamevar += "TF2"; break;
    case 3: dateinamevar += "ZF"; break;
    }
    
    }
    

    Ich hoffe ihr könnt mir helfen. Ich verzweifel da schon 1,5 Tage dran.

    Viele Grüße

    Guddy



  • Werd mal genauer! Was funktioniert denn nicht? Strings zusammensetzen ist eigentlich kein Problem:

    void concatStrings(std::string& s1,std::string s2) {
      s1+=s2;
    }
    
    std::string s1="Test";
    std::string s2="XXX";
    concatString(s1,s2);
    

    Klappt wunderbar...

    BTW: Nimm [cpp ]-Tags statt [code ], ist besser lesbar.



  • Also die Eingabe kannst du da besser mit einer Funktion, oder Schlaufe löschen. Copy/Paste weisst auf eine mögliche Verbesserung des Codes hin.

    Zum Problem. Geh da mal mit dem Debugger duch, dann findest du die Stell, wo es deiner Meinung nach nicht das macht, was du denkst. Wenn du den Fehler dann nicht selber lösen kannst, kannst du du ein wenig genauer posten, was dir nicht klar ist, warum etwas anders geht.


  • Mod

    Deine Funktion zur Namenserzeugung funktioniert ganz ausgezeichnet. Bist du sicher, dass beim Einlesen deiner Werte alles richtig ist? Das kommt mir sehr umständlich vor, wie du das machst, aber ich kenne jetzt ja auch nicht dein Dateiformat.



  • Ich hab das Problem soweit eingegrenzt:

    // sonstige Headerdateien
    #include <stdio.h>
    #include <iostream>
    #include<fstream>
    #include<iomanip>
    #include<cstring>
    #include<math.h>
    #include<sstream>
    #include<string>
    #include <vector>
    #include <limits>
    #include <time.h>		
    #ifdef __unix__				//Header für Auslesen der Dateizeit, Unterscheidet Unix und Windows Dateisystem
          #include <sys/stat.h>	
          #include <sys/types.h>
    #else
          #include <sys\stat.h>
    #endif
    
    using namespace std;
    
    //Funktionsprototypen
    
    int  main(){
    					// \0 = leerer String
    
    char vardat[30]="Variableninput.dat";	//enthält Variablengrenzen
    		//Ergebnisdatei
    
    cout << "\n\nEinlesen der Parameter\n\n\n";
    cout << "*************************\n";
    
    //Einlesen der Variablen aus Datei vardat
    
    string dummy;
    
    string prozess;  				//Name des Prozesses
    
    ifstream in(vardat);     					// neuen Lese-Stream aus Datei vardat erzeugen
    if( !in.is_open() ) 						//Fehlerprüfung ob Datei geöffnet werden kann
    {
    cerr << "Fehler beim Oeffnen der Datei " << vardat << "\n";
    return 1;
    }
    
    //1. Zeile auslesen
    getline(in, dummy, ':'); 			// Einlesen bis :
    in.ignore(); 					// Leerzeichen ignorieren
    getline(in, prozess); 			// Einlesen bis Zeilenende
    
    std::string dateierg="";
    cout << "prozessname: " <<prozess << "free\n";
    
    }
    

    Wenn ich in der Inputdatei nach dem ": " folgendes stehen habe: "Bla"
    bekomme ich folgende Ausgabe: in der letzten Code-Zeile:

    freeessname: Bla
    

    Anscheinend wird die Variable Bla bis Zeilenende eingelesen. Obwohl ich die Datei in Linux editiert habe und der Zeilenumbruch direkt nach "Bla" nach Enter gesetzt wurde. getline nimmt ja automatisch "\n" als delimit-Wert, wenn nichts weiter angegeben wurde.



  • setze ich einen anderen delimiter, wie z.B. "/" im Code und der Inputdatei funktionierts einwandfrei. Aber eigentlich möchte ich das nicht. Wo wird denn der Zeilenumbruch gesetzt, wirklich nach der "Entereingabe"?



  • Enter ist Zeilenumbruch ja.

    Aber ich verstehe nicht ganz, wo dein Problem ist.

    cout << "prozessname: " <<prozess << "free\n";
    

    Ergibt dir mit prozessname = "bla" das da ?

    freeessname: Bla



  • hmm... ist jetzt einw enig geraten, aber das sieht mir nach folgendem aus:
    - in der Datei steht nach dem Bla ein Zeilenumbruch, und zwar windowstypisch ein CR gefolgt von einem LF.
    Das getline(in, prozess) liest bis zum LF, was dazu fürht dass in prozess sowas wie "Bla \r" steht - also der CR mit im String drin ist. Da du den CR also mit ausgibst wird nach dem Bla der Cursor an den Zeilenanfang gesetzt und das free überschreibt die ersten 4 Buchstaben der Zeile...



  • Danke Pumuckl,
    das wußte ich nicht und so funktionierts.

    gibt es eine Möglichkeit sicherzustellen, dass das Dateiformat Unix oder Windows ist? Ich müsste sicherstellen das mein Programm noch läuft. auch wenn jemand änderungen in der Datei in Windows als auch Linux macht.

    Viele Grüße

    Guddy



  • guddy schrieb:

    Ich hab das Problem soweit eingegrenzt:

    Dürfte ich dich um ein paar Dinge bitten, wenn du willst das dir viele helfen?

    1. Minimiere das Programm auf den Problemfall, dies umfasst auch:
    a) Includiere nur das, was für den Fall nötig ist
    b) Vermeide das mischen mehrerer Sprachen (Hier C und C++), sofern du dich damit schon auskennst.

    2. Formatiere den Code so, das er auch für andere lesbar ist
    a) Einrückungen auf Scopeebene (jeder Scope sollte sauber erkennbar sein)
    b) Vermeide unnötig viele Leerzeilen, einzelne können zum Verständnis beitragen, viele führen zu einer optisch zu starken Trennung.
    c) Wähle bezeichner so, das auch andere ihren Sinn erkennen können (vardat sagt z.B. garnichts aus).

    cu André



  • Es gibt im linux ein command dos2unix oder unix2dos. mit
    shell(dos2unix "Dateiname") stelle ich sicher, dass das Format passt. Problem gelöst.

    Danke für eure Hilfe.

    Viele Grüße

    Torsten


Anmelden zum Antworten