AW: Anfänger Fragen - c++
Zitat:
Zitat von
Leange
Etwa das gleiche was wacked gemacht hat aber mit regulären ausdrücken
Viele, viele Möglichkeiten um das gleiche Ziel zu erreichen ^^
Leange
Edit: Ok is dochn bissel was anderes :P
Eigentlich wollte ich mich darüber beschweren das du keine negativen oder Zahlen mit exponent einlesen kannst, aber dann:
Code:
$ wget https://pastebin.com/raw/URrEWHma
$ mv URrEWHma leange.cpp
$ g++ -std=c++11 -o x leange.cpp
$ ./x
terminate called after throwing an instance of 'std::regex_error'
what(): regex_error
Aborted (core dumped)
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
Zitat:
Zitat von
Einstein
...
Es ist schon sehr interessant zu sehen wie eine eigentlich einfache Frage "Input = Zahl ? True Close, Not true ask again" einiges an umdenken und code mit sich bringt. Ich werde es auf jeden fall versuchen hin zu kriegen und dabei so viel mit zu nehmen wie es geht :D
Das ist halt scheiße das "input parsen", also (Eingabe)daten korrekt interpretieren eine der schwersten Sachen ist die es beim Programmieren gibt *und* gleichzeitig die erste die man braucht.
Zitat:
Zitat von
Einstein
Wenn ich das richtig sehe?
Eine Schleife die überprüft ob eine
Integer == Ganzzahl eingegeben wurde, wenn
JA dann close, wenn
NEIN dann
return 0; um die abfrage zu wiederholen mit den gleichen "Parameter bzw. abfrage"
PHP-Code:
while(1) {
int ret = scanf("%d", &a);
// could an int be read?
if (ret == 1) {
break;
}
Und wenn ich z.b das hier entferne schreibt er die Zahl nur 1 mal so wie es glaube ich sein sollte, aber warum das so ist kann ich nicht sagen.
PHP-Code:
else {
/* remove the unparsed data from stdin, so the next call to scanf
doesn't read the same data again
todo: find out why fflush(stdin) doesn't work */
getchar();
}
}
std::cout << a << '\n';
}
Mfg Einstein
Naja es ist eine Schleife bei der 3 Sachen passieren können:
a) es wurde eine Zahl eingegeben --> break;
b) das wo die Zahl von gelesen werden soll ist ("stdin" = Standard Input) funktioniert nicht mehr oder sagt das da jetzt nix mehr kommen kann -> return 0
c) es wurde etwas eingegeben, war aber keine Zahl -> der Rest.
Zu a) scanf() ist sowas wie die C version von std::cin. Du kannst da mehrere Parameter angeben und dann wird auf Benutzerinput gewartet. Irgendwie sowas hier:
Code:
float a;
int b, c, ret;
ret = scanf("%f%d%d", &a, &b, &c);
(Diese %X geben an was für ein Variablentyp erwartet wird, was die &-Zeichen da sollen kommt viel später) Und in ret steht dann wie viele dieser Variablen mit dem erwarteten Typ besetzt werden konnten. Also in dem Beispiel soll erst eine Kommazahl, dann zwei Integer eingegeben werden. Und wenn das erste schon keine Kommazahl ist dann hört die Funktion einfach auf und gibt 0 zurück --> 0 Eingaben passten mit dem erwarteten Variablentyp zusammen bevor es zum ersten Fehler kam. Wenn man "12.345 a 1" oder so eingeben würde, wäre ret == 1, da die Kommazahl noch geklappt hat aber dann beim ersten Integer unerwarter Text war.
Das ist der große Unterschied zu std::cin (das macht einfach fröhlich weiter) und quasi das Herzstück von dem Code.
Aber: scanf() lässt die Daten die es nicht parsen konnte im buffer. Wenn ich also einmal einen Buchstaben eingebe wird danach jeder Versuch eine Zahl einzulesen fehlschlagen. Bis:
* ein scanf() versucht Buchstaben zu lesen und die dann noch vorhandenen Daten akzeptiert
* man den Buffer löscht (das wollte ich eigentlich mit fflush() machen, ging aber nicht...)
* getchar() oder ein anderer Befehl den Buchstaben da rausnimmt.
AW: Anfänger Fragen - c++
@wacked
http://gcc.gnu.org/gcc-4.9/changes.html
Zitat:
Improved support for C++11, including:
Zitat:
Eigentlich wollte ich mich darüber beschweren das du keine negativen oder Zahlen mit exponent einlesen kannst
Die regex nen bissel erweitern und das und noch vieles mehr geht. :P
Leange
AW: Anfänger Fragen - c++
Klar gibt es viele Möglichkeiten, das gesetzte Ziel zu erreichen.
Es ist anfäglich zwar wichtig, dass man es erreicht, doch sollte man immer sauber programmieren.
Anfägliche Fehler lassen sich später schwer ausmerzen, wenn man sie erstmal verinnerlicht hat.
AW: Anfänger Fragen - c++
Also ich versuche mal hier ein wenig Licht ins Dunkle zu bringen.
Zitat:
Zitat von
wacked
Ich geb Text ein und das wird "akzeptiert". std::cin will in eine Zahl schreiben -- wenn halt was anderes kommt haste Pech gehabt.
Also das es akzeptiert stimmt nicht ganz. Die Daten liegen auch noch auf dem Stream, wenn nicht akzeptiert wurde!
Zitat:
Zitat von
wacked
Mir fällt gerade kein Weg (mit std::iostream) zu erkennen ob das was eingegeben wurde auch das richtige Format hatte.
Dafür gibt es ja die Dokumentation ;)
Also es gibt drei Statusflags in der std::ios. Grob kann man das so beschreiben:
- das Badbit wird nur bei ernsthaften IO Fehlern gesetzt
- das Failbit für Operationen die einen Fehler erzeugen dürfen
- das Eofbit um zu signalisieren dass das Ende des Streams erreicht wurde
Für unseren Fall ist das Failbit interessant. Ich habe mal ein wenig Beispielcode vorbereitet:
Zu dem Beispiel von wacked:
Zitat:
Sonst würde ich es halt so machen:
Code:
#include <iostream>
#include <cstdio>
#include <errno.h>
int main() {
int a;
while(1)
{
int ret = scanf("%d", &a);
// could an int be read?
if (ret == 1) {
break;
}
// is the stream fucked or has it ended?
else if (ferror(stdin) || feof(stdin)) {
return 0;
}
else {
// remove the unparsed data from stdin,
// so the next call to scanf doesn't
// read the same data again
// todo: find out why fflush(stdin)
// doesn't work
getchar();
}
}
std::cout << a << '\n';
}
Bitte nicht! Hier wird C mit C++ vermischt was in den seltensten Fällen zu empfehlen ist, und m. M. n. auch kein guter Style ist! Eine schöne Erklärung warum man das nicht will gibt es hier.
Abschließend bleibt noch zu sagen dass Reguläre Ausdrücke für das validieren von Zahlen, wortwörtlich, mit Kanonen auf Spatzen schießen ist! Mit welchen anderen Problemen man dann zu Kämpfen hat zeigt die Exception weiter oben ganz gut finde ich!
AW: Anfänger Fragen - c++
Zitat:
Abschließend bleibt noch zu sagen dass Reguläre Ausdrücke für das validieren von Zahlen, wortwörtlich, mit Kanonen auf Spatzen schießen ist!
Das stimmt in dem Fall ... es ging aber für mich darum ne Möglichkeit zu zeigen wie man Input generell (nicht nur Zahlen) validieren kann.
Zitat:
Mit welchen anderen Problemen man dann zu Kämpfen hat zeigt die Exception weiter oben ganz gut finde ich!
Ffs c++17 ist wip. Benutzt compiler mit ner ordentlichen c++11 Implementierung oder btfo. xD
Leange
AW: Anfänger Fragen - c++
Zitat:
Zitat von
s3rb31
Dafür gibt es ja die Dokumentation ;)
Ok ja ich hätte wenigstens versuchen können das rauszufinden, aber cppreference ist ein bisschen wie die man pages: Um etwas komplett neues herauszufinden sind die ungeignet, die sind nur als Nachlagwerk top.
[QUOTE]Also das es akzeptiert stimmt nicht ganz. Die Daten liegen auch noch auf dem Stream, wenn nicht akzeptiert wurde![/QUOTE]Ähm kann ich jetzt nicht reproduzieren:
Code:
$ cat s3rb31.cpp
#include <iostream>
#include <string>
int main() {
int a;
std::string b, c;
std::cin >> a >> b;
std::cin >> c;
std::cout << a << ',' << b << ',' << c << '\n';
}
$ g++ -o x s3rb31.cpp
$ ./x
a b c
0,,
Zitat:
Zitat von
Leange
Ffs c++17 ist wip. Benutzt compiler mit ner ordentlichen c++11 Implementierung oder btfo. xD
Naja, guck dir das mal an: http://en.cppreference.com/w/cpp/compiler_support
Klar die großen 3 (gcc, MSVC, clang) haben fast alles aber wenn man sich mal anhand der Versionsnummern anguckt wann die ersten Features implementiert wurden und wann die letzten...
AW: Anfänger Fragen - c++
Danke, für die sehr informativen Beiträge. Ich setze mich heute Abend wieder ran und vermute Stark das noch einige Fragen kommen werden, daher würde ich das ganze hier offen lassen.
Eventuell kann man ja hier in der c++ Sektion ein paar Tutorials Posten, einiges ist hier ja schon etwas älter. Ich kann ja was zusammen Kratzen wenn ich was hilfreiches finde in meinen Büchern bzw. tuts.
mfg Einstein
AW: Anfänger Fragen - c++
Zitat:
Zitat von
wacked
Ok ja ich hätte wenigstens versuchen können das rauszufinden, aber cppreference ist ein bisschen wie die man pages: Um etwas komplett neues herauszufinden sind die ungeignet, die sind nur als Nachlagwerk top.
Dafür gibt es Google ;)
Zitat:
Ähm kann ich jetzt nicht reproduzieren:
Code:
$ cat s3rb31.cpp
#include <iostream>
#include <string>
int main() {
int a;
std::string b, c;
std::cin >> a >> b;
std::cin >> c;
std::cout << a << ',' << b << ',' << c << '\n';
}
$ g++ -o x s3rb31.cpp
$ ./x
a b c
0,,
Hast du meinen Beispielcode gelesen? Wenn du nicht abfragst ob da ein Fehler passiert ist und das Failbit clearest, kann es ja auch nicht klappen.
Code:
#include <string>
#include <iostream>
bool check_input()
{
if(std::cin.fail())
{
std::cin.clear();
return false;
}
return true;
}
int main()
{
int a;
std::string b, c;
std::cin >> a >> b >> c;
if (!check_input())
{
std::cin >> b >> c;
std::cout << "Zahl ungültig. " << b << ',' << c << std::endl;
return 1;
}
std::cout << a << ',' << b << ',' << c << std::endl;
return 0;
}
Zitat:
[18:40:13] s3rb31@archbase:~ $ ./a.out
a b c
Zahl ungültig. a,b
[18:40:16] s3rb31@archbase:~ $ ./a.out
1 a b
1,a,b
[18:40:25] s3rb31@archbase:~ $ ./a.out
0s 123 a
0,s,123
AW: Anfänger Fragen - c++
Zitat:
Zitat von
s3rb31
Hast du meinen Beispielcode gelesen? Wenn du nicht abfragst ob da ein Fehler passiert ist und das Failbit clearest, kann es ja auch nicht klappen.
Habe ich, aber als ich bei Zeile 61 angekommen war hatte ich vergessen das in check_input() am iostream etwas verändert wurde. Wurde ja aus dem Funktionsnamen auch nicht (mehr) offensichtlich.
Hätte ich aber vielleicht nochmal drüber gucken sollen bevor ich was gesagt hab... Peinlich
AW: Anfänger Fragen - c++
Mich wunderts ehrlich gesagt dass noch keiner sich über "using namespace std;" beschwert hat. :rolleyes:
Mit Try-Catch
Code:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
int n;
cin >> str;
try {
n = stoi(str);
cout << "Zahl ist: " << n << endl;
}
catch (const invalid_argument&) {
cout << "Keine Zahl. Eingabe ist: " << str << endl;
}
catch (const out_of_range&) {
cout << "Zahl ist nicht in range: " << str << endl;
}
/*cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.get();*/
return 0;
}
Leange