undefined reference to...



  • Hallo @ all,

    wir haben die Aufgabe bekommen in ziemlich kurzer Zeit c++ zu lernen und anzuwenden. Leider ist das ziemlich schwierig. Ich habe die Aufgabe ein WIKI zu programmieren. Hier nun meine Frage. Ich habe eine Methode in der Datei Werkzeug.cpp und der Klasse Werkzeug. Die Methode heisst parseStream(). Sie erwartet einen String und soll einen map Container mit jeweils zwei Strings zurückgeben. Leider bekomme ich die Fehlermeldung "undefined reference to.."

    hier nun erstmal die Header Datei der Werkzeug Klasse:

    #ifndef _Werkzeug_h_
    #define _Werkzeug_h_
    
    #include <iostream>
    #include <dirent.h>
    #include <cstdlib>
    #include <string>
    #include <list>
    #include <map>
    
    using namespace std;
    
    class Werkzeug
    {
    	public:
    		Werkzeug ();  //Konstruktor
    		~Werkzeug();  //Destruktor
    		string ersetze(string s, string s1, string s2);
    		string searchReplace(string searchstring);
    		string directory(string verz, string mask);
    		list<string> split (string str, char tr);
    		map <string, string> parseStream(string str);
    	private:
    		string _Zeichenkette, _searchstring, _s, _s1, _s2;
    };
    
    #endif
    

    Dann noch der Code der Werkzeug Klasse an sich:

    #include "Werkzeug.h"
    
    Werkzeug::Werkzeug() {};
    
    Werkzeug::~Werkzeug() {};
    
    string Werkzeug::ersetze(string s, string s1, string s2) {
    	 int l = s1.length();
    	 int i = s.find(s1);
    	 while(i != string::npos) {
    		s.replace(s.find(s1),l, s2);
    		i++;
    		i = s.find(s1, i);
    	 } 
    	return s;
     }
    
    string Werkzeug::searchReplace(string searchstring)
    {
     searchstring = ersetze(searchstring,"+"," ");
     searchstring = ersetze(searchstring,"%0D%0A","\n");
     searchstring = ersetze(searchstring,"%21","!");
     searchstring = ersetze(searchstring,"%22","\""); //backslash vor dem Ausrufezeichen sagt dem Compiler, das folgende Zeichen ist kein Programmcode
     searchstring = ersetze(searchstring,"%23","#");
     searchstring = ersetze(searchstring,"%24","$");
     searchstring = ersetze(searchstring,"%25","%");
     searchstring = ersetze(searchstring,"%26","&");
     searchstring = ersetze(searchstring,"%27","´");
     searchstring = ersetze(searchstring,"%28","(");
     searchstring = ersetze(searchstring,"%29",")");
     searchstring = ersetze(searchstring,"%2B","+");
     searchstring = ersetze(searchstring,"%2C",",");
     searchstring = ersetze(searchstring,"%2F","/");
     searchstring = ersetze(searchstring,"%3A",":");
     searchstring = ersetze(searchstring,"%3B",";");
     searchstring = ersetze(searchstring,"%3C","<");
     searchstring = ersetze(searchstring,"%3D","=");
     searchstring = ersetze(searchstring,"%3E",">");
     searchstring = ersetze(searchstring,"%3F","?");
     searchstring = ersetze(searchstring,"%5C","\\"); //backslash vor dem backslash sagt dem Compiler, das folgende Zeichen ist kein Programmcode
     searchstring = ersetze(searchstring,"%60","`");
     searchstring = ersetze(searchstring,"%7B","{");
     searchstring = ersetze(searchstring,"%7C","|");
     searchstring = ersetze(searchstring,"%7D","}");
     searchstring = ersetze(searchstring,"%7E","~");
     searchstring = ersetze(searchstring,"%B4","'");
     searchstring = ersetze(searchstring,"%C4","Ä");
     searchstring = ersetze(searchstring,"%D6","Ö");
     searchstring = ersetze(searchstring,"%DC","Ü");
     searchstring = ersetze(searchstring,"%E4","ä");
     searchstring = ersetze(searchstring,"%F6","ö");
     searchstring = ersetze(searchstring,"%FC","ü");
     return searchstring;
    }
    
    string Werkzeug::directory(string verz, string mask)
    {
        DIR *hdir;
        struct dirent *entry;
        int inl_slaenge = 0;
        string fn, list, z;
        char verzc[20]=" ";
        const char *verz1, *mask1, *z1;
        verz1 = verz.c_str();
        //strcpy( verzc, verz1);
        mask1 = mask.c_str();
    
        //verz.c_str();
        hdir = opendir(verz1);
        do
        {
            entry = readdir(hdir);
            if (entry)
            {
            	inl_slaenge = strlen(entry->d_name);
            	z = entry->d_name+inl_slaenge-4;
            	z1 = z.c_str();
            	if ((strcmp(mask1, z1) == 0))
            		{
            			fn = entry->d_name; //Konvertieren des Dateinamens in einen String
            			fn.replace(fn.find(mask),4,""); //Dateiendung inklusive Punkt abschneiden
                  fn = "<a href=\""+verz+fn+mask+"\">"+fn+"</a>";  //erzeugen eines Links
                  list = list + fn + "<br>\n";
            		}
            }
        } while (entry);
        closedir(hdir);
        return list;
    }
    
    //static string quoted(const string &src);
    
    list<string> split (string str, char tr) {
    	list<string> strElemente; // Ergebnis: Liste von Teilstrings
    	string::iterator pos1, // Anfang/Ende von
    		pos2; // Teilstrings
    		pos1 = str.begin(); // Beginn eines Teilstrings
    		pos2 = find (pos1, str.end(), tr); // Ende eines Teilstrings
    		while ( pos2 != str.end()) { // Trenner als Ende gefunden
    			assert(*pos2==tr);
    			string elem; // Teilstring
    			copy (pos1, pos2, back_inserter(elem)); // Teilstring kopieren
    			strElemente.push_back(elem); // Teilstring speichern
    			pos1 = pos2;
    			++pos1; // neuer Anfang hinter altem Ende
    			pos2 = find (pos1, str.end(), tr); // neue Suche
    		}
    		// pos2 zeigt auf das Ende. pos1 zeigt auf den Beginn
    		// des letzten Teilstrings vor dem Ende.
    		// Letzten Teilstring extrahieren:
    		//
    
    		string last;
    		copy (pos1, str.end(), back_inserter(last));
    		strElemente.push_back(last);
    		return strElemente;
    }
    
    	map <string, string> parseStream(string str) {
    	list<string> feldListe = split(str, '&'); // in Felder zerlegen
    	map< string,string > felder; // Ergebnis
    	// Felder in Paare aus Feldnamen und Wert splitten
    	//
    
    	for ( list<string>::iterator i = feldListe.begin();
    		i != feldListe.end();
    		++i){
    			list<string> feldStr = split(*i, '=');
    			pair< string, string > feld;
    			feld.first = feldStr.front(); // Feldname
    			feldStr.pop_front();
    			feld.second = feldStr.front(); // Feldwert
    			felder[feld.first] = feld.second; // Paar speichern
    		}
    return felder; // Abbildung Feld-Name -> Feld-Wert zurueck geben
    }
    

    und jetzt noch der Code, wo ich die Methode nutzen möchte:

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <list>
    #include <map>
    #include "Artikel.h"
    #include "Werkzeug.h"
    
    using namespace std;
    
    int main()
    {
     string eingabe;
     getline(cin,eingabe);
      Werkzeug cgi;
      map <string, string> test = cgi.parseStream(eingabe);
    
      test["user_eingabe"] = cgi.searchReplace(test["user_eingabe"]);
      test["EingabeFeld"] = cgi.searchReplace(test["EingabeFeld"]);
      test["EingabeFeld1"] = cgi.searchReplace(test["EingabeFeld1"]);
     	Artikel Wiki("Titel",test["EingabeFeld1"]);
     	Wiki.printHeader();
     cout << "<p>" << endl;
     cout << "<h3>CGI Analyse</h3>" << endl;
     cout << "<hr>" << endl;
    
     cout << "Die Elemente:<br> " << endl;
     cout << " Feld-A = " << test["EingabeFeld"] // Wert von Feld mit Namen Feld-A ausgeben
     << "<br>"
     << " Feld-B = " << test["EingabeFeld1"] // Wert von Feld mit Namen Feld-B ausgeben
     << endl;
     cout << "<p>" << endl;
     cout << "<hr>" << endl;
     cout << "</body></html>" << endl;
    
     cout << test["user_eingabe"];
     cout << "<br><br><br><hr>";
     cout << cgi.directory("../htdocs/",".htm");
     //dir();
    
     ofstream fout(test["EingabeFeld"].c_str());
     fout << test["user_eingabe"];
     fout.close();
    
    }
    

    Vielen Dank im Voraus



  • Du hast die Methoden split() und parseStream() zwar in der Definition der Klasse angegeben, aber in deiner Werkzeug.cpp stehen nur zwei globale Funktionen mit dem selben Namen.
    (oder kurz: Du hast das Werkzeug:: bei der Definition vergessen)

    PS: Vielleicht übersehe ich ja etwas (bei deinem Code auch nicht verwunderlich), aber an welcher Stelle verwendest du eigentlich die Klassenmember _Zeichenkette, _searchstring,...?



  • ohhh man, natürlich. Naja sowas passiert halt als c++ Anfänger. Und das der Code unübersichtlich ist. Naja, mir egal, hauptsache es genügt später annähernd den Anforderungen des Profs 😃



  • C Stoll wollte wohl eher auf das verwenden von c/c++ Code Tags statt einfachen code Tags hinweisen, sowie dass du etwas viel Code gepostet hast (manches haettest du ja wegstreichen koenen) das macht es den leuten hier schwieriger es zu lesen und ergo zu korrigieren.



  • @Shinja: Worauf ich mit meinem PS eigentlich hinauswollte war die Frage, warum das Ganze in eine Klasse verpackt wurde (theoretisch hätte auch eine Sammlung an freien Funktionen ausgereicht). Schon die Tatsache, daß der Compiler die beiden Funktionen problemlos compiliert hat, deutet auf einen Designfehler oder Verständnisproblem hin.



  • Naja, also laut Prof soll alles in Klassen und objektorientiert. Dann hat er uns noch Designregeln mitgegeben. Aber wie gesagt: als Anfänger ist es schwer überhaupt was auf die Beine zu stellen...


Log in to reply