Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » switch problem...

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
04.11.2007, 11:18 Uhr
wolf360



fflush(stdin); <-- damti entleere ich doch den Tastaturpuffer? Wenn das ein Bug sein sollte was soll ich dann benutzen, weil die fgets Methode hab ich nicht so ganz verstanden?

gruß wolf360
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
04.11.2007, 15:00 Uhr
0xdeadbeef
Gott
(Operator)


Vielleicht nicht so sehr ein Bug wie ein Microsoftismus, unter Windows ist das sogar definiert. Allerdings - laut Standard lassen sich, eigentlich offensichtlicherweise, nur Ausgabeströme flushen, das heißt, fflush(stdin); kann standardkonform alles mögliche machen - abstürzen, nichts tun, den Eingabestrom flushen oder sogar die Festplatte formatieren. Wobei das letztere eher unwahrscheinlich ist.

So oder so, dass es dir den Eingabestrom flusht ist keinesfalls garantiert, und es ist auch eigentlich eher selten wünschenswert - stell dir vor, jemand füttert dir nach stdin ne Datei, dann kriegt das Programm nachher nie mehr Input von stdin.

Sinnvoller ist es, die Eingabe zeilenweise zu verarbeiten, in C mit fgets, in C++ mit std::getline. Das sieht dann so aus:

C++:
#include <stdio.h>

int main(void) {
  char buf[100]; // 100 == maximale Zeilenlänge in diesem Beispiel
  int x, y;

  printf("Zahl x eingeben: ");
  // stdout ist ein Ausgabestrom, das hier sorgt für sofortige Ausgabe unter
  // allen Umständen. Hier nicht wirklich notwendig, da stdout und stdin aneinander
  // gebunden sind, aber so zur Demonstration:
  fflush(stdout);

  fgets(buf, 100, stdin);
  sscanf(buf, "%d", &x);

  printf("Zahl y eingeben: ");
  fflush(stdout);

  fgets(buf, 100, stdin);
  sscanf(buf, "%d", &y);
  
  printf("x = %d, y = %d\n", x, y);

  return 0;
}


Das sieht dann in der Benutzung z.B. so aus:

C++:
$ ./a.out
Zahl x eingeben: 1 2
Zahl y eingeben: 3
x = 1, y = 3


Zu beachten ist noch, dass fgets am Ende das newline-Zeichen erhält. Das ist für das Parsen mit sscanf nicht weiter von Bedeutung, kann aber bei der Ausgabe ungewollt lustige Effekte haben, mit Extra-Newlines und so, deswegen erwähne ich es hier.

Du kannst das ganze auch in eine eigene Funktion gießen, mit ein bisschen C-Magie:

C++:
#include <stdarg.h>
#include <stdio.h>

int linewise_scanf(FILE *stream, char const *fmt, ...) {
  va_list va;
  char buf[1024];
  int rc;

  // fgets gibt NULL zurück, wenn beim Einlesen ein Fehler auftrat
  // In dem Fall, nach scanf-Konvention, geben wir die Anzahl der
  // eingelesenen Elemente - null - zurück
  if(NULL == fgets(buf, 1024, stream)) {
    return 0;
  }

  va_start(va, fmt);

  rc = vsscanf(buf, fmt, va);

  va_end(va);

  return rc;
}

int main(void) {
  char buf[100]; // 100 == maximale Zeilenl�nge in diesem Beispiel
  int x, y;

  printf("Zahl x eingeben: ");
  fflush(stdout);

  linewise_scanf(stdin, "%d", &x);

  printf("Zahl y eingeben: ");
  fflush(stdout);

  linewise_scanf(stdin, "%d", &y);

  printf("x = %d, y = %d\n", x, y);

  return 0;
}


...in C++ wär das halt

C++:
#include <iostream>
#include <sstream>
#include <string>

int main() {
  std::string line;
  std::istringstream is;
  int x;

  std::cout << "Zahl eingeben: " << std::flush;

  std::getline(std::cin, line);
  is.str(line);
  is >> x;

  std::cout << "x = " << x << std::endl;
}



Nachtrag:

Es böte sich hier natürlich an, zusätzlich noch eine Zeilen-Einlese-Funktion zu schreiben, die nicht auf einen festen Buffer angewiese ist, wie GNUs getline. Aber 1024 Zeichen sollten für vertrauenswürdige Umgebungen in aller Regel ausreichen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 04.11.2007 um 15:04 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
04.11.2007, 15:48 Uhr
wolf360



oha.... dazu ein paar fragen:


Heißt der Befehl zum einlesen nicht scanf und nicht sscanf??

fgets(buf, 100, stdin); <---- warum hast du das Array aufgeteilt also buf, 100 und nicht buf[100] ??

gruß wolf360

Dieser Post wurde am 04.11.2007 um 15:52 Uhr von wolf360 editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
04.11.2007, 16:06 Uhr
0xdeadbeef
Gott
(Operator)


scanf liest von stdin, sscanf liest aus einem String, in diesem Fall buf.

Die "Aufteilung" muss deshalb da hin, weil fgets nicht weiß, was für ein Array bzw. was für einen Zeiger sie übergeben kriegt. Dementsprechend erwartet fgets als zweiten Parameter die Länge des Speicherbereichs, den sie benutzen darf, vom übergebenen Zeiger - buf - an vorwärts.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
04.11.2007, 16:23 Uhr
wolf360



okey,

was passiert dann eigentlich wenn man einen anderen Wert eingibt als das Array groß ist?

zB.


C++:
int main(void) {
  char buf[100];
  int x, y;


  fgets(buf, 200, stdin); // oder nen kleineren Wert?
  sscanf(buf, "%d", &y);

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
04.11.2007, 16:47 Uhr
0xdeadbeef
Gott
(Operator)


Dann läufst du in Gefahr, dass fgets über den Buffer hinausschreibt und einen segmentation fault auslöst, oder über die Rücksprungadresse auf dem Stack schreibt und wer-weiß-was macht. Andere Variablen in der selben und anderen Funktionen könnten andere Werte annehmen, das Programm könnte wild im Code-Segment hin- und herspringen, ein findiger Hacker könnte dir Code einschleusen...da kann alles mögliche passieren.

Ein kleinerer Wert als die Größe des Arrays ist erlaubt, aber selten sinnvoll. Ein größerer erzeugt undefiniertes Verhalten.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 04.11.2007 um 16:48 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
05.11.2007, 14:33 Uhr
wolf360



mal eine frage zu deinner Funktion, wie genau funktioniert die funktion,

ich versteh alles bis auf die klammer, des is ja der Parameter, aber was genau bringt der??

in dem Buch wird des so Beschrieben:

[Spezifizierer] Rückgabetyp Funktionsname(Parameter) {
/* Anweisungsblock mit Anweisungen */
}

Parameter – Die Parameter einer Funktion sind optional. Sie werden durch Datentyp und Namen spezifiziert und durch ein Komma getrennt. Wird kein Parameter verwendet, können sie zwischen die Klammern entweder void schreiben oder gar nichts.

wie genau verwedne ich das?

oder könnt ihr mir gleich sagen wie ich son syntax lese? Weil ich auch grad bei dem Kapitel Ein/Ausgabenfunktion bin:

FILE *fopen(const char *pfadname, const char *modus);

ich kappier pfadname und modus abber was heißt dieses const char? Oder soll das char für Zeichen stehen?

gruß wolf360

Dieser Post wurde am 05.11.2007 um 14:38 Uhr von wolf360 editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
05.11.2007, 14:45 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


const char* ... ist ein zeiger auf einen readonly-Speicherinhalt

hingegen char* const... ein konstanter zeiger auf eine read-and-write Speicherinhalt ist...
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
05.11.2007, 14:46 Uhr
wolf360



aachso okey!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
05.11.2007, 18:06 Uhr
0xdeadbeef
Gott
(Operator)


Die generelle Regel hier ist, das was direkt links von const steht, ist const. Es sei denn, const steht ganz links, dann ist es der Term direkt rechts davon. Also

C++:
char const *p1; // variabler Zeiger auf konstanten char
char *const p2; // konstanter Zeiger auf variablen char
char const *const p3; // konstanter Zeiger auf konstanten char
const char *p4; // das selbe wie p1 in spezieller Schreibweise

// Dementsprechend:

*p1 = 'a'; // illegal
++p1; // legal

*p2 = 'a'; // legal
++p2; // illegal

*p3 = 'a'; // illegal
++p3; // illegal


Übrigens macht dein Buch da einen Fehler, jedenfalls, wenn es um C geht. In C sind

C++:
void foo();
void bar(void);


verschiedene Dinge; bar akzeptiert keine Parameter, foo akzeptiert eine unbegrenzte Menge. In der Praxis ist das meistens aber nur für Funktionszeiger interessant. In C++ dagegen sind die beiden Funktionen das selbe, und um den selben Effekt zu erzielen wie () in C, müsste man

C++:
void foo(...);


schreiben.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 05.11.2007 um 18:08 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: