erstellte .exe Datei im Projektpfad bricht vorzeitig



  • na das ist ja ein ganz tolles beispiel. lol.
    wie soll denn etwas im puffer(strom, ram, sonstwo) sein, wenn niemand etwas eingibt.

    richtig wäre wenn du geschrieben hättest:
    Die gezeigte Zeile verwirft eben nicht alle bisher eingegebenen Zeichen, die sich noch im Strom befinden, weil keine Eingabe stattgefunden hat.

    natürlich kann man den puffer mit c-mitteln "löschen", indem man z.b. getchar aufruft. ob nun gelöscht wird oder lediglich intern ein zeiger verbogen wird, ist irrelevant. für den programmierer hat das den effekt eines leeren puffers.



  • c-coder+ schrieb:

    für den programmierer hat das den effekt eines leeren puffers.

    Nein, eben nicht.
    Es wird nur eine Zeile gelesen und verworfen.
    Hast der Nutzer mehrmals Enter gedrückt. Wird davon nur eins gelesen, der Rest bleibt.

    Leeren des Puffers bedeutet, dass du alle Eingaben, die noch nicht abgearbeitet sind, verwirfst.


  • Mod

    😕 Ich weiß ja nicht, welchen Link du geklickt hast, aber in dem Programm wird folgendes eingegeben:

    ----Anfang----
    
    Hopla, wie kommt das den in den gelöschten Puffer? War wohl doch nix.
    ----Ende----
    

    Und wie du siehst, wird diese Eingabe eben nicht gelöscht, es werden lediglich zwei newlines aus dem Stream gelesen. Weil die ganze Vorstellung eines Eingabepuffers falsch ist und nicht funktioniert.

    Wäre das das Programmende gewesen, hätte das Programm auch nicht auf weitere Eingaben gewartet, da das getchar einfach das nächste Zeichen liest und das 'H' ist ja schon direkt verfügbar.

    natürlich kann man den puffer mit c-mitteln "löschen", indem man z.b. getchar aufruft. ob nun gelöscht wird oder lediglich intern ein zeiger verbogen wird, ist irrelevant. für den programmierer hat das den effekt eines leeren puffers.

    Eben nicht, wie gezeigt. Kann es sein, dass dir wirklich nicht klar ist, wie das Eingabemodell in C funktioniert? Ich habe den Eindruck, dass dies bei dir tiefer geht als der Wunsch, Recht zu behalten, sondern dass du das tatsächlich falsch beigebracht bekommen hast. Umso mehr ein Grund, warum du das nicht auch noch weiter geben solltest.



  • DirkB schrieb:

    Es wird nur eine Zeile gelesen und verworfen.
    Hast der Nutzer mehrmals Enter gedrückt. Wird davon nur eins gelesen, der Rest bleibt.
    Leeren des Puffers bedeutet, dass du alle Eingaben, die noch nicht abgearbeitet sind, verwirfst.

    das programm started mit einem leeren puffer.
    denn sonst würde ja, wenn am anfang z.b. mit getchar irgend etwas eingelesen würde, eine ungewollte und undefinierte eingabe stattfinden.
    fein und wenn der benutzer öfter enter drückt, müssten deiner meinung nach also mehrere zeilenumbrüche im puffer sein.
    dazu fällt mir im augenblick nichts ein, wie man so ein scenario als abschreckendes beispiel programmierern könnte.
    entweder folgt ein zweiter funktionsaufruf, der etwas einliest, oder eben nicht.
    wenn ja, kann ich entsprechend im programm auf falscheingaben reagieren. wenn nein, interessiert mich auch nicht mehr was im puffer ist, der bei programmende vom system freigegeben wird.

    SeppJ schrieb:

    😕 Ich weiß ja nicht, welchen Link du geklickt hast, aber in dem Programm wird folgendes eingegeben:

    ----Anfang----
    
    Hopla, wie kommt das den in den gelöschten Puffer? War wohl doch nix.
    ----Ende----
    

    Und wie du siehst, wird diese Eingabe eben nicht gelöscht, es werden lediglich zwei newlines aus dem Stream gelesen. Weil die ganze Vorstellung eines Eingabepuffers falsch ist und nicht funktioniert.

    wenn ich dein programm kompiliere und ausführe verhält es sich auf meinem rechner nicht so.
    so wie du die main-funktion deklarierst können ihr beliebig viele argumente übergeben werden.
    das ist nur ein schmutziger trick :p , der undefined behaviour ausnutzt. wäre
    das verhalten definiert, müsste sich dein programm auf meinem rechner ebenso verhalten.
    wie wäre es, wenn du die main-funktion vernünftig deklarierst, z.b.

    int main(void)
    

    oder

    int main(int argc, char* argv[])
    

    dann sollte das nicht passieren. aber das weißt du selbst ganz genau 😉

    5.1.2.2.1 Program startup
    The function called at program startup is named main. The implementation declares no
    prototype for this function. It shall be defined with a return type of int and with no
    parameters:

    int main(void) { /* ... */ }
    or with two parameters (referred to here as argc and argv, though any names may be
    used, as they are local to the function in which they are declared):
    int main(int argc, char *argv[]) { /* ... */ }
    or equivalent;9) or in some other implementation-defined manner.
    2 If they are declared, the parameters to the main function shall obey the following
    constraints:

    SeppJ schrieb:

    Kann es sein, dass dir wirklich nicht klar ist, wie das Eingabemodell in C funktioniert?

    keine ahnung was du unter modell verstehst.
    ich kenne die standard ein- und ausgabefunktionen und ich weiß, das der standard input und der standard output fully buffered, also gepuffert sind.
    genauer: zeilengepuffert, das letzte zeichen ist das \n, also der zeilenumbruch(new-line character).

    dieses \n sorgt oft für verwirrung und für unerwartetes programmverhalten bei anfängern.
    wenn z.b. zahlen und danach z.b. ein zeichen eingelesen werden soll:

    int main(void)
    { 
    	double number;
    	char character = 'x';
    	puts("Bitte eine Zahl eingeben:");
    	scanf("%lf", &number);
    	puts("Bitte ein Zeichen:");
    	scanf("%c", &character);
    	printf("Die Eingabe war: %f %d %c", number, character, character);
    	return 0;
    }
    

    wenn eine zahl korrekt eingegeben wurde, wird das einlesen des zeichens scheinbar einfach übersprungen.
    grund: die zahl wird nach der eingabe von scanf aus einem zeilengepufferten eingabestrom gelesen, das mit dem \n abgeschlossen ist.
    da dieses \n nicht zum formatstring("%lf") passt, verbleibt das \n im zeilenpuffer.
    der nächste aufruf von scanf liest dieses \n ein, ohne das der benutzer des programms irgend etwas eingegeben hat.
    das sieht man deutlich, wenn man sich die ausgabe des programms anschaut:

    Das eingegebene Zeichen ist: 10

    Die Zahl 10 ist der ASCII Code des Zeilenumbruchs.
    http://de.wikipedia.org/wiki/Zeilenumbruch#Codierung_des_Zeilenumbruchs
    eine möglichkeit dies zu umgehen ist das einfügen der zeile vor scanf, die du anmeckerst und die alle zeichen der zeile im puffer löscht.

    das es puffer gibt, kann man auch im standard nachlesen:

    7.19.3 Files
    At program startup, three text streams are predefined and need not be opened explicitly
    — standard input (for reading conventional input), standard output (for writing
    conventional output), and standard error (for writing diagnostic output). As initially
    opened, the standard error stream is not fully buffered; the standard input and standard
    output streams are fully buffered
    if and only if the stream can be determined not to refer
    to an interactive device.

    7.19.2 Streams
    1 Input and output, whether to or from physical devices such as terminals and tape drives,
    or whether to or from files supported on structured storage devices, are mapped into
    logical data streams, whose properties are more uniform than their various inputs and
    outputs. Two forms of mapping are supported, for text streams and for binary
    streams.
    ...
    2 A text stream is an ordered sequence of characters composed into lines, each line
    consisting of zero or more characters plus a terminating new-line character. Whether the
    last line requires a terminating new-line character is implementation-defined. Characters
    may have to be added, altered, or deleted on input and output to conform to differing
    conventions for representing text in the host environment. Thus, there need not be a oneto-
    one correspondence between the characters in a stream and those in the external
    representation. Data read in from a text stream will necessarily compare equal to the data
    that were earlier written out to that stream only if: the data consist only of printing
    characters and the control characters horizontal tab and new-line; no new-line character is
    immediately preceded by space characters; and the last character is a new-line character
    ...

    soviel zum thema, es gäbe keinen puffer.
    oder was gibt es bei "fully buffered", voll gepuffert, nicht zu verstehen?
    🙂



  • 1. Du hast bisher behauptet, dass du den Eingabepuffer löschen kannst.
    Jetzt redest du nur noch von einer Zeile.

    2. Hast du nicht verstanden was SeppJ eingegeben hat. Die 2 Newline vor dem Hopla fehle bei dir.

    3. Hat die definition von main (mit oder ohne Argumente) nit dem Verhalten nichts zu tun.

    4. kannst du scanf(" %c", &character); auch das '\n' überlesen.
    (Beachte das Leerzeichen vor dem %c)

    5. fully buffered bedeutet hier nur, das keine Zeichen verloren gehen, egal wie schnell du liest oder schreibst oder ob das Ein/Ausgabegerät bereit ist. Im Zweifel warten die Ein/Ausgabe-Funktionen.

    Du hast mit Standard-C keine Möglichkeit Zeichen die im Eingabestrom stehen zu löschen. Du kannst sie nur einlesen und verwerfen.
    Aber das ist nicht das selbe.



  • DirkB schrieb:

    1. Du hast bisher behauptet, dass du den Eingabepuffer löschen kannst.
    Jetzt redest du nur noch von einer Zeile.

    das ist das gleiche in grün. nach dem ersten enter-tastendruck ist es eine zeile.
    dann folgt entweder eine zweite eingabe oder keine.
    zwei \n bekommst du da auf einmal nicht rein.
    zumndest wüsste ich nicht wie.

    DirkB schrieb:

    2. Hast du nicht verstanden was SeppJ eingegeben hat. Die 2 Newline vor dem Hopla fehle bei dir.

    3. Hat die definition von main (mit oder ohne Argumente) nit dem Verhalten nichts zu tun.

    ja, da habe ich wohl allerdigs zuviel in sepps beispiel hineininterpretiert. 😃
    ich war auf dem falschen film, er hätte die eingabe als parameter in der konsole eingegeben.
    aber, es ist ja einfach nur eine nooby-anwendung von der pufferzeilenlöschung. wozu sollte ich den puffer löschen wollen, wenn nichts eingegeben wurde? 🙄
    ist doch klar, das progamm wartet dann auf eine eingabe 🙄
    und die zweite schleife gibt einfach nur das wieder, was eingegeben wird,
    ganz normales programmverhalten. 🙄

    DirkB schrieb:

    4. kannst du scanf(" %c", &character); auch das '\n' überlesen.
    (Beachte das Leerzeichen vor dem %c)

    ja, aber bei einer falscheingabe können viele andere zeichen als nur das \n im stream stehenbleiben.

    DirkB schrieb:

    Du hast mit Standard-C keine Möglichkeit Zeichen die im Eingabestrom stehen zu löschen. Du kannst sie nur einlesen und verwerfen.
    Aber das ist nicht das selbe.

    damit kann ich mich zufrieden geben.
    dann wird das \n eben verworfen und der eingabestrom ist dann wieder sauber, bereit für neue eingaben.
    aber auch nur, wenn man es richtig macht.
    sonst wartet das programm eventuell auf eine eingabe, obwohl nichts eingegeben werden soll.
    von dieser perspektive her betrachtet ist seppjs beispiel dann doch recht lehrreich und nützlich.
    🙂


  • Mod

    Du solltest dich dringend mal von der Vorstellung verabschieden, dass Eingaben irgendwie "eingegeben" werden müssen. Wenn du doch angeblich stdin und andere Ströme verstanden hast, dann musst du doch wissen, dass das einfach nur abstrakte Zeichenketten ohne jede Information über Herkunft und Zeitpunkt der Herkunft dieser Zeichen sind.

    Es gibt einen bestimmten Spezialfall, in dem die Metapher mit dem Eingabepuffer funktioniert: stdin ist mit der Standardeingabe eines Terminalemulators verbunden, dieser Terminalemulator kann mit einer Tastatur bedient werden, der Benutzer nutzt exklusiv diese Methode (also kein Copy&Paste) oder tippt nicht sehr schnell, und der Terminalemulator bietet eine Art "Editormodus" bei dem Eingaben erst dann an das Programm weiter geleitet werden, wenn ein newline auftaucht (so dass man vorher noch mit Backspace, Delete und anderen Tastenkombinationen die Zeile bearbeiten kann.

    Das sind eine ganze Menge an Bedingungen. Zugegeben: Dies ist eine recht häufige Kombination. Aber ein einziges Teil fehlt und die ganze Vorstellung vom Eingabepuffer bricht zusammen und dementsprechend funktioniert kein Programm mehr korrekt, dessen Logik auf dieser Vorstellung beruht.

    Nutzer benutzt Copy&Paste oder tippt schneller als das Programm verarbeiten kann? Fail. Primitives Terminal ohne "Editor" (zum Beispiel, weil man selber solch ein Terminal schreibt)? Fail. Eingabe über andere Geräte (zum Beispiel ein Schnittstellengerät)? Fail. Eingabe aus Datei? Fail. Eingabe aus Pipe? Fail.

    Das sind keine exotischen Szenarien. Das sind gängige Techniken, die ich und andere täglich zigfach benutzen (besonders die letzten beiden). Da muss ein Programm mit zurecht kommen. Da muss der Programmierer verstehen, dass in C ein Eingabestream bloß eine Folge von Zeichen ist, dass es da eben keinen Puffer gibt und dass die Leseoperationen nicht so etwas bedeuten wie "warte auf Eingabe von Tastatur", sondern "interpretiere Zeichen aus Zeichenfolge". Gestaltet er die Programmlogik aber anders und benutzt trotzdem die Eingabeströme (was er auch sollte, denn das hält das Programm flexibel und portabel. Egal ob stdin oder ein beliebiger anderer Stream), dann funktioniert das Programm nicht richtig.



  • wie kommst du bloß darauf, ich hätte generell eine solche vorstellung 😕
    dennoch ging es hier konkret um eine benutzereingabe und da werden eingaben nun einmal irgendwie eingegeben, üblicherweise per tastatur.
    und da wäre es auch sinnfrei, wenn nicht auf die eingabe von tastatur gewartet werden würde.

    und selbstverständlich gibt es puffer, das ist logisch,

    High-level file access structures the file access through memory buffers.
    These buffers hold data going to or coming from the file.

    http://www-control.eng.cam.ac.uk/~pcr20/C_Manual/chap13.html
    auch wenn sie vom programmierer nicht in der weise zugänglich sind, als wenn sie z.b. per malloc allokiert würden.

    recht hast du, bedingt, wenn du behauptest der programmierer müsste nichts genaueres über die puffer wissen.
    bedingt deshalb weil es z.b. in manchen fällen notwendig ist zu wissen, wie man falscheingaben oder unerwünschte daten aus dem eingabepuffer(zeilenpuffer) entfernt.

    High-level file access makes life easier for the programmer because there is no need to know about sector sizes, buffer lengths or other operating system dependent considerations. The only need is to have a pointer to FILE type data and through that pointer access to the caching buffer that holds the data.

    jedoch zu behaupten es gäbe keine puffer, ist schlicht und einfach falsch.
    das ist eine stream-schollklappen-sichtweise.

    🙂


  • Mod

    c-coder+ schrieb:

    wie kommst du bloß darauf, ich hätte generell eine solche vorstellung 😕

    Wegen dem, was du hier schreibst!

    dennoch ging es hier konkret um eine benutzereingabe und da werden eingaben nun einmal irgendwie eingegeben, üblicherweise per tastatur.
    und da wäre es auch sinnfrei, wenn nicht auf die eingabe von tastatur gewartet werden würde.

    Nein, geht es nicht. Die Tastatur hast du als Erster ins Spiel gebracht.

    und selbstverständlich gibt es puffer, das ist logisch,

    High-level file access structures the file access through memory buffers.
    These buffers hold data going to or coming from the file.

    http://www-control.eng.cam.ac.uk/~pcr20/C_Manual/chap13.html
    auch wenn sie vom programmierer nicht in der weise zugänglich sind, als wenn sie z.b. per malloc allokiert würden.

    Und? Wenn sie dem C-Programm nicht zugänglich sind, dann kannst du nicht so programmieren, als wären sie es. Es existiert kein Puffer im Eingabemodell von C, wie du ihn beschreibst! Jedes Programmieren, als gäbe es einen Puffer, ist daher falsch. Wir haben dir doch schon genügend Gegenbeispiele gegeben. Dein eigenes Beispiel funktioniert auch nicht. Was willst du mehr?

    recht hast du, bedingt, wenn du behauptest der programmierer müsste nichts genaueres über die puffer wissen.
    bedingt deshalb weil es z.b. in manchen fällen notwendig ist zu wissen, wie man falscheingaben oder unerwünschte daten aus dem eingabepuffer(zeilenpuffer) entfernt.

    Es gibt keinen Zeilenpuffer! Du kannst daraus nichts entfernen!

    High-level file access makes life easier for the programmer because there is no need to know about sector sizes, buffer lengths or other operating system dependent considerations. The only need is to have a pointer to FILE type data and through that pointer access to the caching buffer that holds the data.

    jedoch zu behaupten es gäbe keine puffer, ist schlicht und einfach falsch.
    das ist eine stream-schollklappen-sichtweise.
    🙂

    Siehe oben. Wenn diese Puffer nicht zugänglich sind, ist es so, als existierten sie nicht. Es gibt den Hoover-Damm. Trotzdem funktioniert

    lasse_wasser_ab(Hoover);
    

    nicht in meinem Programm. Warum? Weil die Talsperre zwar irgendwo existiert, aber für das Programm nicht zugänglich ist. Der Befehl hat daher den gleichen Effekt wie das leeren eines Eingabepuffers, der irgendwo auf Betriebssystemkernelebene existiert. Da kann ein nicht-Kernelmodul schlicht und einfach nicht dran!

    Deine Beispiele funktionieren nicht. Deine Erklärungen sind falsch. Es wurden Gegenbeispiele gegeben. Es wurden korrekte Erklärungen gegeben. Was willst du?



  • SeppJ schrieb:

    Die gezeigte Zeile verwirft eben nicht alle bisher eingegebenen Zeichen, die sich noch im Strom befinden, weil es keinen Puffer gibt, den man (mit C-Mitteln) löschen könnte:
    http://ideone.com/oEMEPG
    Die eine Begrifflichkeit ist eben passend, mit der anderen produziert man Fehler.

    das beispiel hinkt aber ohne ende, denn:

    SeppJ schrieb:

    puts("Mal sehen, ob noch was im Stream ist:");

    ist doch wohl klar, das etwas im stream ist, wenn twas eingegeben wird.
    hier wurde nun einmal "Mal sehen, ob noch was im Stream ist:" eingegeben.


Anmelden zum Antworten