anfänger hat probleme mit globalen variablen



  • hi

    ich hab folgendes problem bei z.b. diesem code hängt er sich jedes mal auf wegen der globalen variable aber warum?

    hier der code:

    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    void func ();
    
    adresse eins("Rostock","Rosenweg 12","0170/1964619");
    
    int main ()
    {
    	eins.putadresse();
    
    	adresse a;
    	a.putadresse();
    	a.setadresse("13055 Berlin","Arendsweg","1609");
    	a.putadresse();
    
    	cout << "Es folgt der erste Aufruf der Funktion func()\n\n";
    
    	func();
    
    	cout << "Es folgt der zweite Aufruf der Funktion func()\n\n";
    
    	func();
    
    	return 0;
    }
    
    void func()
    {
    	static adresse spez1("09471 Baerenstein","Rosenweg","4973");
    	spez1.putadresse();
    
    	adresse funktion("16792 Zehdenick","Falterstrasse","2589");
    	funktion.putadresse();
    
    	cout << "\nVor dem Ende der Funktion!\n\n";
    }
    

    also durch das globale objekt der klasse adresse (eins) hängt er sich immer auf, das weiß ich daher wenn ich es auskommentiere funktioniert es wie gewünscht.

    woran liegts? ich benutze windows xp und den borland compiler 5.5 oder so (ich compiliere von hand also bcc32 -tWC adresse.cpp etc.)

    ich hoffe mir kann jemand helfen.

    guten rutsch übrigens noch und gleich ein frohes neues 🤡.

    mfg david



  • Dir auch ein frohes neues 😉

    :xmas1: :xmas2: :xmas1:

    zu deinem prob. hmmm

    also wenn du die zeile

    adresse eins("Rostock","Rosenweg 12","0170/1964619");
    

    rauskommentierst, geht der rest? was ist putadresse? werden da die daten per cout z.b. ausgegeben?

    nur mal so als tipp. verwende bitte sinnvolle variablennamen. Erst heisst ein objekt "eins" dann "a" dann "funktion" <----sehr dummer name.

    Also ich weiss nicht wie die klasse def. ist, aber vielleicht stimmt der 3te parameter nicht. wieviele zeichen kann der 3te speichern? vielleicht ist ihm das zu lang und er kann z.b. nur 6 zeichen aufnehmen.

    was ich mich jetzt auch frage. du kommentierst die zeile ja raus. und bei der zeile

    eins.putadresse();
    

    soll er nicht meckern? Was meinst du eigentlich mit "hängt" sich auf? crasht der pc? frierst das prog ein? meckert der compiler? Was ist die Fehlermeldung? die Fehlermeldung ist eigentlich immer ganz hilfreich. also besser als "hängt sich auf" 🙂

    lege die adressen am besten in ein adressen array oder noch besser in einem adressen vector (( stichwort vector hier im forum suchen )). ist besser als deine dubiösen namen.



  • Also, stürzt das Programm bei dem Aufrufen des Konstruktors von adresse ab oder wenn du eine Elementfunktion von adresse verwendest?
    Stell doch außerdem mal bitte den Code von der Klasse hier rein, dann kann man das besser beurteilen, woran es liegt, sonst muss man so ins blaue hinein raten 🙂



  • Wenn du keine globalen Varaiablen verwenden würdest, sondern vernünftigerweise
    Funktionsparameter, hättest du schon mal eine Fehlerquelle weniger. 😉

    mfg JJ



  • Trantüte schrieb:

    eins.putadresse();
    

    die wahrsagekugel sagt, dass der fehler wahrscheinlich in dieser funktion liegt.
    ohne weiteren code ist weitere hilfe unmöglich.



  • also an alle die sich wegen:

    eins.putadresse(); beschwert haben, dass ich hab ich natürölich mit auskommentiert. 🙂

    zweitens es kommt keine fehlermeldung beim compilieren er compiliert alles ohne warnungen oder errors. nur beim aufruf der exe datei kommt von windows so ein fenster und zwar dreimal nach einander. in dem fenster steht adresse.exe hat ein problem festgestell und mus beendet werden. und das ganze drei mal 🙂

    so hier nochmal der code von allen dzugehörigen dateien:

    haeder datei adresse.h
    
    #ifndef _adresse_
    #define _adresse_
    
    #include <string.h>
    
    class adresse
    {
    private:
    	char stadt[20];
    	char strasse[25];
    	char telefon[15];
    public:
    	adresse(const char *stadt="xxxxxx",const char *strasse="xxxxxx", const char *telefon="000000");
    	~adresse();
    	void setadresse(const char *,const char *,const char *);
    	void putadresse();
    };
    
    inline void strcpy(char *s1,const char *s2,int n)
    {
    	strncpy(s1,s2,n);
    	s1[n]='\0';
    }
    
    #endif
    
    hier die zweite:
    
    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    int anzahl=0;
    
    adresse::adresse(const char *stadt,const char *strasse,const char *telefon)
    {
    	setadresse(stadt,strasse,telefon);
    	++anzahl;
    
    	cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " erschaffen!\n";
    	cout << "Das war das " << anzahl << ". Objekt!\n";
    }
    
    adresse::~adresse()
    {
    	--anzahl;
    	cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " zerstoert!\n";
    	cout << "Es verbleiben noch " << anzahl << " Objekte!\n";
    }
    
    void adresse::setadresse(const char *city,const char *street,const char *nummer)
    {
    	strcpy(stadt,city,sizeof(stadt)-1);
    	strcpy(strasse,street,sizeof(strasse)-1);
    	strcpy(telefon,nummer,sizeof(telefon)-1);
    }
    
    void adresse::putadresse()
    {
    	cout << "Strasse:\t" << stadt << endl;
    	cout << "Stadt:  \t" << strasse << endl;
    	cout << "Telefon:\t" << telefon << endl;
    
    	cin.get();
    }
    
    und hier die dritte:
    
    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    void func ();
    
    //adresse eins("Rostock","Rosenweg 12","0170/1964619");
    
    int main ()
    {
    	//eins.putadresse();
    
    	adresse a;
    	a.putadresse();
    	a.setadresse("13055 Berlin","Arendsweg 13","030/9821609");
    	a.putadresse();
    
    	cout << "Es folgt der erste Aufruf der Funktion func()\n\n";
    
    	func();
    
    	cout << "Es folgt der zweite Aufruf der Funktion func()\n\n";
    
    	func();
    
    	return 0;
    }
    
    void func()
    {
    	static adresse spez1("09471 Baerenstein","Rosenweg 12","037347/84973");
    	spez1.putadresse();
    
    	adresse funktion("16792 Zehdenick","Falterstrasse 17","03307/302589");
    	funktion.putadresse();
    
    	cout << "\nVor dem Ende der Funktion!\n\n";
    }
    

    mal sehen ob ihr mir jetzt licht ins dunkel bringen könnt 😉

    mfg david



  • du kopierst immer sizeof(stadt), sizeof(strasse) und sizeof(telefon) viele chars aus den übergebenen strings in die arrays. was ist aber, wenn der string, den du übergibst, nicht so viele chars enthält? dann wird grober unsinn mitkopiert bzw. kann es dir passieren, sachen mitzukopieren, die deinem programm eigentlich gar nicht gehören. das ging vielleicht früher, aber heutzutage lässt das kaum ein betriebssystem mehr zu. was ist übrigens, wenn jemand in Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch wohnt? (eine stadt in wales)
    also, du kannst bei dem design bleiben und mit strlen arbeiten

    strcpy(stadt,city,strlen(city));
    strcpy(strasse,street,strlen(street));
    strcpy(telefon,nummer,strlen(nummer));
    

    btw würde ich die funktion nicht unbedingt strcpy nennen, da es schon ein strcpy gibt.
    oder du könntest natürlich auch auf die c++ strings umsteigen.

    was mir noch auf die schnelle auffällt, ist, dass der header nicht string.h sondern cstring heißt, und dass du die präprozessordirektiven

    #ifndef _adresse_
    #define _adresse_
    

    nicht mit einem underscore beginnen solltest. (diese namen sind nämlich für compilerhersteller reserviert)



  • Du sag mal programmierst du C oder C++? Für mich sieht das mal stark nach C aus...



  • 💡 er verwendet iostream, namespaces und klassen.



  • hmmm bis jetzt hat mir immer noch keiner meine Frage beantwortet 😞

    aber ich hoffe noch.

    mfg david



  • Trantüte schrieb:

    class adresse
    {
    private:
    	char stadt[20];
    	char strasse[25];
    	char telefon[15];
    [...]
    };
    
    adresse::adresse(const char *stadt,const char *strasse,const char *telefon)
    {
    	setadresse(stadt,strasse,telefon);
    	++anzahl;
    
    	cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " erschaffen!\n";
    	cout << "Das war das " << anzahl << ". Objekt!\n";
    }
    

    Btw wie unterscheidet der Compiler jetzt zwischen den Parameterbezeichnern des Konstruktors und den Membervariablenbezeichnern der Klasse adresse? Greift er sich da nicht die Membervariablen der Klasse?

    Hmm, ich schlage dir sowieso vor eine Initialisierungliste zu benutzen, das spart den Aufruf vom Default-Konstruktor. 🙂



  • Trantüte schrieb:

    hmmm bis jetzt hat mir immer noch keiner meine Frage beantwortet 😞

    davie schrieb:

    du kopierst immer sizeof(stadt), sizeof(strasse) und sizeof(telefon) viele chars aus den übergebenen strings in die arrays. was ist aber, wenn der string, den du übergibst, nicht so viele chars enthält? dann wird grober unsinn mitkopiert bzw. kann es dir passieren, sachen mitzukopieren, die deinem programm eigentlich gar nicht gehören. das ging vielleicht früher, aber heutzutage lässt das kaum ein betriebssystem mehr zu.

    kurz gesagt ersetze sizeof(stadt) durch strlen(city) [gegebenenfalls überprüfe, ob strlen(city) kleiner als sizeof(stadt) ist]
    oder besser noch: verwende std::string.

    ... schrieb:

    Btw wie unterscheidet der Compiler jetzt zwischen den Parameterbezeichnern des Konstruktors und den Membervariablenbezeichnern der Klasse adresse? Greift er sich da nicht die Membervariablen der Klasse?

    nein. er greift zu den parametern. auf die member kann man via this-> zugreifen.

    ... schrieb:

    Hmm, ich schlage dir sowieso vor eine Initialisierungliste zu benutzen, das spart den Aufruf vom Default-Konstruktor. 🙂

    vielleicht stehe ich auf der leitung: was meinst du?



  • davie schrieb:

    nein. er greift zu den parametern. auf die member kann man via this-> zugreifen.

    Ich wusste es eben nicht mehr aus dem Kopf, weil der this-Zeiger kann ja auch weggelassen werden um auf eine Membervariable zuzugreifen. Aber ich habe es nochmals ausprobiert, es wird tatsächlich auf die Parameter zugegriffen. Trotzdem würde ich Membervariablen mit dem Präfix m_* benennen, das spart die Verwirrung immens.

    davie schrieb:

    vielleicht stehe ich auf der leitung: was meinst du?

    Mit Initialisierungsliste meine ich das hier:

    class A
    {
    public:
        A(int __a) 
        : a(__a) // Initialisierungsliste
        { }
    private:
        int a;
    };
    


  • HI

    adresse(const char *stadt="xxxxxx",const char *strasse="xxxxxx", const char *telefon="000000");
    

    Zum guten programmier stiel gehört auch dazu das man möglichst wenig default werte nimmt, und in diesem fall sind sie sogar absolut unnötig

    mfg spjoe



  • davie schrieb:

    ... schrieb:

    Btw wie unterscheidet der Compiler jetzt zwischen den Parameterbezeichnern des Konstruktors und den Membervariablenbezeichnern der Klasse adresse? Greift er sich da nicht die Membervariablen der Klasse?

    nein. er greift zu den parametern. auf die member kann man via this-> zugreifen.

    Oder man verwendet eine spezielle Bezeichnung für Member Variablen. Das altbekannte Präfix m_ ist zB eine Möglichkeit, einige Programmierer (zB auch meiner einer) verwenden mittlerweile Postfix _.



  • Jop, das geht natürlich auch. Man kanns auch als Präfix anwenden, aber lesbarer ist es natürlich als Suffix, weil der Name besser hervorgeht. Es gibt auch noch mehr sinnvolle Möglichkeiten, aber egal welche man anwendet, die Lesbarkeit wird dadurch immens gesteigert. 😉



  • @davie

    hmm also mit strlen funktioniert es nicht mal ohne globale objekte. da ich noch anfänger bin mach ich vielleicht auch irgendwas anderes falsch. vielleicht kannst du mir mal die entsprechenden passagen umschreiben und posten :).

    mfg david



  • einmal mit c-strings

    //Nummer 1
    #ifndef Adresse_h  
    #define Adresse_h
    
    //Nummer 2
    /*#include <cstring>*/
    
    class adresse
    {
    private:
        char stadt[20];
        char strasse[25];
        char telefon[15];
    public:
        adresse(const char *stadt="xxxxxx",const char *strasse="xxxxxx", const char *telefon="000000");
        ~adresse();
        void setadresse(const char *,const char *,const char *);
        void putadresse();
    };
    
    #endif
    
    #include "adresse.h"
    #include <iostream>
    //Nummer 3
    #include <cstring>
    using namespace std;
    
    //Nummer 4
    namespace
    {
       int anzahl=0; //oder lieber in die klasse rein?
    }
    
    adresse::adresse(const char *stadt,const char *strasse,const char *telefon)
    {
        setadresse(stadt,strasse,telefon);
        ++anzahl;
    
        cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " erschaffen!\n";
        cout << "Das war das " << anzahl << ". Objekt!\n";
    }
    
    adresse::~adresse()
    {
        --anzahl;
        cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " zerstoert!\n";
        cout << "Es verbleiben noch " << anzahl << " Objekte!\n";
    }
    
    void adresse::setadresse(const char *city,const char *street,const char *nummer)
    {
        strncpy(stadt,city, strlen(city)+1);
        strncpy(strasse,street, strlen(street)+1);
        strncpy(telefon,nummer,strlen(nummer)+1);
    }
    
    void adresse::putadresse()
    {
        cout << "Strasse:\t" << stadt << '\n';
        cout << "Stadt:  \t" << strasse << '\n';
        cout << "Telefon:\t" << telefon << '\n';
    
        cin.get();
    }
    
    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    void func ();
    
    adresse eins("Rostock","Rosenweg 12","0170/1964619");
    
    int main ()
    {
        eins.putadresse();
    
        adresse a;
        a.putadresse();
        a.setadresse("13055 Berlin","Arendsweg 13","030/9821609");
        a.putadresse();
    
        cout << "Es folgt der erste Aufruf der Funktion func()\n\n";
    
        func();
    
        cout << "Es folgt der zweite Aufruf der Funktion func()\n\n";
    
        func();
    
        //Nummer 5
        //return 0;
    }
    
    void func()
    {
        static adresse spez1("09471 Baerenstein","Rosenweg 12","037347/84973");
        spez1.putadresse();
    
        adresse funktion("16792 Zehdenick","Falterstrasse 17","03307/302589");
        funktion.putadresse();
    
        cout << "\nVor dem Ende der Funktion!\n\n";
    }
    

    vielleicht auch mit

    void adresse::setadresse(const char *city,const char *street,const char *nummer)
    {
        strcpy(stadt,city);
        strcpy(strasse,street);
        strcpy(telefon,nummer);
    }
    

    und mit std::strings

    //Nummer 1
    #ifndef Adresse_h  
    #define Adresse_h
    
    //Nummer 2
    #include <string>
    
    class adresse
    {
    private:
        //Nummer 3
        std::string stadt;
        std::string strasse;
        std::string telefon;
    public:
        //Nummer 4
        adresse(std::string const& stadt="", std::string const& strasse="", std::string const& telefon="");
        ~adresse();
        //Nummer 5
        void setadresse(std::string const&, std::string const&, std::string const&);
        void putadresse();
    };
    
    #endif
    
    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    //Nummer 6
    namespace {
       int anzahl=0; //oder lieber in die klasse rein?
    }
    
    //Nummer 7
    adresse::adresse(string const& stadt, string const& strasse, string const& telefon)
     : stadt(stadt), strasse(strasse), telefon(telefon)
    {
        ++anzahl;
        cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " erschaffen!\n";
        cout << "Das war das " << anzahl << ". Objekt!\n";
    }
    
    adresse::~adresse()
    {
        --anzahl;
        cout << "\nEs wurde das Objekt fuer die Stadt " << stadt << " zerstoert!\n";
        cout << "Es verbleiben noch " << anzahl << " Objekte!\n";
    }
    
    //Nummer 8
    void adresse::setadresse(string const& city, string const& street, string const& nummer)
    {
       stadt=city;
       strasse=street;
       telefon=nummer;
    }
    
    void adresse::putadresse()
    {
        cout << "Strasse:\t" << stadt << '\n';
        cout << "Stadt:  \t" << strasse << '\n';
        cout << "Telefon:\t" << telefon << '\n';
    
        cin.get();
    }
    
    #include "adresse.h"
    #include <iostream>
    using namespace std;
    
    void func ();
    
    adresse eins("Rostock","Rosenweg 12","0170/1964619");
    
    int main ()
    {
        eins.putadresse();
    
        adresse a;
        a.putadresse();
        a.setadresse("13055 Berlin","Arendsweg 13","030/9821609");
        a.putadresse();
    
        cout << "Es folgt der erste Aufruf der Funktion func()\n\n";
    
        func();
    
        cout << "Es folgt der zweite Aufruf der Funktion func()\n\n";
    
        func();
    
        //Nummer 9
        //return 0;
    }
    
    void func()
    {
        static adresse spez1("09471 Baerenstein","Rosenweg 12","037347/84973");
        spez1.putadresse();
    
        adresse funktion("16792 Zehdenick","Falterstrasse 17","03307/302589");
        funktion.putadresse();
    
        cout << "\nVor dem Ende der Funktion!\n\n";
    }
    

    müsste alles funktionieren, wenn keine tippfehler drin sind.



  • ... schrieb:

    Mit Initialisierungsliste meine ich das hier:

    was eine initialisierungsliste ist, weiß ich. trotzdem fehlt doch irgendwie der bezug?



  • @davie

    erst mal danke für die mühe 🙂 habe beide versionen ausprobiert funktionieren beide genauso wie die ursprüngliche. sobald ich aber das globale objekt eins der klasse adresse initializiere passiert dasselbe drei mal das am anfang beschriebene fenster keine ausführung des programms. compilieren tut ers ohne fehler oder warnungen.

    irgendwas mit globalen objekten klappt nicht. aber was? bei normalen globalen variablen wie anzahl gibt es keine probleme.

    wieso hast du die variable anzahl in namespace verpackt? was ist der efekt oder sinn?

    was ist in <string> definiert?

    das return in der main hast du einfach so auskommentiert gibts da keine probleme oder was ist davon der sinn das mann es nicht schreibt?

    mfg david


Anmelden zum Antworten