Zum Inhalt springen

Auswertung von Zeicheneingaben in Iterationen (Schleifen)


DITTY

Empfohlene Beiträge

Hallo COM,

Hab da gerade folgendes Problem.

Mir geht es einfach darum, in einer iterierenden Schleife hin und wieder per Tastendruck (egal welche) ein Zwischenergebnis ausgeben zu lassen. Die Schleife soll aber munter weiterlaufen.

Hier mein Bsp.-Code:

#include <climits>

#include <cstdint>

#include <cinttypes>

#include <cfloat>

#include <cmath>

#include <cstdlib>

#include <cstdio>

#include <stdio.h>

#include <iostream>

#include <string.h>

#include <termios.h>


using namespace std;


int my_getch()

{

  static int ch = -1, fd = 0;

  struct termios neu, alt;

  fd = fileno(stdin);

  tcgetattr(fd, &alt);

  neu = alt;

  neu.c_lflag &= ~(ICANON|ECHO);

  tcsetattr(fd, TCSANOW, &neu);

  ch = getchar();

  tcsetattr(fd, TCSANOW, &alt);

  return ch;

}


int my_kbhit(void)

{

  struct termios term, oterm;

  int fd = 0;

  int c = 0;

  tcgetattr(fd, &oterm);

  memcpy(&term, &oterm, sizeof(term));

  term.c_lflag = term.c_lflag & (!ICANON);

  term.c_cc[VMIN] = 0;

  term.c_cc[VTIME] = 1;

  tcsetattr(fd, TCSANOW, &term);

  c = getchar();

  tcsetattr(fd, TCSANOW, &oterm);

  if (c != -1)

  {

    ungetc(c, stdin);

  }

  return ((c != -1) ? 1 : 0);

}


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

{

  uint64_t Var29 = 0, tmp29 = 1;


  for(;tmp29 > 0;tmp29++)

  {

    Var29++;

    if(my_kbhit())

    {

      if(my_getch()=='c')

      {

        printf("x: %"PRIu64"\n",Var29);

      }

    }

  }


  getchar();

  return 0;

}

In dem Fall lasse ich einfach die IF-Bedingung war werden, wenn ich die Taste "c" drücke. Kann meinetwegen auch irgendeine sein.

Das Problem dabei, die Schleife iteriert nun arg langsam. Das sie fleißig weiteriteriert, kann man sehen, wenn man mal in unterschiedlichen Zeitintervalen "c" drückt.

Außerdem kann ich nun drücken, was ich möchte, kann aber nicht das Prog anhalten. Üblicherweise halte ich einfach mit STRG+C an. @Moment muss ich immer mit pidof und kill hantieren.

Weiß einer, wie ich denn richtig abfragen müsste, damit:

a.) Die Schleife trotz If-Abfrage, Aufruf von my_kbhit() und my_getch() weiterhin schnell iteriert (ohne IF-Abfrage-[inhalt] ist die Schleife beendet, wie ich das Programm gestartet habe, also sehr sehr schnell und dass bei einer Inkrementierung bis Maximum von __int64_t)?

b.) Ich weiterhin mit STRG+C das Programm beenden kann.

THX im Voraus!

Grüße

DITTY :):):):)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich würde jetzt einfach mal vermuten das deine my_getch und my_kbhit Funktionen das Problem sind

Vermute ich auch. Ich meine, natürlich dauerts länger, da mehrere Instruktionen * Iterationen, als vorher, ohne die IF und ohne Ausgabemöglichkeit.

Ich weiß nur nicht, wo man bei den Funktionen noch optimieren könnte.

Ich bin auf die Funktionen aufmerksam geworden, da ich eben wie gesagt eine Möglichkeit möchte, in einer Schleife bei Tastendruck ein Zwischenergebnis auszugeben. Ich könnte zwar mit Schrittweiten arbeiten, aber die Möglichkeit mit Tastendruck gefällt mir da ein Tick besser.

Ich setze deshalb auf eigene Funktionen für getch() und kbhit(), da ich nach langer Recherchen keine andere Lösung für Standard-C und Linux-Systeme gefunden habe. getch() gibt es zwar, erfordert aber immer ein ENTER und kbhit() war lediglich aus der Windows-Welt bekannt, hilft mir aber nicht bei Linux weiter. Ich wäre natürlich für jede weitere Lösung, bestenfalls mit Bsp.-Code, sehr dankbar.

Ungeachtet dem Bsp.-Prog, würde es mich dennoch mal interessieren, Zwecks Lernfortschritt und potentieller späterer Projekte.

Ich vermute, dass der Compiler in diesem Fall die Schleife komplett wegoptimiert, weil er erkennt, dass sie nichts bewirkt.

Nein, nein, da verstehste mich falsch. Die Schleife wird schon korrekt ausgeführt. Das ist ja nicht das Problem, im Gegenteil, mich freut die schnelle Ausführung.

Nehme einfach mal den IF-Teil mit Ausgabe heraus und lasse die Ausgabe des Endergebnisses nach der Schleife ausführen. Bei meinem System ist es zumindest so, dass alles ausgeführt ist (Effekt, da anscheinend zu schnelle Ausführung), wie ich das Programm gestartet habe. Das Ergebnis stimmt. Gehe ich in den Debugmodus, sehe ich ebenfalls, dass korrekt iteriert wird, ebenso, wenn ich meine angepeilte Lösung mit Zwischenergebnissen auf Tastentruck anwende.

Aber wie gesagt, darum geht es mir nicht. Ich möchte Tasteneingaben ohne Unterbrechung und ENTER-Druck in einer Schleife auswerten und nutzen können. Bei dem oben stehenden Beispiel ist das kein Problem, da die Ausführung so schnell ist, dass, wie gesagt, die Schleife in sehr sehr kurzer Zeit abgearbeitet ist und ich nur eine Ausgabe nach der Schleife tätigen muss. Ich habe aber vor mit größeren Datentypen und Werten zu rechnen, etwa mit "long double" und 2^128. Da dauert es Ewigkeiten. Und genau deshalb möchte ich mir zwischenzeitlich einfach per Tastendruck willkürlich Zwischenergebnisse ausgeben lassen, damit ich weiß, wo ich gerade stehe. Einfaches Debuggen kommt Aufgrund der vielen Iterationen (2^128) nicht in Frage.

Mir gehts aber eben jetzt auch nicht um das Debuggen oder um das Iterieren an sich, sondern:

=> Ausgabe von Zwischenergebnissen in Iterationen mittels "unterbrechungsfreier" Tastenauswertung

Grüße

DITTY :):):):)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich bin auf die Funktionen aufmerksam geworden, da ich eben wie gesagt eine Möglichkeit möchte, in einer Schleife bei Tastendruck ein Zwischenergebnis auszugeben. Ich könnte zwar mit Schrittweiten arbeiten, aber die Möglichkeit mit Tastendruck gefällt mir da ein Tick besser.
Dir muss klar sein, dass so eine Abfrage bei jedem Schleifendurchlauf, gerade wenn ansonsten in der Schleife praktisch nichts passiert, dein Programm locker mal eben um einen Faktor 100 verlangsamen kann. Eben genau soviel, wie die Ausführung von my_kbhit und die Prüfung des Ergebnisses länger dauert als das Inkrementieren eines Integers.

Ich habe aber vor mit größeren Datentypen und Werten zu rechnen, etwa mit "long double" und 2^128. Da dauert es Ewigkeiten.
Je länger die eigentliche Verarbeitung in der Schleife dauert, desto geringer wird die relative Verlangsamung durch die Tastaturabfrage.

Mir gehts aber eben jetzt auch nicht um das Debuggen oder um das Iterieren an sich, sondern:

=> Ausgabe von Zwischenergebnissen in Iterationen mittels "unterbrechungsfreier" Tastenauswertung

Nein, darum geht's dir nicht, das hast du schon gelöst. Du hast jetzt nur noch die nichtfunktionale Anforderung, dass dir die aktuelle Implementierung zu langsam ist.

Zerleg die Berechnung in zwei verschachtelte Schleifen, und frag die Tastatur nur in der äußeren ab.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hmmmm (überleg).

Zerleg die Berechnung in zwei verschachtelte Schleifen, und frag die Tastatur nur in der äußeren ab.

Wär auch ne Möglichkeit. Würde der Overhead dabei aber nicht der Gleiche bleiben?

Schließlich würden dann trotzdem die Funktionen my_getch() und my_kbhit() bei jeder Iteration ausgeführt werden.

Oder hab ich dich missverstanden?

Und gibts auch andere Möglichkeiten einer Tasteneingabeauswertung ohne ENTER?

Keine selbstgeschriebenen Funktionen, sondern Std-Funktionen, Libs, System, etc.?

Grüße

DITTY :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wär auch ne Möglichkeit. Würde der Overhead dabei aber nicht der Gleiche bleiben?

Schließlich würden dann trotzdem die Funktionen my_getch() und my_kbhit() bei jeder Iteration ausgeführt werden.

Nein. Wenn du eine Operation, die eine Million Mal ausgeführt werden muss, in zwei verschachtelte Schleifen mit je 1000 Iterationen umsetzt, und die Tastatur nur in der äußeren Schleife abfragst, geschieht diese Abfrage logischerweise nur 1000 Mal. Je seltener du die Abfrage machst, desto schlechter ist natürlich die Reaktionszeit auf den Tastendruck.

Und gibts auch andere Möglichkeiten einer Tasteneingabeauswertung ohne ENTER?

Keine selbstgeschriebenen Funktionen, sondern Std-Funktionen, Libs, System, etc.?

Auch jede andere Möglichkeit muss letztendlich dasselbe tun: Beim Betriebssystem nachfragen, ob ein Tastendruck im Tastaturpuffer liegt. Da kannst du nicht viel Geschwindigkeit rausholen. Selbst wenn du die Abfrage in einen anderen Thread auslagerst: Die reine Prüfung, ob etwas passiert ist, kostet dich viel Zeit, wenn du sie bei jedem Durchlauf machst.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Da kannst du nicht viel Geschwindigkeit rausholen. Selbst wenn du die Abfrage in einen anderen Thread auslagerst: Die reine Prüfung, ob etwas passiert ist, kostet dich viel Zeit, wenn du sie bei jedem Durchlauf machst.

Letztendlich ist aber genau das gefordert: Nebenläufigkeit

Die Berechnung ist unabhängig von dem Tastendruck, d.h. in unterschiedlichen Thread wird gearbeitet und dann eventgesteuert eine Ausgabe erzeugen, wobei man diese ggf durch einen Cache während der Berechnung noch zwischen speichert. Eine passende Synchronisation, damit keine Lost Updates erzeugt werden ggf via 2-Phasen-Locking und das System sollte entsprechend arbeiten

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein. Wenn du eine Operation, die eine Million Mal ausgeführt werden muss, in zwei verschachtelte Schleifen mit je 1000 Iterationen umsetzt, und die Tastatur nur in der äußeren Schleife abfragst, geschieht diese Abfrage logischerweise nur 1000 Mal. Je seltener du die Abfrage machst, desto schlechter ist natürlich die Reaktionszeit auf den Tastendruck.

Also ich habe zwei Schleifen. Einmal (äußere Schleife) die der Tastaturabfrage mit [my_]kbhit() und [my_]getch() und dann noch die Iterationschleife für die Variableniteration (innere Schleife)?

Wie genau meinst Du das?

Wenn die äußere Schleife den Status der Tastatur erfragt, aber nichts gedrückt wurde, würde doch false herauskommen und die gesamte Schleife übersprungen werden. Und wie soll auf beiden Schleifen jeweils die Hälfte (Bsp. 1000 und 1000 = 1 Mio) verteilt werden, wenn es doch bei 0 anfängt?

Es soll ja hochgezählt werden. Natürlich könnte ich die Grenze festlegen und dann der äußeren, wie der inneren Schleife jeweils entsprechend iterieren lassen, woraus sich letztendlich dann wieder die Grenze als Ergebnis ergeben würde, da Anzahl Iterationen äußerer Schleife mal Anzahl Iterationen innere Schleife. Aber eine Grenze möchte ich ja nicht festlegen. Im Gegenteil. Bei dem Bsp.-Prog. versuche ich ja die Grenze eines Datentyps via Schleife zu ermitteln, die Grenze ist also Anfangs unbekannt und kann daher nicht auf beide Schleifen verteilt werden.

Grüße

DITTY :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...