"Fehler: »nullptr« wurde in diesem Gültigkeitsbereich nicht definiert" Was mach ich falsch?
-
Anjuta = GCC = Der läuft auch in neueren Versionen standardmäßig im C++03 Modus.
Lösung: -std=c++0x bzw -std=c++11
-
Hallo,
vielen Dank für die schnelle Hilfe.
Leider hab ich noch nicht genug Fachvokabular und Knowhow um alle Tips hier zu verstehen.Ich hab das Programm jetzt noch einmal mit 0 anstelle von nullptr geschrieben.
Was mir dieses mal aufgefallen ist, wenn ich beim ausführen Buchstaben als variable eingebe dreht mein Programm durch. Heißt das es mir die Auswahl in einer endlosen Schleife wiedergibt. Verwende ich allerdings Zahlen funktioniert alles.@Ethon, kannst Du mir bitte genau sagen wo ich c++11 in Anjuta aktiviere?
Wenn ich dich richtig verstehe ist das ein Befehl den ich im Programm als Header angebe? Hab es schon versucht, aber irgendwas mach ich falsch.Grüße
Matt
-
Hast du schon mal selbst etwas mit dem GCC kompiliert? Meistens wird eine recht lange Befehlszeile übergeben wie zb
g++ -o MeinProgramm -O2 -I./include test.cpp
Was so viel bedeutet wie dass dem g++ gesagt wird, dass er die erstellte Datei als MeinProgramm speichern, Optimierungslevel 2 verwenden, den Ordner ./include zum Suchpfad hinzufügen soll, für das Kompilieren der Datei test.cpp.
Das -std=c++0x gehört an irgendeinen Platz in der Befehlszeile bevor die Quelldatei aufgelistet wird.
Ich habe nur leider keine Ahnung von Anjuta - kannst du da irgendwo deine eigenen Compilerflags übergeben?Ich sehe gerade, bei Anjuta kannst du die CXX_FLAGS setzen. Zu denen gehört dasd -std=c++0x .
https://developer.gnome.org/anjuta-build-tutorial/3.2/figures/configure-dialog.png.en
-
matthn80 schrieb:
Leider hab ich noch nicht genug Fachvokabular und Knowhow um alle Tips hier zu verstehen.
Dann frag nach, was du nicht verstehst. Sind nämlich gute Tipps und durch das Nachfragen erweiterst du dein Wissen.
matthn80 schrieb:
Was mir dieses mal aufgefallen ist, wenn ich beim ausführen Buchstaben als variable eingebe dreht mein Programm durch. Heißt das es mir die Auswahl in einer endlosen Schleife wiedergibt. Verwende ich allerdings Zahlen funktioniert alles.
Das Problem ist, dass beim ersten Einlesen du einen
int
einliest. Heisst es wird eine Zahl erwartet. Wenn keine Zahl kommt, geht der Stream (std::cin
) in einen Fehlerzustand und solange er in diesem Fehlerzustand ist, wird jede Leseoperation auf der Stelle abgebrochen.Du musst solche Fehler abfangen und entsprechend verarbeiten. Dazu helfen dir Funktionen wie
fail
,good
undclear
. Du kannst aber nicht einfach nur den Fehlerzustand zurücksetzen, da die Eingabe, welche nicht verarbeitet werden konnte, noch im Stream drin ist. Diese Eingabe muss du somit zuerst verwerfen, was du wiederrum darüber machen kannst:std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Siehe auch: http://en.cppreference.com/w/cpp/io/basic_istream/ignore
Am Ende bietet sich meistens allerdings an, dass du bei solchen Eingaben immer Zeilenweise einliest mit
std::getline
. Die Chance, dassgetline
fehlschlägt, ist äusserst klein und könnte man allenfalls in Zukunft ebenfalls einfach abfangen. Wenn du die Linie hast, kannst du sie danach in eine Zahl umwandeln und die Fehler abfangen, siehe dazu:
http://www.c-plusplus.net/forum/39488matthn80 schrieb:
Wenn ich dich richtig verstehe ist das ein Befehl den ich im Programm als Header angebe? Hab es schon versucht, aber irgendwas mach ich falsch.
Nein, das sind Kompileroptionen (Kommandozeilen-Parameter). Ich kenne leider Anjuta nicht, aber das sollte man irgendwo unter den Einstellungen oder Projekt-Eigenschaften einstellen können.
Grüssli
-
Dravere schrieb:
Du musst solche Fehler abfangen und entsprechend verarbeiten. Dazu helfen dir Funktionen wie
fail
,good
undclear
.Hmm. Meistens erledigt man das über den Konvertierungsoperator. So ist das auch Gedacht.
-
Andere Tipps:
- für
std::string
musst du auch irgendwo mal#include <string>
geschrieben haben - In C++ musst du Variablen nicht alle am Anfang einer Funktion definieren. Du kannst sie "lokaler" definieren, was einserseits IMHO die Lesbarkeit erhöht und andererseits recht praktisch sein, wenn du einer Variable eine kürzere Lebenszeit gibst. Ich denke da speziell an
hilfsZeiger
undfreund
. - Datenstrukturen wie verkette Listen (und mehr) gibt es ja schon fertig in der Standardbibliothek. Man muss und sollte in der Hinsicht das Rad nicht neu erfinden.
- Vermeide Funktionen die ganz viele Dinge auf einmal tun. Gliedere solche Sachen aus. Halte Funktionen klein und rufe ggf andere Funktionen darin auf, die entsprechende Namen haben, damit der Leser sich ein Bild davon machen kann, was darin passiert.
#include <iostream> #include <string> #include <vector> using namespace std; struct WoW_t { string klasse; string nickname; unsigned int freund_seit; }; void eingabe(WoW_t & freund) { cout << "Klasse : "; cin >> freund.klasse; cout << "Name : "; cin >> freund.nickname; cout << "Verbund : "; cin >> freund.freund_seit; } void anzeigen(vector<WoW_t> const& freunde) { cout << "\nDeine WoW-Freunde\n"; for (auto& freund : freunde) { cout << "Klasse : " << freund.klasse; cout << "\nName : " << freund.nickname; cout << "\nVerbund: " << freund.freund_seit << endl; } } int main() { vector<WoW_t> freunde; int wahl; do { cout << "-1- Freund hinzufuegen\n"; cout << "-2- Freunde ausgeben\n"; cout << "-3- Beenden\n"; cout << "Deine Wahl: "; wahl = 3; cin >> wahl; switch(wahl) { case 1: { freunde.emplace_back(); // neues Element am Ende hinzufuegen eingabe(freunde.back()); // ...und befuellen break; } case 2: { anzeigen(freunde); break; } } } while (wahl != 3); return 0; }
So ist das ein bisschen besser. Allerdings ist hier noch keine ordentliche Fehlerbehandlung bzgl der Eingabe drin.
- für
-
Sone schrieb:
Dravere schrieb:
Du musst solche Fehler abfangen und entsprechend verarbeiten. Dazu helfen dir Funktionen wie
fail
,good
undclear
.Hmm. Meistens erledigt man das über den Konvertierungsoperator. So ist das auch Gedacht.
Ja, aber ehrlich gesagt ist meine Erfahrung damit inzwischen die folgende: Das verwirrt die meisten Anfänger nur. Eine Funktion welche
good
oderfail
heisst, sagt den Leuten viel mehr, als irgendein seltsamer Konvertierungsoperator. Ehrlich gesagt empfinde ich es auch als eine recht seltsame Designentscheidung, wie so vieles bei den C++ Streams.Grüssli
-
Dravere schrieb:
Ehrlich gesagt empfinde ich es auch als eine recht seltsame Designentscheidung, wie so vieles bei den C++ Streams.
Schon, aber irgendwie ist das auch ein wenig literarisch, nicht?
if( std::cin >> a )
liest sich doch so schön. Schöner als
if( !std::cin.operator>>(a).fail() )
Eine Funktion welche good oder fail heisst, sagt den Leuten viel mehr, als irgendein seltsamer Konvertierungsoperator.
Da hast du Recht. Aber wäre es nicht auch besser gewesen,
std::vector
std::dynamic_array
zu nenne, undvalarray
stattdessenvector
?Außerdem verstehen Anfänger anfangs sowieso einiges nicht. Die Qualifizierung mit
std
oder dasusing namespace
ist meistens nicht sofort erklärbar, wie einiges andere auch, sondern das muss man einfach so hinnehmen wie es ist und warten bis es dran kommt.
-
Sone schrieb:
Dravere schrieb:
Ehrlich gesagt empfinde ich es auch als eine recht seltsame Designentscheidung, wie so vieles bei den C++ Streams.
Schon, aber irgendwie ist das auch ein wenig literarisch, nicht?
if( std::cin >> a )
liest sich doch so schön. Schöner als
if( !std::cin.operator>>(a).fail() )
So hat Dravere das sicher nicht gemeint.
-
Sone schrieb:
Schöner als
if( !std::cin.operator>>(a).fail() )
Wenn scchon, dann doch bitte
if( !(std::cin >> a).fail() )