Benutzereingabe Timeout ?

lano

Mitglied
Moin.

Ich frag mich grade ob das überhaupt möglich ist einen timeout zu setzen für Benutzereingaben.

Sowas wie "Wollen Sie updaten? [j/N]"
Kann man da nach Timeout einfach mit default weitermachen irgendwie?
 

german

Aktives Mitglied
devCommunity-Experte
Hmmm, in Standard C hast du da vermutlich nur Threads. Weil die aber erfahrungsgemäß noch nicht flächendeckend unterstützt werden, in deinem Fall wohl eher pthreads. Wenn wir aber schon bei POSIX sind, könnte ich mir vorstellen mit Signals zu arbeiten. Muss ich mir heute Abend mal ansehen ob ich das unter Windows oder WSL simulieren kann ...
 

german

Aktives Mitglied
devCommunity-Experte
Bäh. Keine Ahnung was für Abhängigkeiten der ganze Quatsch hat. Ich hatte noch so ein WinAPI / POSIX Mix aus der Sudoku Challenge rumfliegen. Hab ich kurz umgeschrieben. Vermutlich zu kompliziert, sollte aber funktionieren.

defaultinput.h
C:
#ifndef DEFAULTINPUT_H_INCLUDED__
#define DEFAULTINPUT_H_INCLUDED__

char GetDefaultInput(const char *prompt, char defaultchar, unsigned timeout);

#endif // DEFAULTINPUT_H_INCLUDED__

defaultinput.c
C:
#include "defaultinput.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

// The calling convention of thread routines on Windows is required to be
// __stdcall.
#if defined(_WIN32) ||                                                         \
    defined(__CYGWIN__) // Windows default, including MinGW and Cygwin
#define BASICTHREAD __stdcall
#else // POSIX
#define BASICTHREAD
#endif

typedef void *basic_thread_t;
typedef void *(BASICTHREAD *basic_thread_routine_t)(void *);

bool CreateBasicThread(basic_thread_t *const thread_ptr,
                       basic_thread_routine_t start_routine, void *arg_ptr);
int FastestBasicThread(basic_thread_t thread_array[2]);
void SleepSec(unsigned s);

void *BASICTHREAD Timeout(void *arg);
void *BASICTHREAD ReadInput(void *arg);

char GetDefaultInput(const char *prompt, char defaultchar, unsigned timeout) {
  char ch = 0;
  basic_thread_t thread_ids[2] = {0};
  fputs(prompt, stdout);
  fflush(stdout);
  CreateBasicThread(&thread_ids[0], Timeout, &timeout);
  CreateBasicThread(&thread_ids[1], ReadInput, &ch);
  if (FastestBasicThread(thread_ids) == 0) {
    printf("%c\n", defaultchar);
    return defaultchar;
  }

  return ch;
}

void *BASICTHREAD Timeout(void *arg) {
  unsigned *parg = arg;
  SleepSec(*parg);
  return NULL;
}

void *BASICTHREAD ReadInput(void *arg) {
  char *parg = arg;
  *parg = getchar();
  while (*parg != '\n' && getchar() != '\n')
    ;
  return NULL;
}

#if defined(_WIN32) ||                                                         \
    defined(__CYGWIN__) // Windows default, including MinGW and Cygwin

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x601
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

bool CreateBasicThread(basic_thread_t *const thread_ptr,
                       basic_thread_routine_t start_routine, void *arg_ptr) {
  return (*thread_ptr = (basic_thread_t)CreateThread(
              NULL, 0u, (LPTHREAD_START_ROUTINE)start_routine, arg_ptr, 0u,
              NULL)) != NULL;
}

int FastestBasicThread(basic_thread_t thread_array[2]) {
  int found_thread = -1;

  do {
    Sleep(1u);
    for (int i = 0; i < 2; ++i) {
      if (WaitForSingleObject(thread_array[i], 0u) == 0u) {
        found_thread = i;
        break;
      }
    }
  } while (found_thread == -1);

  TerminateThread(thread_array[!found_thread], 0);

  for (int i = 0; i < 2; ++i)
    CloseHandle(thread_array[i]);

  return found_thread;
}

void SleepSec(unsigned s) { Sleep(s * (DWORD)1000U); }

#else // POSIX

#include <unistd.h>
#if defined(_POSIX_THREADS) && _POSIX_THREADS == 200809L
#include <pthread.h>
#include <signal.h>
#else
#error POSIX Threads Not Supported.
#endif

bool CreateBasicThread(basic_thread_t *const thread_ptr,
                       basic_thread_routine_t start_routine, void *arg_ptr) {
  pthread_t thread = 0;
  bool ret = pthread_create(&thread, NULL, start_routine, arg_ptr) == 0;
  *thread_ptr = (basic_thread_t)(uintptr_t)thread;
  return ret;
}

int FastestBasicThread(basic_thread_t thread_array[2]) {
  int found_thread = -1;

  do {
    usleep(1000u);
    for (int i = 0; i < 2; ++i) {
      if (pthread_kill((pthread_t)(uintptr_t)thread_array[i], 0) != 0) {
        found_thread = i;
        break;
      }
    }
  } while (found_thread == -1);

  pthread_join((pthread_t)(uintptr_t)thread_array[found_thread], NULL);
  pthread_cancel((pthread_t)(uintptr_t)thread_array[!found_thread]);

  return found_thread;
}

void SleepSec(unsigned s) { sleep(s); }

#endif // platforms

Testcode
C:
#include "defaultinput.h"
#include <stdio.h>

int main(void) {
  char ch = GetDefaultInput("Ja oder Nein? [j/n]: ", 'j', 2);
  printf("%c\n", ch);
  return 0;
}
Hoffe das kompiliert bei dir.
//EDIT atomic_bool entfernt
 
Zuletzt bearbeitet:

german

Aktives Mitglied
devCommunity-Experte
Hehe, mir reicht wenn ich weiß dass es funktioniert (oder eben nicht und ich nachbessern muss).
 

german

Aktives Mitglied
devCommunity-Experte
kann er froh sein das er überhaupt
:ROFLMAO: Ja nee is klar. Wenn ich nicht wüsste von wem das kommt ...

Aber ohne Flachs...
Wenn ich Code poste ist das einzige Benefit was ich ziehen kann eine Rückmeldung ob das was ich da verbrochen habe irgend einen Sinn macht. Von daher: 0 Feedback --> Ignore List fürs nächste mal
Den Hauptgewinn hätte ich wenn sich wirklich mal jemand die Zeit nimmt und geposteten Code von vorn bis hinten verreißt und mir die ganze Unzulänglichkeiten um die Ohren wirft, die sich mit Sicherheit noch darin verbergen. Sowas gibt dann wieder Schub nach vorn.
Ne Dankesrede brauch ich allerdings tatsächlich nicht ;)
 

lano

Mitglied
:ROFLMAO: Ja nee is klar. Wenn ich nicht wüsste von wem das kommt ...
Ich hatt gehofft du erinnerst dich. :D

ist das einzige Benefit was ich ziehen kann eine Rückmeldung ob das was ich da verbrochen habe irgend einen Sinn macht.
Naja, soo planlos bist du jetzt nicht das das völlig sinnlos wäre.

0 Feedback --> Ignore List fürs nächste mal
Ist sone sache. kann halt manchmal dauern. ich hab (wie immer eigentlich) reichlich zutun, trotz corona. Und mir tun die pfoten weh ..
heist aber nicht das es nicht für nen dankeschön reicht. Aber da war ich grad echt schon fast aus der tür raus...

die ganze Unzulänglichkeiten um die Ohren wirft
Uh, da bist du bei mir wohl falsch. Du weist selbst wie dankbar ich für deine arbeit bin. grad bei pointern und speicher.

Ne Dankesrede brauch ich allerdings tatsächlich nicht
Nicht jeder bekommt was er sich vorstellt... Ich hab da mal was vorbereitet ... :LOL:

Jane, fällt aus. Aber trotzdem Dankeschön :)
 
Oben Unten