Komischer Error



  • deklarier die variablen als extern und pack die initialisierung in die cpp datei



  • externer schrieb:

    deklarier die variablen als extern

    Wozu braucht man eigentlich extern? Ich hab das noch nie gebraucht.



  • Sagen wir du hast Test.cpp

    int i = 0;
    
    // Hier wäre dann noch mehr Code
    

    und du möchtest i in Main.cpp brauchen, dann musst du das so machen:

    extern int i; // (1)
    
    int main()
    {
    	cout << i << endl;
    }
    

    Wenn du 1 gänzlich weglässt, dann kommt ein Fehler wie "undeclared identifier". Wenn du das extern wegläst dann kommt was mit "multiple definition". Gebraucht hab ichs aber auch noch nie 🙂



  • Ich habs jetzt so gemacht:

    //trash_h.h
    //Globals
    extern bool saved;
    extern char str_date[30];
    extern int aktual_day, aktual_month; 
    extern char aktual_year[5];
    extern char termine_output[MAX_CHARS];
    extern char db_filename[30];
    extern datenbank db;
    //Globals ende
    
    //trash_h.cpp
    saved = true; //das ist im Code Zeile 12
    aktual_day = 1;
    aktual_month = 1;
    strcpy(aktual_year, "");
    strcpy(termine_output, "");
    strcpy(db_filename, "");
    

    Aber es will immernoch nicht richtig.
    Code::Blocks-Error:

    ||=== *********(progname), Debug ===|
    \trash_h.cpp | 12 | error: expected constructor, destructor, or type conversion before '=' token
    \trash_h.cpp | 13 | error: expected constructor, destructor, or type conversion before '=' token
    \trash_h.cpp | 14 | error: expected constructor, destructor, or type conversion before '=' token
    \trash_h.cpp | 15 | error: expected constructor, destructor, or type conversion before '(' token
    \trash_h.cpp | 16 | error: expected constructor, destructor, or type conversion before '(' token
    \trash_h.cpp | 17 | error: expected constructor, destructor, or type conversion before '(' token
    ||=== Build finished: 8 errors, 0 warnings ===|
    

    Soll ich eigentlich die trash_h.h auch in #ifndef trash_cpp usw setzen? Ich glaub eher nicht.

    PS: Sorry, aber ich kann erst heut abend wieder hier rein schaun 😞
    PSS: Ich hab grad in meinem C++ von A bis Z nachgeschlagen und rausgefunden, dass extern keine Variablen Deklariert. Also hab ich das mit dem extern in jede .cpp-datei geschrieben und in meine trash_h.h habe ich das extern weggelassen. es kommen die gleichen Fehler 😞
    @interner:

    C++ von A bis Z, Seite 252 schrieb:

    Mit dem Schlüsselwort extern teilen Sie dem Compiler mit, dass die Definition von Variablen oder Funktionen in einer anderen Datei oder einem externen Modul vorgenommen wurde. Mit extern deklarierte Objekte geben nur den Namen bekannt und belegen zunächst noch keinen Speicherplatz. Dies geschieht erst bei der Definition in einer anderen Datei.

    Edit: Ach verdammt, Icarus hat das auch schon geschrieben



  • Nein, include-guards brauchts in .cpp Dateien nicht.

    p.s.:

    strcpy(db_filename, "");
    

    Das geht schneller:

    memset(db_filename, sizeof(char)*30, 0);
    


  • Und warum nicht einfach

    db_filename[0] = '\0';
    

    ? Was dahintersteht, ist ja egal...

    Ich wäre ohnehin für std::string , das macht vieles einfacher.



  • Scorcher24 schrieb:

    p.s.:

    strcpy(db_filename, "");
    

    Das geht schneller:

    memset(db_filename, sizeof(char)*30, 0);
    

    schneller? meinst du das Programm braucht nicht so lang? Weil es ist ja eigentlich mehr text. Und sizeof(char) ergibt doch immer 1, oder? warum braucht man das dann? Oder ist das, damit der Code Portabel wird für Computer auf denen ein Byte zu Beispiel 9 Bit hat?

    Aber eigentlich ist es doch nur Code-Design (memset oder strcpy) und ändert nichts an dem verwirrenden Fehler 😞

    PS: std::string mag ich irgendwie nicht =| Ich find c-strings besser.



  • NOPx90 schrieb:

    Scorcher24 schrieb:

    p.s.:

    strcpy(db_filename, "");
    

    Das geht schneller:

    memset(db_filename, sizeof(char)*30, 0);
    

    schneller? meinst du das Programm braucht nicht so lang? Weil es ist ja eigentlich mehr text. Und sizeof(char) ergibt doch immer 1, oder? warum braucht man das dann? Oder ist das, damit der Code Portabel wird für Computer auf denen ein Byte zu Beispiel 9 Bit hat?

    Aber eigentlich ist es doch nur Code-Design (memset oder strcpy) und ändert nichts an dem verwirrenden Fehler 😞

    PS: std::string mag ich irgendwie nicht =| Ich find c-strings besser.

    Wie meinst du das jetzt mit mehr Text? 😃

    Er ist deswegen schneller weil strcpy und konsorten tendenziell etwas langsamer sind als z.bsp. memset.

    Eigentlich finde ich std::string auch besser, wie Nexus sagte. Warum magst du das nicht? Ist doch viel einfacher und vor allem bist du vor pufferüberläufen besser geschützt. Und kommst nicht in die Gefahr über die Grenzen deines Arrays rauszuschreiben.

    @Nexus
    Wie gesagt, std::string finde ich auch besser. Und ich finde das ganze Array nullen besser als nur abszuschneiden, wenn man schon löscht, was hier wohl die intention des TE war. Um die Daten, also den Inhalt, auch wirklich zu löschen.



  • Scorcher24 schrieb:

    Wie meinst du das jetzt mit mehr Text? 😃

    Ja das eine hat 24 Zeichen und das andere 40, aber ist ja eigentlich auch egal.

    Scorcher24 schrieb:

    Eigentlich finde ich std::string auch besser, wie Nexus sagte. Warum magst du das nicht? Ist doch viel einfacher und vor allem bist du vor pufferüberläufen besser geschützt. Und kommst nicht in die Gefahr über die Grenzen deines Arrays rauszuschreiben.

    Weis auch nicht genau. Vielleicht, weil ich dann keine Ahnung mehr habe was der Computer macht? Weis nicht genau.

    Was bedeutet eigentlich der Error?:

    expected constructor, destructor, or type conversion before '=' token
    

    Eigentlich ist der doch unlogisch



  • NOPx90 schrieb:

    Weis auch nicht genau.

    Dann würde ich mir std::string mal genauer anschauen. Auch wenn du dich entschliesst, die Klasse nicht zu benutzen, gibt es wahrscheinlich doch einige interessante Punkte.

    NOPx90 schrieb:

    Vielleicht, weil ich dann keine Ahnung mehr habe was der Computer macht?

    Naja, viel mehr erfährst du bei char* nicht. Und das, was du siehst, hast du schnell einmal gesehen 😉

    Soll heissen, char -Arrays sind sicher gut, um etwas über die Hintergründe zu erfahren. Nach einiger Zeit kennst du diese aber und weisst somit auch, wie std::string funktioniert. Und sobald es um den produktiven Einsatz geht, lohnt es sich nicht mehr, alles von Hand zu machen, was einem die Standardbibliothek bereits abnimmt. Das bringt nur unnötigen Aufwand und Fehler mit sich.

    NOPx90 schrieb:

    Was bedeutet eigentlich der Error?:[code]expected constructor, destructor, or type conversion before '=' token

    Irgendein Syntaxfehler. Zeig mal den Kontext, in dem er auftritt.



  • Äääähm um den geht doch der Thread. Schau mal auf der ersten Seite den letzten Post an.
    Und std::string kann ich mir mal anschaun, aber in diesem Projekt werde ich noch bei den C-Strings bleiben(vorerst).



  • NOPx90 schrieb:

    Äääähm um den geht doch der Thread. Schau mal auf der ersten Seite den letzten Post an.

    Äh ja, ich sprach aber vom Kontext, den du uns leider nicht vollständig gezeigt hast. Stehen die Anweisungen in einer Funktion? Gibt es Header-Guards oder sonstige Makros? Steht vor dem Code etwas Anderes, das du uns unterschlagen hast? Was wird wovon inkludiert?

    Also poste ein komplettes Codebeispiel, das nur noch deinen Fehler enthält. Halte den Code aber trotzdem so klein wie möglich.



  • Nexus schrieb:

    NOPx90 schrieb:

    Äääähm um den geht doch der Thread. Schau mal auf der ersten Seite den letzten Post an.

    Äh ja, ich sprach aber vom Kontext, den du uns leider nicht vollständig gezeigt hast. Stehen die Anweisungen in einer Funktion? Gibt es Header-Guards oder sonstige Makros? Steht vor dem Code etwas Anderes, das du uns unterschlagen hast? Was wird wovon inkludiert?

    Anweisungen stehen nicht in einer Funktion.
    Header-Guards gibt es(steht aber schon weiter oben)
    Es steht nichts anderes in der Trash_h.h. Nur das:
    [spoiler]

    //Trash_h.h
    #ifndef TRASH_H
    #define TRASH_H
    #include "datenbank_h.h"
    //Funktion zum testen ob eine Datei existiert
    bool fexists(const char *filename);
    
    //Globals
    bool saved;
    char str_date[30];
    int aktual_day, aktual_month;
    char aktual_year[5];
    char termine_output[MAX_CHARS];
    char db_filename[30];
    datenbank db;
    //Globals ende
    
    #endif
    
    //trash_h.cpp
    #include "trash_h.h"
    #include "datenbank_h.h"
    #include <fstream>
    using namespace std;
    
    bool fexists(const char *filename)
    {
      ifstream ifile(filename);
      return ifile;
    }
    
    saved = true;
    aktual_day = 1;
    aktual_month = 1;
    strcpy(aktual_year, "");
    strcpy(termine_output, "");
    strcpy(db_filename, "");
    

    [/spoiler]

    Was wird wovon inkludiert?

    main.cpp:

    #include <windows.h>
    #include <stdio.h>
    #include <time.h>
    #include "datenbank_h.h"
    #include "trash_h.h"
    

    datenbank_h.cpp:

    #include <iostream>
    #include <fstream>
    #include <Windows.h>
    #include "datenbank_h.h"
    #include "trash_h.h"
    using namespace std;
    

    datenbank_h.cpp:

    //none
    

    trash_h.cpp:

    #include "trash_h.h"
    #include "datenbank_h.h"
    #include <fstream>
    using namespace std;
    

    trash_h.h:

    #include "datenbank_h.h"
    

    Nexus schrieb:

    Also poste ein komplettes Codebeispiel, das nur noch deinen Fehler enthält. Halte den Code aber trotzdem so klein wie möglich.

    Was meinst du mit komplett? Weil ich will meinen kompletten Source-Code lieber nicht posten (davon abgesehen sind es ca 800-900 Zeilen) Oder meinst du nur die globalen Definitionen oder ähnliches?



  • Willst Du C oder C++ programmieren? Entscheide dich bitte.
    Wozu die ganzen globalen? Da ist ein Singleton Pattern noch vernünftiger. Das ist auch eine globale, aber man kann wenigstens vernünftige Zugriffe einbauen.

    Also erstmal ne Korrektur:

    // Trash_h.h:
    
    //Globals
    extern bool saved;
    extern char str_date[30];
    extern int aktual_day, aktual_month;
    extern char aktual_year[5];
    extern char termine_output[MAX_CHARS];
    extern char db_filename[30];
    extern datenbank db;
    //Globals ende
    
    //Trash_h.cpp:
    bool saved = true;
    int aktual_day = 1;
    int aktual_month = 1;
    char aktual_year[5];
    char termine_output[MAX_CHARS];
    char db_filename[30];
    datenbank db;
    

    So wäre das erstmal die richtige Definition. strcpy einfach im globalen Bereich stehen haben geht nicht. Pack das in eine init-funktion oder, weil wir im C++ Forum sind, am besten in den Konstruktor. Aber in C++ braucht man strcpy nur bedingt.
    Das hier wäre C++:

    class Trash
    {
    public:
      Trash()
      : saved(true), day(1), month(1), year(1900)
      {}
    
      bool saved = true;
      int day;
      int month;
      int year;
      std::string termine_output;
      std::string db_filename;
      datenbank db;
    
    };
    
    // Reimplementierung als singelton:
    class Trash
    {
    private:
      Trash()
      : saved(true), day(1), month(1), year(1900)
      {}
    
      Trash(const Trash&) {}
      Trash& operator=(const Trash& rhs) { return *this; }
    
    public:
      static Trash& getInstance()
      {
          static Trash OnlyOne;
          return OnlyOne;
      }
    
      bool saved = true;
      int day;
      int month;
      int year;
      std::string termine_output;
      std::string db_filename;
      datenbank db;
    
    };
    

    Jetzt kannst du über Trash::getSingleton().saved als bsp, auf alle Member zugreifen und die Werte bleiben, da die Funktion statisch ist.
    Wie du das genau organisierst musst du selber beschliessen, ich kenne hier nur Fragmente deines Codes.



  • Willst Du C oder C++ programmieren? Entscheide dich bitte.

    Sorry, aber das weis ich auch nicht so genau. Jede der beiden Sprachen hat Vorteile. Und es ist ja so ungefähr das gleiche. Ich weis schon dass man das nicht mischen darf... ich schäm mich ja schon.

    strcpy einfach im globalen Bereich stehen haben geht nicht.

    Omg bin ich dumm, dass ich das vergesse 😞 *schäm*

    Aber danke an alle! Ich habs jetzt geschafft. es lag an dem extern (sry, mit dem hab ich noch nie gearbeitet).



  • NOPx90 schrieb:

    Anweisungen stehen nicht in einer Funktion.

    In C und C++ müssen sie das aber. Was ausserhalb stehen kann, sind Deklarationen.

    Hier liegt auch dein Fehler.



  • NOPx90 schrieb:

    Jede der beiden Sprachen hat Vorteile.

    Und welche Vorteile hat C? Mir fällt im Moment keiner ein.



  • 314159265358979 schrieb:

    Und welche Vorteile hat C? Mir fällt im Moment keiner ein.

    Das kommt auf das Anwendungsgebiet an. Frag mal die Embedded-Entwickler, die sehr Hardware-nahen, höchstperformanten Code produzieren müssen. Da wird viel in C geschrieben (mal ungeachtet der Tatsache, obs von einem C- oder C++-Compiler übersetzt wird)



  • pumuckl schrieb:

    314159265358979 schrieb:

    Und welche Vorteile hat C? Mir fällt im Moment keiner ein.

    Das kommt auf das Anwendungsgebiet an. Frag mal die Embedded-Entwickler, die sehr Hardware-nahen, höchstperformanten Code produzieren müssen. Da wird viel in C geschrieben (mal ungeachtet der Tatsache, obs von einem C- oder C++-Compiler übersetzt wird)

    Auf nem handelsüblichen PC hat C keine Daseinsberechtigung mehr, abgesehen vom Betriebssystem und dessen Komponenten. Ich bezweifle auch, dass C schneller ist, als C++, insbesondere mit C++0x wird C++ ziemlich sicher schneller sein als C.



  • 314159265358979 schrieb:

    NOPx90 schrieb:

    Jede der beiden Sprachen hat Vorteile.

    Und welche Vorteile hat C? Mir fällt im Moment keiner ein.

    Man kann über die Geschwindigkeit C vs C++ den x-ten Flamewar führen 🙄


Anmelden zum Antworten