EXGET (C)

Die Idee zu der Funktion exget (Extended Get) kam mir beim programmieren mit C. Alle Eingaberoutinen für die Tastatur, die in C bereits verfügbar waren, waren relativ unkomfortabel oder sogar gefährlich.

Unkomfortabel, weil beim Lesen von Daten mit scanf die Eingabe bei einem Whitespace (Leertaste, Tabulatortaste, Return-Taste) beendet wird. Dies macht sich insbesondere bei Eingabe von Strings, in denen ein Leerzeichen enthalten sein soll, unangenehm bemerkbar.

Gefährlich, weil man bei Eingabe mittels gets (get String) zwar auch Whitespace einiesen kann, diese Funktion aber nicht prüft, ob man vorher genügend Speicher reserviert hat. Reserviert man also für die Variable, mit der man gets aufruft, nicht genügend Speicher, kann man leicht bei der Eingabe zuviel Zeichen tippen und damit unkontrolliert Werte im Speicher zerstören, die vielleicht noch wichtig gewesen wären. Die Folge kann ein Systemabsturz sein.

Hier greift nun die Funktion exget ein. Mit ihrer Hilfe wird es möglich, Strings in C sehr komfortabel einzulesen. Der korrekte Aufruf lautet:

exget(&eing, laenge, dfstr, Schalter)

Dabei müssen die Parameter wie folgt deklariert worden sein:

char *eing 
int laenge 
int dfstr 
int schalter

Mit laenge kann man angeben, wie lang der einzulesende String maximal werden darf. Hierbei ist zu beachten, daß man den Wert um l größer angeben muß als die tatsächliche Länge des Strings, da für das String-Endezeichen (‘\0’) ja auch ein Byte benötigt wird. Der String kann dann nur bis zu dieser maximalen Länge eingegeben werden. Versucht man mehr Zeichen einzugeben, ertönt eine Glocke.

Zudem läßt sich ein Default-String auf den Bildschirm bringen, der dann ediert werden kann. Dazu muß eing schon auf einen String zeigen und dfstr muß den Wert 1 bekommen. In dem Fall wertet exget den Default-String aus und gibt ihn auf dem Bildschirm aus. Hat der Default-String eine kürzere Länge als man in laenge angegeben hat, so wird laenge auf diese kürzere Länge gesetzt, so daß sich nur ein String bis zu dieser Länge eingeben läßt. Dies dient der Verhinderung des Hineinschreibens des Strings in wichtige Speicherstellen. Schließlich zeigt eing dann vielleicht nicht auf einen Speicherbereich, der groß genug ist. Will man also einen Default-String edieren, der kürzer als laenge ist, muß man ihn mit Blanks auffüllen, bis er laenge erreicht hat. Default-Strings, die länger sind als in laenge angegeben, werden nur bis laenge ausgegeben und können nur bis zu dieser Länge ediert werden. Wird dfstr auf einen anderen Wert als 1 gesetzt, wird kein Default-String ausgegeben.

Über den Parameter Schalter hat man die Möglichkeit, in der 24sten Zeile des Bildschirms eine Ausgabe zu erzeugen, mit der man die Eingabe kontrollieren kann. Dazu muß Schalter den Wert 1 erhalten. Bei allen anderen Werten erscheint keine Statuszeile. Hat Schalter den Wert 1, wird folgendes ausgegeben:

AP: XXX AL: XXX ML: XXX

Hierbei bedeutet AP die aktuelle Position des Cursors innerhalb des Eingabe-Strings, AL dessen aktuelle und ML dessen maximale Länge. Da diese Ausgaben bei eigenen Programmen stören können, lassen sie sich über den Parameter Schalter ausschalten.

Der String kann während der Eingabe ediert werden, wozu man diverse Möglichkeiten zur Verfügung hat:

< Backspace >

Mit der Backspace-Taste wird das links vom Cursor stehende Zeichen gelöscht und der rechts vom Cursor stehende Text nachgezogen. Dies dürfte jedem aus der Textverarbeitung hinreichend bekannt sein.

< Delete >

Mit der Delete-Taste wird das Zeichen, das unter dem Cursor steht, gelöscht und der rechts vom Cursor stehende Text nachgezogen.

< Insert >

Mit der Insert-Taste kann man zwischen dem Überschreib- und dem Einfügemodus Umschaltern Bei jedem Druck auf diese Taste wird der Modus gewechselt. Den augenblicklichen Modus kann man am Cursor erkennen. Im Überschreibmodus hat man einen ausgefüllten stehenden Cursor, während man im Einfügemodus einen ausgefüllten blinkenden hat.

< Pfeil links >

Mit dieser Taste wird der Cursor um ein Zeichen nach links bewegt.

< Pfeil rechts >

Mit dieser Taste wird der Cursor um ein Zeichen nach rechts bewegt.

< CLR/HOME > oder < Shift Pfeil links >

Mit diesen Tasten wird der Cursor auf den Anfang des Eingabe-Strings gesetzt.

< Shift CLR/HOME > oder < Shift Pfeil rechts >

Mit diesen Tasten wird der Cursor auf das Ende des Eingabe-Strings gesetzt.

< Escape >

Mit der Escape-Taste kann man die Eingabe von neuem beginnen. Das bis dahin Getippte (oder der Default-String) verschwindet vom Bildschirm, der Cursor steht am Anfang des Eingabefeldes.

Es ist noch darauf zu achten, daß die Konstanten TRUE und FALSE mit der Präprozessoranweisung #define deklariert werden.

Damit der Compiler alle Prototypen finden kann, müssen die folgenden Header-Dateien eingebunden werden:

So, das war’s. Beim Arbeiten mit exget wünsche ich viel Spaß. Anregungen und Verbesserungsvorschläge nehme ich gerne entgegen (garantiere aber nicht, daß ich selbige implementieren werde). Die vorliegende Funktion habe ich mit Turbo C 2.0 von Borland entwickelt, sie sollte aber ohne große Probleme auch mit anderen C-Compilern verwendet werden können.


/*---------------------------------------------------
    Funktion exget zum einlesen von Strings 
             August 1990 von 
             Helmut Lehmkuhl 
    (c) MAXON Computer GmbH 1991
-----------------------------------------------------*/
#include <stdio.h>
#include <aes.h> 
#include <ext.h>
#include <tos.h>
#include <ctype.h>

#define TRUE 1 
#define FALSE 0

void exget(char **wort, int laenge, int dfstr, int schalter);

main()
{
    char *eing;

    printf("\033EBitte geben Sie einen String ein:");
    eing = "Dies ist eine Probe"; 
    exget(&eing, 20, 1, 1);
    printf("\n\nlhre Eingabe war : %s\n", eing);
    getch(); 
    return(0);
}

void exget(char **wort, int laenge,int dfstr, int schalter)
{
    char y, * zwwort;
    int schleife, i, z, ende, insert;

    zwwort = *wort; 
    if( dfstr == 1 )
    {
        i = 0;
        while( zwwort[i] != '\0' && i < (laenge-1))
        {
            putch(zwwort[i]); 
            i++;
        }
        if( i < (laenge - 2) )
            laenge = i + 1; 
        ende = i;
    }
    else
    {
        i = 0; 
        ende = 0;
    }
    insert = FALSE;
    Cursconf(1, 0);
    Cursconf(3, 0);
    if( schalter == 1 )
    {
        printf ("\033j");
        printf("\033Y\067\040 AP: %3d AL: %3d ML: %3d",i+1, ende+1, laenge); 
        printf ("\033k");
    }
    while ( (z = evnt_keybd() ) != 7181 )
    {
        switch (z)
        {
            case 3592 : /* Backspace gedrückt */
                if ( i > 0 )
                {
                    if ( i == ende )
                    {
                        printf("\b \b"); 
                        i--; 
                        ende--; 
                        if ( i < 0 ) 
                            i = 0;
                    }
                    else /* Fall für Backspace in der Mitte der Eingabe */
                    {
                        printf("\b \b"); 
                        i--;
                        for( schleife = i; schleife < ( ende - 1 ); schleife++)
                        {
                            zwwort[schleife] = zwwort[schleife+1];
                            printf("%c", zwwort[schleife]);
                        }
                        printf(" \b"); 
                        ende--;
                        schleife = ende; 
                        while( schleife != i )
                        {
                            printf("\b"); 
                            schleife--;
                        } /* while( schleife != i ) */
                    } /* if( i == ende ) */
                } /* if( i > 0 ) */
                else
                    printf("\a"); 
                break;
            case 21375: /* Delete gedrückt */
                if( i != ende ) /* Nur der Fall für Delete in der Mitte */
                {
                    printf (" \b");
                    for( schleife = i; schleife < ( ende-1 ); schleife++)
                    {
                        zwwort[schleife] = zwwort[schleife+i];
                        printf("%c", zwwort[schleife]);
                    }
                    printf(" \b"); 
                    ende--;
                    schleife = ende; 
                    while( schleife != i )
                    {
                        printf("\b"); 
                        schleife--;
                    }
                } /* if( i != ende ) */
                else
                    printf("\a"); 
                break;
            case 20992: /* INSERT gedrückt */ 
                if( insert == TRUE )
                {
                    insert = FALSE;
                    Cursconf(3, 0);
                }
                else
                {
                    insert = TRUE;
                    Cursconf(2, 0);
                }
                break;
            case 19200: /* Pfeil links gedrückt */
                if ( i > 0 )
                {
                    printf("\b");
                    i--;
                }
                else
                    printf("\a" ); 
                break;
            case 19712: /* Pfeil rechts gedrückt */
                if ( i < ende )
                {
                    printf("%c", zwwort[i]); 
                    i++;
                }
                else
                    printf("\a"); 
                break;
            case 18176: /* CLR/HOME gedrückt */
            case 19252: /* Shift Pfeil links */
                /* An den Anfang des Eingabestrings springen */ 
                while ( i > 0 )
                {
                    printf("\b"); 
                    i--;
                }
                break;
            case 18231: /* Shift CLR/HOME gedrückt */
            case 19766: /* Shift Pfeil rechts gedrückt */
                /* An das Ende des Eingabestrings springen */ 
                while( i < ende )
                {
                    printf ("%c", zwwort[i]); 
                    i++;
                }
                break;
            case 283: /* ESCAPE gedrückt */
                /* Eingabe von neuem beginnen */ 
                while( i < ende )
                {
                    printf(" "); 
                    i++;
                }
                while( i > 0 )
                {
                    printf("\b \b");
                    i--;
                }
                ende = Ö; 
                break; 
            default:
                y = (char) z; 
                if( isprint(y) )
                {
                    if( ende < (laenge - 1) || (insert == FALSE && i != ende) )
                    {
                        if ( insert == FALSE )
                        {
                            putch(y); 
                            zwwort[i] = y; 
                            if ( i == ende ) 
                                ende++; 
                            i++;
                        }
                        else /* Buchstaben Mitte einfügen */ 
                        {
                            putch(y);
                            for( schleife = ende; schleife > i; schleife--) 
                                zwwort[schleife] = zwwort[schleife-1]; 
                            zwwort[i] = y; 
                            i++; 
                            ende++;
                            for( schleife = i; schleife < ende; schleife++) 
                                printf("%c", zwwort[schleife]); 
                            schleife = ende; 
                            while( schleife != i )
                            {
                                printf("\b"); 
                                schleife--;
                            }
                        } /* if( insert == FALSE ) */
                    } /* if( ende < (laenge - 1) ) */
                    else
                        printf("\a");
                } /* if( isprint(y) ) */
            } /* switch (z) */
            if( Schalter == 1 )
            {
                printf("\033j”);
                printf ("\033Y\067\040 AP; %3d AL: %3d ML; %3d", i + 1, ende + 1, laenge); 
                printf("\033k");
            }
        } /* while ( (z = evnt_keybd ()) != 7181 ) */
        zwwort[ende] = '\0';
        *wort = zwwort; 
        if ( schalter == 1 )
            printf("\033j\033Y\067\040\033k");
        Cursconf(0, 0);
        return;
    }

Helmut Lehmkuhl
Aus: ST-Computer 05 / 1991, Seite 78

Links

Copyright-Bestimmungen: siehe Über diese Seite