Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Stringvorgabe für scanf ?

1 view
Skip to first unread message

wolfgang bauer (D)

unread,
May 7, 2022, 6:23:36 AM5/7/22
to

Hallo

Ich möchte eine Eingabe für scanf vorgeben, so das man in der Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss.

puts/putchar schreiben offenbar nicht in den Buffer für scanf.

--
Gruß, Greetings

Helmut Schellong

unread,
May 7, 2022, 9:21:08 AM5/7/22
to

Helmut Schellong

unread,
May 7, 2022, 1:48:25 PM5/7/22
to
On 05/07/2022 16:12, Stefan Ram wrote:
> "wolfgang bauer (D)" writes:
>> Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>> Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>> muss.
>
> Ich denke nicht, daß dies mit Standard-C geht.
>
> Vielleicht geht es mit speziellen Konsolen-Funktionen,
> aber dann wäre es nicht portabel. (Frage zum Beispiel
> in einer Windows-Newsgroup danach.)
>
> Was vielleicht geht, wäre es, bei einer "leeren" Eingabe
> eine Vorgabe zu verwenden.
>
> Aber selbst das würde nicht mit "scanf" gehen. Man müßte
> "getchar" verwenden. Aber dann müßte man viele Fähigkeiten
> von "scanf" aufwendig manuell implementieren. Eine Demo:
>
>
|All conversions are introduced by the % (percent sign) character.
|The format string may also contain other characters.
|White space (such as blanks, tabs, or newlines) in the format string
|match any amount of white space, including none, in the input.

Wie ich bereits schrieb.
Es kann sich lohnen, die Beschreibung zu lesen und ein paar Versuche zu machen.

wolfgang bauer (D)

unread,
May 7, 2022, 2:41:44 PM5/7/22
to
07.05.22 , 20:26 , Thomas Noll:

> Das ist aber auch trivial, mit scanf etwas einzulesen und bei speziellen
> Eingaben eineSonderbehandlung zu machen. Gefragt war aber wohl eher ein
> Verhalten wie z.B die bash mit readline support mit read -i bietet.
>
> Und das kann man, erstaunlicherweise, mit der readline lib bekommen.
> Ausgangspunkt int rl_insert_text (const char *text), wie es genau geht,
> wird der OP uns dann sicher wissen lassen, wenn er es umgesetzt hat.


Erstmal Danke an alle, die geantwortet haben.

Die "readline lib" kannte ich bisher nicht und werde mir das einmal genauer ansehen.

Mir ging es aber zunächst darum, ob scanf im beschriebenen Sinne eingesetzt werden kann. Wie es aussieht, wohl eher
nicht. Ich möchte das Programm (welches ich unter Linux entwickle) auch per Crosscompiler Windowstauglich machen.
Ohne systemabhängige Methoden scheint es also nicht zu gehen. Im vorliegenden Fall ist es nicht so wichtig; ich wollte
eigentlich nur einen lästigen optischen Nebeneffekt verhindern (Cursor wandert in die nächste Zeile, wenn die
Returntaste ohne Eingabe betätigt wird). Ungültige Eingaben erkennt das Programm und löscht die Eingabezeile einfach wieder.
Also wollte ich z.b. einfach ein Blank vorgeben.






--
Gruß, Greetings

wolfgang bauer (D)

unread,
May 7, 2022, 2:50:41 PM5/7/22
to
07.05.22 , 20:29 , Stefan Ram:
> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>> while( p < top && ch != '\n' )*p++ = ch =( char )getchar();
>
> Die folgende, neue Version erlaubt es nun immerhin,
> die Eingabezeile wie bei Verwendung von "scanf" noch
> zu bearbeiten, bevor die Eingabetaste gedrückt wird.
>
> #include <stdio.h>
> #include <string.h>
>
> #define BUFFER_SIZE 4096
> #define xstr(a) str(a)
> #define str(a) #a
>
> int main( void )
> { char input[ BUFFER_SIZE ];
> const char * const top = input + BUFFER_SIZE;
> printf( "Zahl (Eingabetaste fuer 0)? " );
> fgets( input, BUFFER_SIZE, stdin );
> if( *input == '\n' )
> { puts( "Eingabetaste erkannt." );
> strncpy( input, "0\n", BUFFER_SIZE-1 ); }
> for( char * p = input; p < top && *p; ++p )
> if( *p == '\n' ){ *p = 0; break; }
> printf( "Eingabe = \"%." xstr( BUFFER_SIZE ) "s\"\n", input ); }
>
>


Das erledigt genau, was ich brauche ! Danke :-)



--
Gruß, Greetings

Claus Reibenstein

unread,
May 7, 2022, 5:24:11 PM5/7/22
to
Helmut Schellong schrieb am 07.05.2022 um 19:49:

> On 05/07/2022 16:12, Stefan Ram wrote:
>
>> "wolfgang bauer (D)" writes:
>>
>>> Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>>> Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>>> muss.
>>
>> Ich denke nicht, daß dies mit Standard-C geht.

Ich auch nicht.

> Es kann sich lohnen, die Beschreibung zu lesen und ein paar Versuche zu machen.

Es kann sich auch lohnen, die ursprüngliche Frage genau zu lesen, sie zu
verstehen und erst dann zu antworten.

Gruß
Claus

Helmut Schellong

unread,
May 7, 2022, 6:42:35 PM5/7/22
to
Die ursprüngliche Frage ist:
|Ich möchte eine Eingabe für scanf vorgeben, so das man in der Konsole
|nur noch ohne weitere Eingabe die Returntaste drücken muss.

Ich bin offenbar der Einzige, der sie ernst genommen und verstanden hat,
einschließlich des Aufgabenstellers.

Ich wollte somit eine Lösung für _scanf_ verfolgen, wie es das Lastenheft vorgibt.
Wie sich herausstellte, ist diese Aufgabenstellung irrelevant.
(Lösungen ohne scanf (nicht kanonisch) hatte ich bereits in den 1980ern.)
Es gibt übrigens die Konversion '%\0'.

Helmut Waitzmann

unread,
May 8, 2022, 3:39:54 AM5/8/22
to
Helmut Schellong <r...@schellong.biz>:
>On 05/07/2022 23:24, Claus Reibenstein wrote:

>> Es kann sich auch lohnen, die ursprüngliche Frage genau zu lesen,
>> sie zu verstehen und erst dann zu antworten.
>>
>
>Die ursprüngliche Frage ist:
>
>|Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>|Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>|muss.
>
>Ich bin offenbar der Einzige, der sie ernst genommen und verstanden
>hat,

Du hast sie nicht erfasst, denn du hast den zweiten Teil der
Aufgabenstellung ignoriert.  Vollständig lautet die Aufgabenstellung
so:

«Ich möchte eine Eingabe für scanf vorgeben, sodass man in der
Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss.
puts/putchar schreiben offenbar nicht in den Buffer für scanf.»

Und jetzt kommt die entscheidende Frage, die du dir hättest stellen
müssen:  Was will der Aufgabensteller mit dem letzten Satz andeuten?

Antwort:  Er hat erstens erwartet, dass er mit puts/putchar den für
scanf zuständigen Eingabepuffer vor‐ausfüllen kann, damit er, wenn
er mit dem vorausgefüllten Eingabetext zufrieden ist, nur noch die
Returntaste drücken muss und dadurch trotzdem, obwohl er den
vorausgefüllten Text nicht selber eingetippt hat, beim Aufruf der
scanf‐Funktion ein Ergebnis erhält, als hätte er ihn eingetippt, und
zweitens erfahren, dass er das Vor‐Ausfüllen mit puts/putchar nicht
hinbekommt.

>einschließlich des Aufgabenstellers.
>

Der Aufgabensteller hat im Gegensatz zu dir seine Frage verstanden. 
Nicht gewusst hat er jedoch, dass Eingabe von einem Terminal und
Ausgabe auf das Terminal zwei verschiedene Paar Schuhe sind, die,
obwohl beide ein sichtbares Resultat im Terminal hinterlassen (es
sei denn, man hätte das Terminal‐Echo abgeschaltet), nichts mit
einander zu tun haben.

>Ich wollte somit eine Lösung für _scanf_ verfolgen, wie es das
>Lastenheft vorgibt.

Die richtige Antwort auf das Lastenheft wäre die folgende
zweigeteilte gewesen: 

(1.) Das von dir gewünschte geht nicht:  Man kann den
Terminal‐Eingabepuffer für zeilenweise Eingabe nicht durch eine
Ausgabe vor‐ausfüllen, weil Terminal‐Ein‐ und Ausgabe nichts mit
einander zu tun haben, obwohl es so aussieht, als hätten sie es. 
Deshalb muss

(2.) die von dir gewünschte Verbindung – im Eingabepuffer steht
jederzeit das, was auf dem Terminal geschrieben steht – vom Programm
selber simuliert werden.  Man schaltet dazu das Terminal in eine
Betriebsart um, die es dem Programm ermöglicht, jedes Zeichen, das
man tippt, sofort vom Terminal zu erhalten, obwohl man die
Returntaste noch gar nicht getippt hat.  Dann kann das Programm
entsprechend reagieren:  Ist das gelesene Zeichen ein druckbares
Zeichen, muss es erstens im simulierten Eingabepuffer abgelegt und
zweitens auf dem Terminal ausgegeben werden.  Ist es jedoch ein
Steuerzeichen – beispielsweise das, was das zuletzt eingetippte
Zeichen aus dem Eingabepuffer und vom sichtbaren Text im Terminal
löschen und die Schreibmarke eine Position zurücksetzen soll, muss
erstens das zuletzt im simulierten Eingabepuffer abgelegte Zeichen
aus dem simulierten Eingabepuffer entfernt werden und zweitens das
im Terminal sichtbare zuletzt eingetippte Zeichen mit einem
Leerzeichen überschrieben und die Position der Schreibmarke dorthin
gesetzt werden, wo das überschriebene Zeichen stand.  Das alles muss
man aber nicht selber programmieren, weil es dafür fertige Libraries
(readline, …) gibt.  Mit einem einfachen scanf ist es dabei nicht
mehr getan.

Helmut Schellong

unread,
May 8, 2022, 6:04:57 AM5/8/22
to
On 05/08/2022 06:57, Helmut Waitzmann wrote:
> Helmut Schellong <r...@schellong.biz>:
>> On 05/07/2022 23:24, Claus Reibenstein wrote:
>
>>> Es kann sich auch lohnen, die ursprüngliche Frage genau zu lesen, sie zu verstehen und erst dann zu antworten.
>>>
>>
>> Die ursprüngliche Frage ist:
>> |Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>> |Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>> |muss.
>>
>> Ich bin offenbar der Einzige, der sie ernst genommen und verstanden hat,
>
> Du hast sie nicht erfasst, denn du hast den zweiten Teil der Aufgabenstellung ignoriert.  Vollständig lautet die Aufgabenstellung so:
>
> «Ich möchte eine Eingabe für scanf vorgeben, sodass man in der Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss. puts/putchar schreiben offenbar nicht in den Buffer für scanf.»
>
> Und jetzt kommt die entscheidende Frage, die du dir hättest stellen müssen:  Was will der Aufgabensteller mit dem letzten Satz andeuten?

Die Semantik des zweiten Satzes ist abstrus und nicht durchführbar, weshalb
ich mich auf den ersten Satz konzentrierte.

Eingabefunktionen stützen sich auf einen Eingabepuffer, der
vom Terminal gefüllt wird.
Dieser Puffer ist systemspezifisch irgendwo und nicht sichtbar.
Die Verwaltungsobjekte dazu sind intern und nicht zugänglich.

Mittels setvbuf() kann auf einen selbst angelegten Puffer gelenkt werden
und drei Modi der Pufferung angegeben werden.
Die Verwaltungsobjekte bleiben jedoch intern, so wie die Definition des Typs FILE.

> Antwort:  Er hat erstens erwartet, dass er mit puts/putchar den für scanf zuständigen Eingabepuffer vor‐ausfüllen kann, damit er, wenn er mit dem vorausgefüllten Eingabetext zufrieden ist, nur noch die Returntaste drücken muss und dadurch trotzdem, obwohl er den vorausgefüllten Text nicht selber eingetippt hat, beim Aufruf der scanf‐Funktion ein Ergebnis erhält, als hätte er ihn eingetippt, und zweitens erfahren, dass er das Vor‐Ausfüllen mit puts/putchar nicht hinbekommt.
>
>> einschließlich des Aufgabenstellers.
>
> Der Aufgabensteller hat im Gegensatz zu dir seine Frage verstanden.

Ja, aber er hat sein Verständnis nicht beschrieben.
Das (übliche) fast endlose Frage/Antwort-Spiel wollte ich nicht durchführen.

> Nicht gewusst hat er jedoch, dass Eingabe von einem Terminal und Ausgabe auf das Terminal zwei verschiedene Paar Schuhe sind, die, obwohl beide ein sichtbares Resultat im Terminal hinterlassen (es sei denn, man hätte das Terminal‐Echo abgeschaltet), nichts mit einander zu tun haben.

Offensichtlich.
Es gibt nicht ohne Grund 'stdin' und 'stdout'.
Und fflush() ist z.B. nur auf 'stdout' anwendbar.

>> Ich wollte somit eine Lösung für _scanf_ verfolgen, wie es das Lastenheft vorgibt.
>
> Die richtige Antwort auf das Lastenheft wäre die folgende zweigeteilte gewesen:

[...]

Vielleicht könnte ich das Problem tatsächlich allein mit scanf() hinbekommen.
Eventuell kann freopen() dabei helfen.

Jedenfalls habe ich bisher stets termio.h und termios.h benutzt, um
das Terminal umfassend zu konfigurieren.
Insbesondere für die Input-Sequenzen:
...
# define K_DEL (K_BASE+83)
# define K_U (K_BASE+72)
# define K_D (K_BASE+80)
# define K_R (K_BASE+77)
# define K_L (K_BASE+75)
# define K_N5 (K_BASE+76)
# define K_END (K_BASE+79)
# define K_PGD (K_BASE+81)
# define K_HOME (K_BASE+71)
# define K_PGU (K_BASE+73)
# define K_INS (K_BASE+82)
# define K_F1 (K_BASE+59)
...

n= read(fdg, ca, 6);
//...
CA0: c=ca[0], --n;
if ( n==2-1&&(c==K_CSI||c==K_ESC) ) n=0, c=ca[1]+K_BASE;
else if (n==3-1&& c==K_ESC&&(ca[1]=='['||ca[1]=='O'))
n=0, c=ca[2]+K_BASE;
else if (n>=4-1&&n<=5-1&& c==K_ESC&&ca[1]=='[') {
if (ca[n]=='~') {
if (n==4-1) n=0, c= ca[2]-'0'+'~'+K_BASE;
if (n==5-1) n=0, c=(ca[2]-'0')*10+ca[3]-'0'+'~'+K_BASE;
}
else if (n==4-1&&ca[2]=='[') n=0, c=ca[3]+K_BASE+'a'-'A';
}
return (N=n,I=1, c);


Es können bis zu 5 Zeichen eingehen aufgrund eines Tastendruckes.
Da hat man was zu tun, für sechs verschiedene BS.

Juergen Ilse

unread,
May 8, 2022, 10:45:00 AM5/8/22
to
Hallo,

"wolfgang bauer (D)" <sch...@gmx.de> wrote:
> Ich möchte eine Eingabe für scanf vorgeben, so das man in der Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss.
>
> puts/putchar schreiben offenbar nicht in den Buffer für scanf.

Damit das funktioiert, muesstest du auch den TerminalModus passend schalten,
denn per default ist der vermutlich line buffered, so dass erst nach Abschluss
der Zeile die Zeile vom Terminal in die input queue uebertragen wird. Wenn
du das alles moeglichst portabel hinbekommen moechtest, lohnt sich ein Blick
aauf die Funktionen der "curses" library. Portabler als das wirst du es wohl
kaum hinbekommen ...

Tschuess,
Juergen Ilse (juergen@usenet-verwaöltung.de)

Juergen Ilse

unread,
May 8, 2022, 10:48:39 AM5/8/22
to
Hallo,

Stefan Ram <r...@zedat.fu-berlin.de> wrote:
> "wolfgang bauer (D)" writes:
>>Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>>Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>>muss.
>
> Ich denke nicht, daß dies mit Standard-C geht.

Da hasst du wohl recht.

> Vielleicht geht es mit speziellen Konsolen-Funktionen,
> aber dann wäre es nicht portabel. (Frage zum Beispiel
> in einer Windows-Newsgroup danach.)

Das portabelste in dieser Richtung duerfte meiens Erachtens nach die curses
librar sein, da die auf so ziemlich jedes halbwegs gaengige Desktop System
portiert wurde und auch in so ziemlich allen unixoiden Systemen verfuegbar
ist.

> Was vielleicht geht, wäre es, bei einer "leeren" Eingabe
> eine Vorgabe zu verwenden.

Ich fuerchte, das wird nicht funktionieren.

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Juergen Ilse

unread,
May 8, 2022, 10:55:56 AM5/8/22
to
Hallo,

Helmut Schellong <r...@schellong.biz> wrote:
> On 05/07/2022 23:24, Claus Reibenstein wrote:
>> Helmut Schellong schrieb am 07.05.2022 um 19:49:
>>
>>> On 05/07/2022 16:12, Stefan Ram wrote:
>>>
>>>> "wolfgang bauer (D)" writes:
>>>>
>>>>> Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>>>>> Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>>>>> muss.
>>>>
>>>> Ich denke nicht, daß dies mit Standard-C geht.
>>
>> Ich auch nicht.
>>
>>> Es kann sich lohnen, die Beschreibung zu lesen und ein paar Versuche zu machen.
>>
>> Es kann sich auch lohnen, die ursprüngliche Frage genau zu lesen, sie zu
>> verstehen und erst dann zu antworten.
>>
>>
>
> Die ursprüngliche Frage ist:
> |Ich möchte eine Eingabe für scanf vorgeben, so das man in der Konsole
> |nur noch ohne weitere Eingabe die Returntaste drücken muss.

Ja, und da bei so ziemlich allen gaengigen Desktopsystemen dere Terminal
Treiber per default ein line-buffering macht (die eingabe alsso erst nach
Abschluss der Zeile in den input stream weiter gibt), muesste auch das
Verhaltwen des Terminal Treibers aendern. Das koennte man unter unixoiden
Systemen z.B, mittels libtermcap oder libtermio machen. Oder portabler
mittels einer libcurses (die ihrerseits auf dem System auf eine der beiden
oben genannten librarys oder auf Systemen, die das nicht kennen auf system-
spezifische Funktionen aufsetzt).

> Ich bin offenbar der Einzige, der sie ernst genommen und verstanden hat,
> einschließlich des Aufgabenstellers.

Eibildung ist auch eine Bildung ...

Tscchuess,
Juergen Ilse (juergenqusenet-vewaltung.de)

Juergen Ilse

unread,
May 8, 2022, 11:01:03 AM5/8/22
to
Hallo,

Helmut Waitzmann <nn.th...@xoxy.net> wrote:
> Helmut Schellong <r...@schellong.biz>:
>>On 05/07/2022 23:24, Claus Reibenstein wrote:
>
>>> Es kann sich auch lohnen, die ursprüngliche Frage genau zu lesen,
>>> sie zu verstehen und erst dann zu antworten.
>>>
>>
>>Die ursprüngliche Frage ist:
>>
>>|Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>>|Konsole nur noch ohne weitere Eingabe die Returntaste drücken
>>|muss.
>>
>>Ich bin offenbar der Einzige, der sie ernst genommen und verstanden
>>hat,
>
> Du hast sie nicht erfasst, denn du hast den zweiten Teil der
> Aufgabenstellung ignoriert.  Vollständig lautet die Aufgabenstellung
> so:

Ich muss mich entschuldigen, ich habe auch zu oberflaechlich drueber
hinweg gelesen. Ich hatte an den Fall gedacht, dass man eine Eingabe
Zeichen fuer Zeichen einlesen moechte, ohne erst auf <return> zu warten,
und dazu muss man aauf passende libraries zurueckgreifen, oder man wird
*sehr* systemabhaengig.
Fuer den Fall des Threadstarters iist vermutlich tatsaechlich libreadline
der passendste Weg, wenn die librar fuer alle Zielsysteme zur Verfuegung
steht.

Tschuess,
Juergen Ilse (jue...@useenet-verwaltung.de)

Thomas Koenig

unread,
May 8, 2022, 11:14:32 AM5/8/22
to
Juergen Ilse <ne...@usenet-verwaltung.de> schrieb:

> Eibildung ist auch eine Bildung ...

Sowieso, die Frage ist nur noch, ob Spiegel- oder Rührei...

wolfgang bauer (D)

unread,
May 8, 2022, 1:29:33 PM5/8/22
to
08.05.22 , 12:05 , Helmut Schellong:
> On 05/08/2022 06:57, Helmut Waitzmann wrote:

>> Du hast sie nicht erfasst, denn du hast den zweiten Teil der Aufgabenstellung ignoriert.  Vollständig lautet die Aufgabenstellung so:
>>
>> «Ich möchte eine Eingabe für scanf vorgeben, sodass man in der Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss. puts/putchar schreiben offenbar nicht in den Buffer für scanf.»
>>
>> Und jetzt kommt die entscheidende Frage, die du dir hättest stellen müssen:  Was will der Aufgabensteller mit dem letzten Satz andeuten?
>
> Die Semantik des zweiten Satzes ist abstrus und nicht durchführbar, weshalb
> ich mich auf den ersten Satz konzentrierte.

Naja, auf den "Vorwurf" des Abstrusen muss ich dann doch nochmal antworten. Dein Vorredner (Helmut Waitzmann) hat den Kern meiner Frage erfasst und nochmal
herausgestellt. So abstrus kann meine Formulierung nicht gewesen sein. Auch andere haben verstanden, worum es mir ging.

>> Der Aufgabensteller hat im Gegensatz zu dir seine Frage verstanden.
>
> Ja, aber er hat sein Verständnis nicht beschrieben.

Doch, das habe ich.

> Das (übliche) fast endlose Frage/Antwort-Spiel wollte ich nicht durchführen.

Und genau darum, um das Pingpong zu vermeiden, habe ich den Kern meiner Frage (zum *Vestaendnis* bzgl. des scanf-Mechanismus') nochmal unterstrichen,
indem ich meine Erwartung zu puts/putchar beschrieb, die ja dann nicht erfüllt wurde.

Danke nochmal an die Beteiligten für die Ausführungen, denen ich einiges entnehmen konnte. So oft programmiere ich nicht für die Konsole und habe daher
noch einiges zu lernen. Bis auf simpelste Ein- und Ausgaben habe ich da noch nicht viel gemacht. Ansonsten versehe ich meine Programme mit einem GUI.





--
Gruß, Greetings

wolfgang bauer (D)

unread,
May 8, 2022, 1:41:32 PM5/8/22
to
08.05.22 , 16:44 , Juergen Ilse:

>> puts/putchar schreiben offenbar nicht in den Buffer für scanf.
>
> Damit das funktioiert, muesstest du auch den TerminalModus passend schalten,
> denn per default ist der vermutlich line buffered, so dass erst nach Abschluss
> der Zeile die Zeile vom Terminal in die input queue uebertragen wird. Wenn
> du das alles moeglichst portabel hinbekommen moechtest, lohnt sich ein Blick
> aauf die Funktionen der "curses" library. Portabler als das wirst du es wohl
> kaum hinbekommen ...
Danke für den Tip. Auch diese Library, neben der schon vorgeschlagenen readline-Library, werde ich mir einmal
genauer ansehen.

--
Gruß, Greetings

Helmut Schellong

unread,
May 8, 2022, 2:40:42 PM5/8/22
to
On 05/08/2022 18:29, Thomas Noll wrote:
> Am 08 May 2022 14:55:55 GMT schrieb Juergen Ilse:
>
>> Hallo,
>>
>> Helmut Schellong <r...@schellong.biz> wrote:
>>> Die ursprüngliche Frage ist:
>>> |Ich möchte eine Eingabe für scanf vorgeben, so das man in der Konsole
>>> |nur noch ohne weitere Eingabe die Returntaste drücken muss.
>>
>> Ja, und da bei so ziemlich allen gaengigen Desktopsystemen dere Terminal
>> Treiber per default ein line-buffering macht (die eingabe alsso erst nach
>> Abschluss der Zeile in den input stream weiter gibt), muesste auch das
>> Verhaltwen des Terminal Treibers aendern.
>
> Ich würde ja mal sagen, daß das explizit gewünschte Drücken der Returntaste
> die Zeile abschließt.
>

Ja, deshalb schrieb ich auch, daß Versuche mit scanf eventuell das Problem lösen.

Helmut Schellong

unread,
May 8, 2022, 2:55:14 PM5/8/22
to
On 05/08/2022 19:29, wolfgang bauer (D) wrote:
> 08.05.22 , 12:05 , Helmut Schellong:
>> On 05/08/2022 06:57, Helmut Waitzmann wrote:
>
>>> Du hast sie nicht erfasst, denn du hast den zweiten Teil der Aufgabenstellung ignoriert.  Vollständig lautet die Aufgabenstellung so:
>>>
>>> «Ich möchte eine Eingabe für scanf vorgeben, sodass man in der Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss. puts/putchar schreiben offenbar nicht in den Buffer für scanf.»
>>>
>>> Und jetzt kommt die entscheidende Frage, die du dir hättest stellen müssen:  Was will der Aufgabensteller mit dem letzten Satz andeuten?
>>
>> Die Semantik des zweiten Satzes ist abstrus und nicht durchführbar, weshalb
>> ich mich auf den ersten Satz konzentrierte.
>
> Naja, auf den "Vorwurf" des Abstrusen muss ich dann doch nochmal antworten. Dein Vorredner (Helmut Waitzmann) hat den Kern meiner Frage erfasst und nochmal
> herausgestellt. So abstrus kann meine Formulierung nicht gewesen sein. Auch andere haben verstanden, worum es mir ging.

puts/putchar _können nicht_ in den scanf-Puffer schreiben.
Niemand kann in diesen Puffer schreiben, weil der intern ist.
Dieser Gedanke, diese Vorstellung ist von Grund auf abstrus.

>>> Der Aufgabensteller hat im Gegensatz zu dir seine Frage verstanden.
>>
>> Ja, aber er hat sein Verständnis nicht beschrieben.
>
> Doch, das habe ich.

Einige Postings später kam die Info, daß der Cursor durch scanf
unerwünscht in die nächste Zeile ging.

Genau das sind hilfreiche Detailinformationen, die die Lösung näher bringen.
Kamen aber viel zu knapp.

>> Das (übliche) fast endlose Frage/Antwort-Spiel wollte ich nicht durchführen.
>
> Und genau darum, um das Pingpong zu vermeiden, habe ich den Kern meiner Frage (zum *Vestaendnis* bzgl. des scanf-Mechanismus') nochmal unterstrichen,
> indem ich meine Erwartung zu puts/putchar beschrieb, die ja dann nicht erfüllt wurde.

puts/putchar sind Ausgabefunktionen, scanf eine Eingabefunktion.
In der Summe sind die Informationen daher für mich abstrus (verworren, unbegreiflich)
gewesen, weshalb ich mich auf den ersten Satz konzentrierte, der nicht abstrus ist.

Helmut Schellong

unread,
May 8, 2022, 3:04:02 PM5/8/22
to
termio.h, termios.h, read(), etc. sind im POSIX-Standard enthalten.
Ich konnte damit alle Unix-Systeme und Windows mit Einzeltasten-Lesen ausstatten.
Im POSIX ist übrigens auch der C-Standard enthalten.

Der Aufwand damit dürfte 5-30-fach geringer sein als mit genannten Libraries
curses oder readline.


--
Mit freundlichen Grüßen
Helmut Schellong v...@schellong.biz

wolfgang bauer (D)

unread,
May 8, 2022, 3:30:36 PM5/8/22
to
08.05.22 , 20:56 , Helmut Schellong:

>>> Die Semantik des zweiten Satzes ist abstrus und nicht durchführbar, weshalb
>>> ich mich auf den ersten Satz konzentrierte.
>>
>> Naja, auf den "Vorwurf" des Abstrusen muss ich dann doch nochmal antworten. Dein Vorredner (Helmut Waitzmann) hat den Kern meiner Frage erfasst und nochmal
>> herausgestellt. So abstrus kann meine Formulierung nicht gewesen sein. Auch andere haben verstanden, worum es mir ging.
>
> puts/putchar _können nicht_ in den scanf-Puffer schreiben.
> Niemand kann in diesen Puffer schreiben, weil der intern ist.
> Dieser Gedanke, diese Vorstellung ist von Grund auf abstrus.

Mit Verlaub, aber sinnentnehmend lesen und mitdenken liegt dir nicht. Bist du auf Konfrontationskurs ?

Meine Frage stellte ich ja gerade darum, *WEIL* ich da noch eine Frage hatte. Ich erkläre dir gerade, das 1+1=2 ist.


> Einige Postings später kam die Info, daß der Cursor durch scanf
> unerwünscht  in die nächste Zeile ging.
>
> Genau das sind hilfreiche Detailinformationen, die die Lösung näher bringen.
> Kamen aber viel zu knapp.

Für andere nicht. Für dich schon. Das liegt aber nicht an mir. Du solltest lernen, dein
überschäumendes Temperament zu zügeln. Sonst hast du genau die Offtopic-Exzesse, die du
doch vermeiden wolltest.


>>> Das (übliche) fast endlose Frage/Antwort-Spiel wollte ich nicht durchführen.
>>
>> Und genau darum, um das Pingpong zu vermeiden, habe ich den Kern meiner Frage (zum *Vestaendnis* bzgl. des scanf-Mechanismus') nochmal unterstrichen,
>> indem ich meine Erwartung zu puts/putchar beschrieb, die ja dann nicht erfüllt wurde.
>
> puts/putchar sind Ausgabefunktionen, scanf eine Eingabefunktion.
> In der Summe sind die Informationen daher für mich abstrus (verworren, unbegreiflich)
> gewesen, weshalb ich mich auf den ersten Satz konzentrierte, der nicht abstrus ist.

Nein. Du denkst nicht mit und wirfst dann mit Formulierungen um dich, die man nicht einfach so stehen lassen kann.

Kehren wir zum Thema zurück, wobei das Problem längst gelöst ist. Siehe <t56f20$gvv$1...@dont-email.me>






--
Gruß, Greetings

wolfgang bauer (D)

unread,
May 8, 2022, 3:32:19 PM5/8/22
to
08.05.22 , 21:04 , Helmut Schellong:

> termio.h, termios.h, read(), etc. sind im POSIX-Standard enthalten.
> Ich konnte damit alle Unix-Systeme und Windows mit Einzeltasten-Lesen ausstatten.
> Im POSIX ist übrigens auch der C-Standard enthalten.
>
> Der Aufwand damit dürfte 5-30-fach geringer sein als mit genannten Libraries
> curses oder readline.

Danke, auch das ist notiert und steht nun auf meiner Todo-Liste.



--
Gruß, Greetings

Thomas Koenig

unread,
May 8, 2022, 4:44:20 PM5/8/22
to
wolfgang bauer (D) <sch...@gmx.de> schrieb:
>
> Hallo
>
> Ich möchte eine Eingabe für scanf vorgeben, so das man in der
> Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss.

Wie andere schon geschrieben haben, geht das mit Standard-C nicht
genau so.

Was aber geht, ist einen Default-Wert einzustellen und den im
Zweifelsfall einfach nicht zu überschreiben, etwa so:

#include <stdio.h>

int main()
{
char buffer[80];
double a;
int rc;
a = 2.0;
fgets (buffer, sizeof buffer, stdin);
rc = sscanf (buffer, "%lf", &a);
if (rc != 1)
fprintf (stderr, "Warnung: Default-Wert verwendet!\n");

printf ("Wert ist jetzt: %f\n", a);
return 0;
}

oder eine Variation davon (Puffergröße, Fehlerbehandlung,
Rückgabewert von fgets, was passiert, wenn der Benutzer
fasdfasdfasdfa statt 1.2 eingibt, getline() stat fgets(),
falls man POSIX verwendet oder es selber implementiert, ...)

Mit scanf direkt geht das nicht, weil scanf auch über Zeilenenden
hinausliest, um einen Wert zu bekommen.

Helmut Schellong

unread,
May 9, 2022, 6:39:32 AM5/9/22
to
On 05/08/2022 22:44, Thomas Koenig wrote:
> wolfgang bauer (D) <sch...@gmx.de> schrieb:
>>
>> Hallo
>>
>> Ich möchte eine Eingabe für scanf vorgeben, so das man in der
>> Konsole nur noch ohne weitere Eingabe die Returntaste drücken muss.
>
[...]
> Mit scanf direkt geht das nicht, weil scanf auch über Zeilenenden
> hinausliest, um einen Wert zu bekommen.
>

Von stdin her, oder mit sscanf?

Mit setvbuf() kann der Puffermodus geändert werden.

Juergen Ilse

unread,
May 9, 2022, 7:46:26 AM5/9/22
to
Hallo,

Helmut Schellong <r...@schellong.biz> wrote:
> On 05/08/2022 19:41, wolfgang bauer (D) wrote:
>> 08.05.22 , 16:44 , Juergen Ilse:
>>
>>>> puts/putchar schreiben offenbar nicht in den Buffer für scanf.
>>>
>>> Damit das funktioiert, muesstest du auch den TerminalModus passend schalten,
>>> denn per default ist der vermutlich line buffered, so dass erst nach Abschluss
>>> der Zeile die Zeile vom Terminal in die input queue uebertragen wird. Wenn
>>> du das alles moeglichst portabel hinbekommen moechtest, lohnt sich ein Blick
>>> aauf die Funktionen der "curses" library. Portabler als das wirst du es wohl
>>> kaum hinbekommen ...
>> Danke für den Tip. Auch diese Library, neben der schon vorgeschlagenen readline-Library, werde ich mir einmal
>> genauer ansehen.
>>
>
> termio.h, termios.h, read(), etc. sind im POSIX-Standard enthalten.
> Ich konnte damit alle Unix-Systeme und Windows mit Einzeltasten-Lesen ausstatten.
> Im POSIX ist übrigens auch der C-Standard enthalten.

Es gibt noch unixoide Systeme, die nicht sowohl termio.h als auch termios.h
enthalten. Auf aelteren unixoiden Sstemen (die nicht unbedingt posix konform
sind) findet man manchmal per default sogar nur termcap.h. Um das sstem-
uebergreifeend kompatibel zu halten, muss man einen erheblichen Aufwand mit
bedingter Compilierung treiben. Die libcurses existiert jedoch auf nahezu
*allen* unixoiden Systemen, denn sie ist eine Abstraktion der eher low level
Funktionen von termio, termios und termcap.

> Der Aufwand damit dürfte 5-30-fach geringer sein als mit genannten Libraries
> curses oder readline.

Das ist voelliger Unfug. Da ja mehr als ein bischen "Cursorsteuerung" getan
werden soll, sondern eine input-routine mit "Vorgabe" und "Editierfunktion"
implementiert werden soll, ist libreadline (die das alles bereits enthaelt
mit Sicherheit die Version, die weniger Aufwand kostet, als alles von Grund
auf neu zu implementieren. Allerdings sollte man (wenn man die Softwae
weiterzugeben gedenkt) ggfs. auf die Lienzen achten (steht die libreadline
unter GPL oder LGPL? Unter welcher Lizenz soll die neue Software stehen?).

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Helmut Schellong

unread,
May 9, 2022, 11:36:54 AM5/9/22
to
Ich kann da mit konkreter Realität antworten:

Seit den 1980ern habe ich mit termio.h oder termios.h das Tastendruck-Operieren realisiert.
Ich benötige zum Konfigurieren (hin und her) des Terminals etwa 5 Zeilen.
Ich finde das sehr wenig.
Eine Funktion Getch() habe ich entwickelt, um deren Tastenwert einem switch zuzuführen.
Diese Funktion habe ich bereits zu 90% gepostet - einige wenige Zeilen.
Ich finde den geschilderten Aufwand tiny.
Funktionen wie ioctl(), read(), ... sind in der libc enthalten.

Cursor-Steuerung und ähnlich muß stets explizit mittels entsprechender Befehle
implementiert werden - weil: hellseherische Fähigkeiten gibt es da nicht.

Juergen Ilse

unread,
May 9, 2022, 11:54:59 AM5/9/22
to
Hallo,

Helmut Schellong <r...@schellong.biz> wrote:
> On 05/09/2022 13:46, Juergen Ilse wrote:
>>>
>>> termio.h, termios.h, read(), etc. sind im POSIX-Standard enthalten.
>>> Ich konnte damit alle Unix-Systeme und Windows mit Einzeltasten-Lesen ausstatten.
>>> Im POSIX ist übrigens auch der C-Standard enthalten.

Aber nicht umgekeht, und es war zu Begin des Tnreads nach Loesungen im Rahmen
des C-Standards die Rede ...

>> Es gibt noch unixoide Systeme, die nicht sowohl termio.h als auch termios.h
>> enthalten. Auf aelteren unixoiden Sstemen (die nicht unbedingt posix konform
>> sind) findet man manchmal per default sogar nur termcap.h. Um das sstem-
>> uebergreifeend kompatibel zu halten, muss man einen erheblichen Aufwand mit
>> bedingter Compilierung treiben. Die libcurses existiert jedoch auf nahezu
>> *allen* unixoiden Systemen, denn sie ist eine Abstraktion der eher low level
>> Funktionen von termio, termios und termcap.
>>
>>> Der Aufwand damit dürfte 5-30-fach geringer sein als mit genannten Libraries
>>> curses oder readline.
>>
>> Das ist voelliger Unfug. Da ja mehr als ein bischen "Cursorsteuerung" getan
>> werden soll, sondern eine input-routine mit "Vorgabe" und "Editierfunktion"
>> implementiert werden soll, ist libreadline (die das alles bereits enthaelt
>> mit Sicherheit die Version, die weniger Aufwand kostet, als alles von Grund
>> auf neu zu implementieren. Allerdings sollte man (wenn man die Softwae
>> weiterzugeben gedenkt) ggfs. auf die Lienzen achten (steht die libreadline
>> unter GPL oder LGPL? Unter welcher Lizenz soll die neue Software stehen?).
>
> Ich kann da mit konkreter Realität antworten:
>
> Seit den 1980ern habe ich mit termio.h oder termios.h das Tastendruck-Operieren realisiert.
> Ich benötige zum Konfigurieren (hin und her) des Terminals etwa 5 Zeilen.
> Ich finde das sehr wenig.

Es ging aber nicht nur um das konfigurieren des Terminals, sondern um die
Loesung der Aufgabe des Threadstarters. Das lief dann letztendlich auf
so etwas wie einen "Eingabe-Editor mit Antwortvorgabe" hinaus. Die
libreadline enthaeelt bereits die gesamte Funktionalitaet, die low-level
Terminal-Routinen *ausschliesslich* die Terminal-Steuerung, waehrend alles
andere dann "von Hand" neu zu programmieren waere.

libcurses abstrahiert die Terminalsteuerung (so dass einfache Faelle von
"Terminal-Mode umsetzen" ggfs. sogar geringfuegig aufwendiger sein koennten.
Sobald die Anforderungen etwas umfangreicher werden, hat aber curses bei
wachsender Komplexistaet immermehr Vorteile.

Tschuess,
Juergen Ilse (juergenqusenet-verwaltung.de)

Helmut Schellong

unread,
May 9, 2022, 12:52:38 PM5/9/22
to
On 05/09/2022 17:54, Juergen Ilse wrote:
> Hallo,
>
> Helmut Schellong <r...@schellong.biz> wrote:
>> On 05/09/2022 13:46, Juergen Ilse wrote:
>>>>
>>>> termio.h, termios.h, read(), etc. sind im POSIX-Standard enthalten.
>>>> Ich konnte damit alle Unix-Systeme und Windows mit Einzeltasten-Lesen ausstatten.
>>>> Im POSIX ist übrigens auch der C-Standard enthalten.
>
> Aber nicht umgekeht, und es war zu Begin des Tnreads nach Loesungen im Rahmen
> des C-Standards die Rede ...

Ja, und ich wollte das dementsprechend per scanf lösen.
Dann bekam ich aber Schimpfe, ich hätte alles falsch verstanden, und das
erste Posting sagte bereits, daß das in Standard-C nicht lösbar sei.
Bei mir ist das dann so etwas:
writef(FDWR, "\033[0m\033[D");
Finde ich ganz simpel: ANSI-Sequenzen zur Terminalsteuerung.

> libcurses abstrahiert die Terminalsteuerung (so dass einfache Faelle von
> "Terminal-Mode umsetzen" ggfs. sogar geringfuegig aufwendiger sein koennten.
> Sobald die Anforderungen etwas umfangreicher werden, hat aber curses bei
> wachsender Komplexistaet immermehr Vorteile.
>
>

Ja, bei hoher Komplexität hat curses Vorteile.
Ich kenne curses, habe in den 1990ern mich damit mal befaßt.

Ich fand folgendes aber insgesamt angemessener:

//...
case K_U :
case K_PGU :
if (udpos<=0) goto JBEEP;
if (c==K_U) --udpos;
if (c==K_PGU) udpos-=nud;
if (udpos<0) udpos=0;
goto DWNGZ;
case K_D :
case K_PGD :
if (udpos>=nzeil) goto JBEEP;
if (c==K_D) ++udpos;
if (c==K_PGD) udpos+=nud;
if (udpos>=nzeil) { udpos=nzeil; goto KESC; }
DWNGZ:;
zi= GetZ(Zeile, udpos);
cup=Cup;
break;
case K_L :
if (cup>0) CursLR(-1), Cup=--cup;
continue;
case K_R :
if (cup<zi) CursLR(1), Cup=++cup;
continue;
case K_PGUt:
case K_HOME:
cup=0;
//...

Juergen Ilse

unread,
May 9, 2022, 3:14:09 PM5/9/22
to
Helmut Schellong <r...@schellong.biz> wrote:
> On 05/09/2022 17:54, Juergen Ilse wrote:
>>>> Das ist voelliger Unfug. Da ja mehr als ein bischen "Cursorsteuerung" getan
>>>> werden soll, sondern eine input-routine mit "Vorgabe" und "Editierfunktion"
>>>> implementiert werden soll, ist libreadline (die das alles bereits enthaelt
>>>> mit Sicherheit die Version, die weniger Aufwand kostet, als alles von Grund
>>>> auf neu zu implementieren. Allerdings sollte man (wenn man die Softwae
>>>> weiterzugeben gedenkt) ggfs. auf die Lienzen achten (steht die libreadline
>>>> unter GPL oder LGPL? Unter welcher Lizenz soll die neue Software stehen?).
>>>
>>> Ich kann da mit konkreter Realität antworten:
>>>
>>> Seit den 1980ern habe ich mit termio.h oder termios.h das Tastendruck-Operieren realisiert.
>>> Ich benötige zum Konfigurieren (hin und her) des Terminals etwa 5 Zeilen.
>>> Ich finde das sehr wenig.
>>
>> Es ging aber nicht nur um das konfigurieren des Terminals, sondern um die
>> Loesung der Aufgabe des Threadstarters. Das lief dann letztendlich auf
>> so etwas wie einen "Eingabe-Editor mit Antwortvorgabe" hinaus. Die
>> libreadline enthaeelt bereits die gesamte Funktionalitaet, die low-level
>> Terminal-Routinen *ausschliesslich* die Terminal-Steuerung, waehrend alles
>> andere dann "von Hand" neu zu programmieren waere.
>
> Bei mir ist das dann so etwas:
> writef(FDWR, "\033[0m\033[D");
> Finde ich ganz simpel: ANSI-Sequenzen zur Terminalsteuerung.

Es gibt mehr als nur ANSI Terminals (sogar richtigin der Praxis aktiv
verwendet), und manche sind sogar in keiner Weise ANSI kompatibel ...
Die von dir hier praesentierte Methode ist also alles andere als portabel,
im Gegensatz zu cureses oder readline (da beide libraries die notwendigen
Funktionen soweit wie moeglich *portabel* fuer diverse Terminaltypen um-
setzen und nicht nur fuer ein einziges).
Warum? Weil du diesen Kram selbst gebastelt hast? In realen Programmen
ist man IMHO mit curses *erheblich* besser bedient. Und ein vollstaendiger
Eoingabe editor (wie ihn libreadline bietet) ist das bei weitem auch noch
nicht ...

Tschuess,
Juergen Ilse (juergenqusenet-verwaltung.de)

Helmut Schellong

unread,
May 9, 2022, 4:39:45 PM5/9/22
to
Ich habe seit den 1980ern _nur_ ANSI-Terminals kennengelernt (15..20).
Falls ich einmal unbedingt mit einem Nicht-ANSI-Terminal klarkommen
müßte, würde ich wohl curses verwenden.
Das ist angesichts der Realität jedoch äußerst unwahrscheinlich.

Ich war also _nur_ mit ANSI-Terminals konfrontiert.
Und alle diese sind untereinander fast identisch bei den Sequenzen!
ANSI-Sequenzen sind ja schließlich von ANSI _standardisierte_ Sequenzen.
Es ist ein vollständiger Kommandozeilen-Editor, etwas besser als DOSKEY.
Ich hatte mich in den 1990ern so 2-3 Tage mit curses beschäftigt.
Und ich habe mich danach nach einiger Überlegung gegen curses entschieden.
Nicht allumfassend gegen curses, sondern nur meine geplanten Projekte betreffend.

=================================================================================
char *
readline (const char *prompt);

COPYRIGHT
Readline is Copyright (C) 1989-2014 Free Software Foundation, Inc.

DESCRIPTION
readline will read a line from the terminal and return it, using prompt
as a prompt. If prompt is NULL or the empty string, no prompt is
issued. The line returned is allocated with malloc(3); the caller must
free it when finished. The line returned has the final newline
removed, so only the text of the line remains.

readline offers editing capabilities while the user is entering the
line. By default, the line editing commands are similar to those of
emacs. A vi-style line editing interface is also available.
=================================================================================

Es ist hier zu bemerken, welches Konzept hier vorliegt.
Für mich nicht/kaum gebrauchsfähig.

Was ich damals mindestens brauchte:

Einzeltastendruck-Bedienung
Einfüge- und Überschreib-Modus
Löschen, Springen HOME & END, Bewegen links & rechts
Automatisches Speichern jeder eingegebenen Zeile
Wieder hochholen & back jeder gespeicherten Zeile; Springen PGup,PGdown
Dabei die letzte Schreibposition speichern und verwenden

Meine Lösung ist einfacher und schneller bedienbar, dennoch voll ausreichend.
0 new messages