Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: NANOcoder am 12. February 2011, 23:53
-
Guden allezusammen ^^
Ich bin recht neu hier und ist mein erster Beitrag.
Wie das Theme schon heist getc und Tastaturtreiber.
Ich steh grad vor dem Problem eine funktion zu schreiben um Buchstaben oder überhaupt erst mal zeichen einzulesen nach einem ENTER tastendruck. Ich hab zwar ähnliche dinge in sufu gesehen aber nichts richtiges gefunden und wenn doch tut mir leid das ich nicht gefunden haben ;)
Also ich kann zwar zeichen einlesen und diese dann in der main vergleichen aber wie kann ich eine "scanf()" ähnliche funktion schrieben die erst nach einem ENTER druck auch einliest ? Da wenn ich eine einfache if vergleich mache dann liest er sofort den buchstabe bei Tastendruck.
Theoretisch dachte ich das ich da was bei den Interrupts machen muss aber ich weiß nicht wie genau das gehen soll auch habe ich mehrere tuts durch gelesen wo zwar der code steht aber nicht wie das genau funktioniert, denn ich will ja keine codes schnurren oder einfach nur kopieren :-D
Ich hoffe ihr konntet verstehen was ich meine und wollte noch mal sagen das ich jetzt keinen Code-Schnipsel von jeden möchte um den einfahc nur copy-paste mache . Theoretische Iden reichen mir erst mal aus
danke schon mal für ein paar theoretische Anregungen ^^
-
wenn ich dich richtig verstehe pollst du momentan und willst das ganze jetzt insterrupt gesteuert machen?
PNoob
-
naja was heist will ^^ also ich will ne getc funktion es gibt zwar mehrere die schon erklärt sind auch hier im forum aber wie bekomme ich das hin das er die zeichen bzw. später dann strings erst nach ENTER "liest" da ich momentan eine globale variabel habe die gespeichert wird und in in die getc funktion übergeben wird. Später will ich dann befehle eingeben können um systembefehle wie "reboot" . Nun weiß ich nicht wie ich das mit dem ENTEr tastendruck regeln soll .
Sagen wir nen einfaches beispiel ich hab ne einfache if schleife und wenn ich 0 drücke dann soll der pc herunterfahren bei mir ist das momentan so, sobald ich die 0 drücke rebootet das system automatisch aber nicht nach einem ENTER wie man es von alten C Konsolenprogs gewohnt ist xD
-
Soll es für DOS sein?:
Ralf Browns Interrupt List(RBIL):
http://www.pobox.com/~ralf
http://www.pobox.com/~ralf/files.html
ftp://ftp.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/
RBIL->inter61b.zip->INTERRUP.F
--------D-210A-------------------------------
INT 21 - DOS 1+ - BUFFERED INPUT
AH = 0Ah
DS:DX -> buffer (see #01344)
Return: buffer filled with user input
Notes: ^C/^Break are checked, and INT 23 is called if either detected
reads from standard input, which may be redirected under DOS 2+
if the maximum buffer size (see #01344) is set to 00h, this call returns
immediately without reading any input
SeeAlso: AH=0Ch,INT 2F/AX=4810h
Format of DOS input buffer:
Offset Size Description (Table 01344)
00h BYTE maximum characters buffer can hold
01h BYTE (call) number of chars from last input which may be recalled
(ret) number of characters actually read, excluding CR
02h N BYTEs actual characters read, including the final carriage return
Dirk
-
Hm, wen interessiert heutzutage noch DOS? ;)
Du willst ein char-Array nehmen und dort hintereinander Zeichen einlesen. Wenn Enter gedrückt wird, schreibst du ein Nullbyte ans Ende der eingelesenen Zeichen und fertig ist dein String. Zum Vergleichen musst dir dann ein strcmp() schreiben.
-
Hallo,
für ein scanf benötigt man einen internen Puffer in den erst mal alle Zeichen (die der User so eintippt) rein kommen und das ganze erst dann weitergeleitet wird wenn das ENTER kommt.
Grüße
Erik
-
hey danke für die schnellen antworten ^^
das heist ich mach ne vari char als array und als ENTER muss ich ein NUllbyte am ende des strings rein schreiben.
@erik.vikinger
also eine globale variabel steht schon da ich ja schon einzelne zeichen einlesen kann nur mit mit ENTER prob muss ich noch mal ausprobieren ^^
@all
danke schon mal ich werd mich schonmal damit auseinder setzten und mal nen wenig coden :-D
NANOcoder
-
Du liest so lange in einen Puffer ein, bis du ein Enter findest, erst danach analysierst du, was du eigentlich gefunden hast. Das kann dann z.B. so aussehen:
char buf[25], tmp; int index=0;
while( index < 25 ) { /* Pufferüberlauf verhindern */
tmp = lies_ein_zeichen();
if ( (tmp != 13) && (tmp != 10) ) { /* kein ENTER (CR/LF) gedrückt */
buf[index] = tmp;
index = index + 1;
} else {
break; /* das war jetzt ein ENTER, mach weiter */
}
}
if ( (buf[0] == 'b') && (buf[1] == 'o') && (buf[2] == 'o') && (buf[3] == 't') ) {
/* er hat 'boot' eingegeben */
reboote_das_system();
}
Den Vergleich unten solltest du durch strncmp ersetzen, wenn du eine passende Funktion hast. Für eine richtige Shell gehört noch ein bisschen mehr dazu, aber das ist ein Ansatz.
Viel Erfolg!
-
hey danke für die infos muss nur noch zeit finden das alles zu machen hab auch schon ne idee wie ich es ungefähr mache ;)
-
Hallo,
auch die Backspace-Taste und die Entfernen-Taste (und natürlich die Kursor-Tasten für Links und Rechts) sollten beim Zusammenbauen des Strings korrekt benutzt werden können (sonnst könnten die User der Shell niemals einen Tippfehler korrigieren).
Grüße
Erik
-
theoretisch müsste ich ja den bei einer entfern-Taste oder backspace ein zeichen aus dem string herauslöschen udn diesen dann wieder neu rein schreiben in den string.
NANOcoder
-
jo genau. bei der entf Taste den der nach dem aktuellem Curser ist und bei der Backspace Taste den hinter dem Curser. ein druck auf die entf Taste muss wenn der Curser am ende des eingegebenen steht ohne effekt bleiben.
PNoob
-
Hallo,
wenn die Backspace-Taste oder die Entfernen-Taste mitten im Text gedrückt wird muss der hintere Teil des Strings natürlich um ein Byte nach vorne kopiert werden (es dürfen keine Lücken entstehen).
Wenn die Backspace-Taste am Stringanfang gedrückt wird dann muss diese auch ohne Effekt bleiben.
Das ist aber alles nicht so schwer, das läuft nur auf ne kleine Hand voll Regeln hinaus die das Verhalten exakt vollständig beschreiben.
Grüße
Erik
-
Hm, wen interessiert heutzutage noch DOS? ;)
Na alle Programmierer die vom Retro-Feeling der alter DOS-Kisten begeistert sind!
Dirk
-
Hallo mal wieder ^^,
Ich hab mal in meiner main.c den code von svenska laufen lassen als Test um zu schauen ob es überhaupt funtz mit meiner strcmp funktion jedoch passiert da rein gar nichts :(
Hier meine strcmp funktion:
...
int strcmp(char* string1, char* string2)
{
int i = 0;
int fail = 0;
while(string1[i] != '\0' && string2[i] != '\0')
{
if(string1[i] != string2[i])
{
fail = 1;
break;
}
i++;
}
if( (string1[i] == '\0' && string2[i] != '\0') || (string1[i] != '\0' && string2[i] == '\0') )
fail = 1;
return fail;
}
...
dann in der main.c :
...
char buf[25], tmp; int index=0;
char reb[] = {'r','e','s','t','a','r','t'};
for(;;)
{
while( index < 25 )
{
tmp = getc();
if ( (tmp != 13) && (tmp != 10) )
{
buf[index] = tmp;
index++;
}
else
{
break;
}
}
if ( strcmp(buf,reb) == 0 )
{
restart();
}
//if(...)
//{
//...
//}
}
...
Wie gesagt um zu sehen ob es überhaupt funktioniert hab ich das mal das so improvisiert.
Wenn ich jetzt das laufen lasse mittels VirtualBox kann ich zwar wie gewohnt meine schönen Buchstaben am Bildschirm tippen jedoch passiert nicht wenn ich z.B restart eingebe , muss ich da villt so was wie nen "volatile" deklarieren ?
Oder es liegt an meiner strcmp-funktion, wobei ich die tausend mal durch gechekt habe.
Wenn das dann funtz will ich es so umschreiben das wenn man nen fehler macht das noch verbessern kann und schließlich dann ENTER-drückt um die strings dann zu vergleichen.
NANOcoder
-
Hallo,
char reb[] = {'r','e','s','t','a','r','t'};
Kann sein das mein C etwas eingerostet ist aber ich denke dieser String ist nicht 0-terminiert.
Grüße
Erik
-
upps ^^ naja ich habs auch mit 0-terminiert und funtz auch net das war halt so als ich das wieder umgeändert hatte aus irgendein grund ^^
Und die restart()-funktion funktioniert einwandfrei wenn ich sie mit ner ganz einfachen if-schleife vergleiche mit ner nummer wie z.b. 1 oder 'a'
prob is jetzt nur strings und nach einem ENTER ^^ Ich bin noch mal selbst am nachschauen wo der fehler liegt aber bis jetzt habe ich keine idee. Hoffentlich ist das nicht so nen hässlicher kleiner fehler ;)
Grüße
NANOcoder
-
Funktioniert dein getc()?
Was gibt dir getc() für Werte zurück, wenn du Tasten drückst? Welchen Wert hat ENTER?
Ich bin im Beispielcode von ASCII-Werten ausgegangen, nicht von Tastatur-Scancodes.
Die Eingabe wird übrigens nicht nullterminiert, da müsstest du hinter das "else" noch ein >>buf[index]='\0';<< setzen, und du solltest den Teststring ebenfalls nullterminieren.
Das strcmp() sieht spontan erstmal gut aus.
Gruß,
Svenska
-
char reb[] = {'r','e','s','t','a','r','t'};
Das kann man übrigens auch so schreiben und hat damit die Nullterminierung auch erledigt:
char reb[] = "restart";
Was die Nullterminierung angeht, fehlt sie natürlich nicht nur im else-Zweig, sondern auch, wenn mehr als 25 Zeichen eingegeben wurden. Ich würde die Schleife also nur bis 24 laufen lassen und dahinter ein buf[index] = '\0'; einbauen.
Und strcmp sieht zwar für deinen Zweck hier ausreichend aus, ist aber natürlich kein echtes strcmp (man kann nicht unterscheiden, welcher String "größer" ist).
-
Also die getc()-funktion geht hab ich schon mehrmals ausprobiert, die funktion sollte funzen da ich ,wie gesagt, sie schon mit einzelnen zeichen 1 oder a probiert habe und dann noch eine restart funktion gemacht habe , hat super geklappt also daran sollte es nicht liegen.
Also die strcmp war mir auch erst spontan eingefallen und hab mir auch überlegt das sie ja "erst" mal ausreichen sollte. Bei mir dauert das immer ein wenig bis sich da was verändert und fällt mir immer spontan ein das umgeändert werden muss :-D
Ich werde das ganze noch mal ausprobieren und austesten ich werde mich dann melden.
Danke noch mal für die schnellen Antworten :wink:
-
Hallo wieder,
war ne zeit lang nicht online wegen schulische sache Prüfung etc . ;)
Naja ich hab versuhct was ihr sagt nun es klappt immer noch nicht jedoch bin ich überzeugt es liegt an den rückgabewert von getc hab aber keine idee wie ich es nun lösen soll. Wenn ich nur getc() laufe und den char wiedergben der eingelesen wurde wird auf den bildschrim eine zeile übersprüngen für die normale ENTER eingabe und ein zweites mal durch die wiedergabe die ja durch getc() gelesen wurde. Nun es hieß ich soll
buf[index]='\0'; hinter dem else machen. Aber muss ich nicht ein \n machen und ein \0 hinten dran schreiben als zusätzlichen argument ? Ich arbeite mit scancodes um evtl. Missverständisse zu beseitigen ^^ Sry wenn ich immer in so großen zeitabschnitten schreibe.
NANOcoder
-
Wenn du ein \n im String haben willst, musst du es natürlich reinschreiben. Über das \0 wurde eigentlich nur gesagt, dass es auf jeden Fall hinten dran sein muss, damit es ein ordentlicher String ist, mit dem man Sachen wie strcmp machen kann.
-
hey also das \0 muss rein um den string ordenlich zu beenden , das habe ich verstanden. jedoch vorher soll "else" erkennen das ich jetzt Enter drücke. Das muss ich doch noch definieren, oder nicht ?
NANOcoder