Die meistgestellten Fragen



  • Update durch Arcoth: Diese Liste wird momentan recht einstimmig als veraltet betrachtet und ist dementsprechend fortan kein Sticky mehr.

    -----------------------------------------------------------

    Da im Forum manche Fragen mit einer gewissen Regelmäßigkeit aufkommen, sammle und beantworte ich sie in diesem Thread.

    1. Wie kann ich eine richtige Oberfläche programmieren?
    2. Wenn ich mein Programm ausführe, passiert gar nichts/flackert nur kurz was auf! Wieso?
    3. Ich habe den Code 1:1 aus dem Buch abgeschrieben. Wieso funktioniert der nicht?
    4. Ich will mit ganz großen Zahlen rechnen. Wie geht das?
    5. Ich hab ein Template. Jetzt bekomm ich aber den Fehler "nicht aufgelöstes externes Symbol". Warum?
    6. Ich blicke bei den ganzen Zeichenketten nicht durch. Was soll ich benutzen?
    7. Wenn ich Sachen inkludiere, kommen Fehler, in denen "undeclared identifier" oder sowas ähnliches steht. Was tun?
    8. Ich will eine Zahl oktal/hexadezimal speichern. Wie geht das?
    9. Wieso bekomme ich immer ein "warning: no newline at end of file"?
    10. C nicht mit C++ vermischen
    11. Was ist der Unterschied zwischen Klassentemplate und Templateklasse?

    1. Wie kann ich eine richtige Oberfläche programmieren?

    Das Problem bei dieser Frage ist, dass es nicht zu Standard-C++ gehört, GUIs zu programmieren. Da gibt es viele verschiedene Frameworks für. Windows? Da gibt es die WinAPI, aber die ist nicht C++. Die MFC, aber die ist nicht modernes C++ und vor allem nicht kostenfrei. WxWidgets, GTKmm, QT und andere. Linux? Embedded? Es kommt immer darauf an, was man eigentlich will.

    Kurzum: Es gibt viele Wege zum Ziel, aber keiner davon führt an den Grundlagen von C++ vorbei. Links gibt es viele, die meisten via Google. In meinen Augen sind die besten Links die Referenzen der o.g. Frameworks, nur dass Referenzen sich am besten lesen, wenn man bereits weiß, was man tut.

    Vielen Dank an LordJaxom für diese Antwort.

    2. Wenn ich mein Programm ausführe, passiert gar nichts/flackert nur kurz was auf! Wieso?

    Schau mal in der Konsolen-FAQ in den Thread Automatisches Schließen verhindern. Desweiteren gibts es (kostenlose) IDEs, die das Problem von selbst lösen. Als Beispiele seien Code::Blocks und Visual C++ 2005 Express Edition genannt.

    Eine dritte Methode ist das Erstellen einer Batch-Datei, die das eigentliche Programm aufruft. Das geht unter Windows folgendermaßen:
    1. Im Explorer (also der ganz normale Datei-Browser) im Menü auf Extras -> Ordneroptionen.
    2. Dann auf "Ansicht" und bei "Erweiterte Einstellungen" den Haken bei "Erweiterung bei bekannten Dateitypen ausblenden" entfernen.
    3. OK
    4. Datei -> Neu -> Textdokument
    5. Einen Namen, der mit ".bat" endet, eingeben, wie z.B. "Starter.bat"
    6. Rechtsklick auf die bat-Datei und Bearbeiten auswählen.
    7. Im Editor folgendes eingeben:

    meinprogramm.exe
    pause
    

    Für "meinprogramm" den Namen des Programms eingeben.
    8. Datei speichern und Editor beenden.
    9. Doppelklick auf die bat-Datei und das Programm bleibt danach offen!

    Als vierte Möglichkeit sei "Open Command Window Here" aus den Windows XP Powertoys genannt. Mit diesem öffnet man schnell eine Konsole in dem gewünschten Verzeichnis und braucht nur noch den Programmnamen einzugeben. Anders als bei den vorherigen Lösungen beendet sich das eigene Programm zwar, die Ausgabe bleibt aber dennoch sichtbar, da die Konsole ja nicht geschlossen wird.

    3. Ich habe den Code 1:1 aus dem Buch abgeschrieben. Wieso funktioniert der nicht?

    Viele Bücher halten sich nicht an den C++-Standard. Die neueren Compiler allerdings halten ihn schon ziemlich genau ein. Daher kann es sein, dass dein Buch/Tutorial etwas benutzt, was dein Compiler nicht unterstützt. Typische Beispiele:

    void main() // oder: main()
    // ersetzen durch:
    int main()
    
    #include <iostream.h>
    // ersetzen durch:
    #include <iostream>
    using namespace std;
    
    #include <stdio.h>
    // ersetzen durch:
    #include <cstdio>
    using namespace std;	// analog dazu: assert.h, ctype.h, locale.h, time.h, math.h und weitere
    

    Wenn man die Zeile "using namespace std;" weglässt, wie man es in Header-Dateien machen sollte, muss man den sog. qualifizierten Namen schreiben, d. h. ein "std::" vor den Namen setzen. Beispiel:

    #include <string>
    
    std::string foo = "bar"
    

    Anmerkung: Die alten Header existieren auch im Standard noch, sie sind allerdings als "deprecated" gekennzeichnet und man darf sich nicht wundern, wenn der Compiler eine entsprechende Warnung ausgibt.

    4. Ich will mit ganz großen Zahlen rechnen. Wie geht das?

    Oftmals brauchst du gar nicht mit so großen Zahlen zu rechnen (z. B. wenn dich nur das Verhältnis zweier Zahlen interessiert oder alle Zahlen in einem kleinen Bereich liegen) oder hast noch genug andere Probleme, um die du dich eher kümmern solltest als große Zahlen. Wenn du dir dennoch sicher bist, dass du riesige Zahlen brauchst (größer als 2^64 = 18.446.744.073.709.551.616), kannst du das zum Beispiel mit Gnu MP tun.

    Frag jetzt nicht, wie man das mit GMP macht. Dafür gibts die Doku!

    5. Ich hab ein Template. Jetzt bekomm ich aber den Fehler "nicht aufgelöstes externes Symbol". Warum?

    Meistens kommt diese Frage, wenn der Fragesteller das Template aufgeteilt hat, wie er es von Klassen gewohnt ist: Klassendefinition in eine Header-Datei, Memberdefinitionen in eine entsprechende cpp-Datei. Allerdings ist ein Template nur eine Vorlage, die richtigen Klassen/Funktionen erstellt der Compiler erst beim Kompilieren nach dieser Vorlage. Nun ist es wohl klar, dass dem Compiler dafür die gesamte Vorlage zur Verfügung stehen muss. Er sieht aber nur die zu kompilierende Quellcode-Datei inklusive aller eingebundenen Header (man spricht von einer Übersetzungseinheit), die Definitionen der Member werden deshalb nicht gefunden -> nicht aufgelöstes externes Symbol.

    Mögliche Workarounds:
    - alles direkt in die Klassendefinition einfügen; das wird bei großen Templates ziemlich unübersichtlich
    - am Ende der Header-Datei eine Implementationsdatei inkludieren, in der die Member definiert werden (üblicherweise hat diese die Endung .impl)
    - die gewünschten Template-Instanzen explizit definieren
    - das Schlüsselwort export benutzen; allerdings gibt es kaum Compiler, die dieses unterstützen

    6. Ich blicke bei den ganzen Zeichenketten nicht durch. Was soll ich benutzen?

    Anfangs wird man meist mit zwei verschiedenen Typen von Zeichenketten konfrontiert: char* mit den entsprechenden Funktionen in <cstring> (bzw. <string.h>), und string aus <string>.

    Benutze am besten den string aus <string>. Der andere Typ wird quasi nur noch für Konstanten verwendet. Wenn dir irgendwann mal langweilig ist, kannst du dir auch diesen mal angucken.

    Jetzt gibt es allerdings ein Problem: Die Standardbibliothek arbeitet mit (const) char*. Das merkst du zum Beispiel, wenn du eine Datei öffnen willst:

    string name = "test.txt";
    ifstream in(name);	// Fehler!
    

    Den String name muss man erst konvertieren, bevor man ihn bei ifstream verwenden kann. Das sieht dann so aus:

    string name = "test.txt";
    ifstream in(name.c_str());
    

    Einen guten Artikel über std::string gibt es im Magazin.

    7. Wenn ich Sachen inkludiere, kommen Fehler, in denen "undeclared identifier" oder sowas ähnliches steht. Was tun?

    Der Inhalt sämtlicher Standard-Headerdateien (s. dazu auch 3.) liegt im Namespace std. Um dem Compiler zu sagen, dass er auch in diesem Namespace nach Namen suchen soll, schreibt man folgende Zeile (üblicherweise unter den #include-Anweisungen):

    using namespace std;
    

    8. Ich will eine Zahl oktal/hexadezimal speichern. Wie geht das?
    Die Fragestellung ist falsch formuliert. Zahlen werden nämlich nicht standardmäßig dezimal gespeichert, sondern dezimal ausgegeben. Intern kann der Computer die Zahlen eh nur binär abspeichern. Also suchst du eine Option, um eine Zahl oktal/hexadezimal auszugeben. Das geht so:

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int zahl = 42;
    	cout << zahl << endl;
    	cout << hex << zahl << endl;
    	cout << oct << zahl << endl;
    }
    

    9. Wieso bekomme ich immer ein "warning: no newline at end of file"?

    Dreimal darfst du raten...

    Der Standard empfiehlt, dass eine Quellcode-Datei mit einer leeren Zeile abgeschlossen wird. Der Compiler gcc warnt, wenn das nicht der Fall ist.

    10. C nicht mit C++ vermischen
    (Danke an CodeFinder für diesen Punkt)

    Beispiel a) Casts:

    fstream fStr("C:\\demo.dat");
    // ...
    unsigned long ulNummer;
    fStr.read(reinterpret_cast<char*>(&ulNummer), sizeof(unsigned long)); // C++
    // und nicht:
    // fStr.read((char*)&ulNummer), sizeof(unsigned long)); // C
    // ...
    

    Beispiel b) File Handling:

    // Filestreams statt FILE-Structs
    fstream fStr(...); // C++
    // und nicht:
    // FILE *pFile; // C
    

    Beispiel c) Speicherreservierung:

    // new statt malloc und Kohorten
    Typ* tName= new Typ[Anzahl]; // C++
    // und nicht:
    // Typ* tName = (Typ*)malloc(Anzahl * sizeof(Typ)); // C
    

    11. Was ist der Unterschied zwischen Klassentemplate und Templateklasse?
    Wenn man über Templates spricht, ist es manchmal wichtig, eine gemeinsame Terminologie zu haben. Der Ausdruck Klassentemplate beschreibt eine Schablone für eine Familie von Klassen. Templateklasse wird leider auch manchmal als Synonym für Klassentemplate benutzt, bezeichnet aber eigentlich eine Klasse, die aus der Vorlage (dem Template) erzeugt wurde bzw. eine Spezialisierung des Templates.

    ----------

    Anregungen, Kritik und Verbesserungsvorschläge sind erwünscht.

    MfG,

    Michael E.



  • zu 2.

    Würde ich noch hinzufügen:
    "Besorg dir einen ordentlichen Compiler, der das automatisch macht!
    Visual C++ 6 -> Visual C++ 2005 Express Edition
    Dev-C++ -> Code::Blocks"
    Ist für Anfänger einfacher. Außerdem funktioniert das in der FAQ mit ignore nicht immer, besser ist mit sync.

    mfg.



  • Ich glaube nicht, dass man Leuten vorschreiben sollte, welchen Compiler (bzw. hier eher welche GUI) sie verwenden. Der erste Fall ist ja noch verständlich (wenn auch die meisten Anfängerfehler _nichts_ damit zu tun haben), aber Dev-C++ und Code::Blocks verwenden schließlich AFAIK beide den gcc.
    Ich könnte genauso gut sagen: "Verwendet gefälligst alle Vim, weil ich das auch tue". Keine gute Idee.

    @ Michael E.
    Prima Sache, danke für die Arbeit. Wenn das Sticky gemacht wird animiert es vielleicht mehr Nutzer sich vorher zu Informieren als die FAQs (die IMHO _sehr_ unübersichtlich sind).
    Ich schau mal, ob ich noch mehr immer wiederkehrende Fragen finde.

    /edit:
    Bei Pkt. 1 fehlt ein 'e' 😉
    Punkt 3 solltest du noch mal überarbeiten. Ein Hinweis darauf, dass man using namespace nicht in Headern macht fehlt und

    Als Faustregel gilt, dass aus <xxxxxx.h> ein <cxxxxxx>

    stimmt so nicht. Aus iostream.h wurde nicht ciostream, es fehlt der Hinweis darauf, dass die C-Header gemeint sind. Der Teil mit <conio.h> erübrigt sich, wenn der Leser Punkt 2 beherzigt hat.



  • .filmor schrieb:

    Ich glaube nicht, dass man Leuten vorschreiben sollte, welchen Compiler (bzw. hier eher welche GUI) sie verwenden. Der erste Fall ist ja noch verständlich (wenn auch die meisten Anfängerfehler _nichts_ damit zu tun haben), aber Dev-C++ und Code::Blocks verwenden schließlich AFAIK beide den gcc.

    Sry, ich meinte IDE. Und bei Dev-C++ zu Code::Blocks ist halt der Vorteil, das Code::Blocks die Konsole nicht automatisch schließt. Ist vielleicht kein großer Vorteil, trotzdem kriegen es viele Einsteiger nicht hin, bei jedem verlassen im Code, das hinzuschreiben. Vor allem wenn sie mehrere returns in main() haben (oder auch irgentwo ein exit(0) eingebaut haben) sind sie schnell frustriert. Bedenke: ->Anfänger<-fragen. Das sind halt meistens Leute mit Visual C++ 6 und Dev-C++. Das finde ich einfach lästig, wenn die dann mit Code ankommen, wo sie das cin.get() falsch postiert haben.

    mfg.



  • @joomoo Hast du da ein Beispiel aus diesem Forum für? Ich denke, ein klein bisschen Denken kann man auch von Anfängern erwarten.

    @Michael E.
    Grundlagen des Dateihandlings mit fstreams und ein Link auf die stringstream-FAQ wären vielleicht noch angebracht.



  • .filmor schrieb:

    Als Faustregel gilt, dass aus <xxxxxx.h> ein <cxxxxxx>

    stimmt so nicht. Aus iostream.h wurde nicht ciostream, es fehlt der Hinweis darauf, dass die C-Header gemeint sind.

    das schöne an faustregeln: sie können auch mal falsch sein, ohne falsch zu sein 😉 er hat den fall ja schließlich auch bereits im code behandelt. ich halte eher die bemerkung über <string.h> und konsorten für ungünstig. esgeht ja nicht darum, welche header verwendet werden, sondern mit welcher art strings man arbeitet.



  • Häufig gestellt wird im Moment wohl auch

    "Ich habe eine Variable [ersetzbar durch Funktion] in meine .h-Datei geschrieben, und bekomme jetzt immer 'Multiple Definition'-Fehler". Quasi der Komplementärfall zu 5. 😉



  • .filmor schrieb:

    @joomoo Hast du da ein Beispiel aus diesem Forum für?

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-150600-and-postdays-is-0-and-postorder-is-asc-and-start-is-20.html
    gab's noch mehr, nur finde ich jetzt nicht auf die schnelle.

    Obwohl ich persönlich nicht zu den Leuten gehöre, höre ich hier des öfteren das Dev-C++ totaler schrott sein soll, deswegen ist es doch nicht schlecht einem Anfänger schon gleich ne ordentlich IDE zu geben, oder?

    Ich mein: Was spricht denn dagegen den Visual-C++-6-Leuten den neuen 2005er zu empfehlen? Wird hier sowieso sehr oft getan, dann schreiben wir's dazu, oder?

    Ich denke, ein klein bisschen Denken kann man auch von Anfängern erwarten.

    Wenn du noch nie programmiert hast, ist es erstmal frustierend, dass du schon drei Zeilen, die du 0 verstehst, an die richtige stelle tun sollst, nur damit ein "Hallo Welt" funktioniert. Außerdem muss man das gleiche ja denn bei nem return in main oder einem exit/abort wieder davor packen.

    mfg.



  • gut, und nun erkläre den anfängern noch klassen und kapselung 😉



  • joomoo schrieb:

    .filmor schrieb:

    @joomoo Hast du da ein Beispiel aus diesem Forum für?

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-150600-and-postdays-is-0-and-postorder-is-asc-and-start-is-20.html
    gab's noch mehr, nur finde ich jetzt nicht auf die schnelle.

    Ok, du hast wohl recht.

    joomoo schrieb:

    Obwohl ich persönlich nicht zu den Leuten gehöre, höre ich hier des öfteren das Dev-C++ totaler schrott sein soll, deswegen ist es doch nicht schlecht einem Anfänger schon gleich ne ordentlich IDE zu geben, oder?

    Ich hatte mit Dev-C++ nie wirklich Probleme. Wer meint, dass müsse man demjenigen sagen kann das ja tun, wenn der betreffende fragt.

    joomoo schrieb:

    Ich mein: Was spricht denn dagegen den Visual-C++-6-Leuten den neuen 2005er zu empfehlen? Wird hier sowieso sehr oft getan, dann schreiben wir's dazu, oder?

    Aber meistens wirds da dazu geschrieben, wo es auch passt, nämlich wenn ein Compilerfehler auftritt, der von dem miesen VC6-Compiler herrührt. Diese Fälle sind aber AFAIK (ich benutze schon immer gcc) nicht das, was einem C++-Anfänger direkt vor der Nase rumspringt. Wenn er bei Metaprogrammierung angekommen ist hat er denke ich genug Verständnis dafür, welchen Compiler er nehmen sollte.

    joomoo schrieb:

    Ich denke, ein klein bisschen Denken kann man auch von Anfängern erwarten.

    Wenn du noch nie programmiert hast, ist es erstmal frustierend, dass du schon drei Zeilen, die du 0 verstehst, an die richtige stelle tun sollst, nur damit ein "Hallo Welt" funktioniert. Außerdem muss man das gleiche ja denn bei nem return in main oder einem exit/abort wieder davor packen.

    Die drei Zeilen werden in dem Artikel aber sinnvoll in eine Funktion gepackt, die dann sehr leicht verständlich ist.

    Tuxinator schrieb:

    gut, und nun erkläre den anfängern noch klassen und kapselung 😉

    !(OOP == C++) :p



  • Vielleicht noch "Einmal Zahl nach String und zurück" (http://www.c-plusplus.net/forum/viewtopic-var-t-is-39488.html).
    Steht zwar in den FAQs auf der ersten Seite, es kommen aber trotzdem regelmäßig Fragen zu dem Thema.
    Manchmal frage ich mich, ob überhaupt jemand in die FAQs schaut...

    .filmor schrieb:

    Ich denke, ein klein bisschen Denken kann man auch von Anfängern erwarten.

    👍



  • es geht hier um c++,gell?

    Vergiss es. Solange du die Grundlagen nicht kannst (und zu den Grundlagen gehört mehr als schon mal ne Klasse erstellt zu haben!), hat es keinen Sinn, sich mit Oberflächen zu beschäftigen.



  • Tuxinator schrieb:

    es geht hier um c++,gell?

    Vergiss es. Solange du die Grundlagen nicht kannst (und zu den Grundlagen gehört mehr als schon mal ne Klasse erstellt zu haben!), hat es keinen Sinn, sich mit Oberflächen zu beschäftigen.

    Ja genau, und deshalb sind Klassen fundamental, also überdenke deinen Beitrag besser nochmal.



  • Tuxinator schrieb:

    es geht hier um c++,gell?

    Vergiss es. Solange du die Grundlagen nicht kannst (und zu den Grundlagen gehört mehr als schon mal ne Klasse erstellt zu haben!), hat es keinen Sinn, sich mit Oberflächen zu beschäftigen.

    Jap.

    Ich guck mal, was ich noch hinzufüge/entferne. Mein Ziel ist es nämlich nicht, eine große Sammlung zu erstellen, in dem möglichst viele häufig gestellte Fragen beantwortet werden (dafür sind schließlich die FAQ da), sondern einen kleinen Text zu schreiben, der wenn möglich nur das Wichtigste enthält.

    Alle Änderungen nehm ich im OP vor.



  • IMHO solltest du, wenn du das schon machst, vllt. die Top 10 der meistgestellten Fragen rausfinden und in einem Post mit den entsprechenden Einträgen der FAQ verlinken, also:

    1. Warum verschwindet mein Konsolenfenster sofort?
      ...


  • .filmor schrieb:

    Die drei Zeilen werden in dem Artikel aber sinnvoll in eine Funktion gepackt, die dann sehr leicht verständlich ist.

    Was wenn der Anfänger noch nicht (eigene) Funktionen gehabt hat? Ich seh hier meistens nur Leute die cin.get() und system("PAUSE") benutzen, und das wahrscheinlich auch deswegen, weil ihnen der Code aus der FAQ nicht ganz klar wird. Die Funktion wait() muss ja noch in der main-Funktion aufgerufen werden (und zwar vor return, wer noch keine Funktionen hat, weiß das vielleicht auch nicht).
    Auch finde ich es total lästig, immer ein wait() an allen meinen programm-abbrüchen einzufügen. Und bei einem assert oder /0 bringst ja dann sowieso nichts mehr.
    Deswegen: Was spricht denn dagegen? Man könnte diese IDE-Tipps ja nur als Empfehlung hinschreiben und nichts als zwingende Aufforderung.

    mfg.



  • Zu Punkt 6: IMHO müsste es heissen "Die Standardbibliothek arbeitet mit const char*", jedenfalls in dem Zusammenhang.



  • Hallo

    Michael E. schrieb:

    void main()
    // ersetzen durch:
    int main()
    
    #include <iostream.h>
    // ersetzen durch:
    #include <iostream>
    using namespace std;	// analog dazu: <string.h> -> <string>
    
    #include <stdio.h>
    // ersetzen durch:
    #include <cstdio>
    using namespace std;	// analog dazu: assert.h, ctype.h, locale.h, time.h, math.h und weitere
    

    <string.h> wird doch aber nicht zu <string>, sondern zu <cstring>.

    chrische



  • Hm, ich würd's sinnvoller finden (wegen redundanz u. übersichtlichkeit), wen man im C++-Froum soetwas wie einen "Indexthread" zum FAQ sticky macht in welchem man für bestimmte Probleme auf den/die passende(n) FAQ Threads verweist. Dann würde man sich nämlich die Posts sparen, in denen wieder 'mal jemand meint, er habe in der FAQ gesucht und gesucht und doch nix gefunden (obwohl der Rest der Welt weiß, daß dort steht was er sucht).

    Greetz, Swordfish

    @chrische: mein ich auch!!



  • Swordfish schrieb:

    Hm, ich würd's sinnvoller finden (wegen redundanz u. übersichtlichkeit), wen man im C++-Froum soetwas wie einen "Indexthread" zum FAQ sticky macht in welchem man für bestimmte Probleme auf den/die passende(n) FAQ Threads verweist. Dann würde man sich nämlich die Posts sparen, in denen wieder 'mal jemand meint, er habe in der FAQ gesucht und gesucht und doch nix gefunden (obwohl der Rest der Welt weiß, daß dort steht was er sucht).

    Greetz, Swordfish

    @chrische: mein ich auch!!

    stiime zu. man kann ja abwägen: wenn die frage in einer zeile zu beantworten ist, kann man sie hier beantworten, sonst nimmt man einen link.


Gesperrt