Von der DEA zum Quellcode, wie geht man am besten vor?
-
Ich habe nochmal eine korrigierte Fassung der DEA Grafik hochgeladen.
Das Newlinezeichen als Leerzeichensubstitution lasse ich so bestehen.
-
Ich habe nochmal eine korrigierte Fassung der DEA Grafik hochgeladen.
http://img267.imageshack.us/img267/1221/deaw.png
-
-
so sollts doch reichen? schrieb:
der passende code:
int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; while(1){//q0 c = *p++; if(c==' '){//goto q1 while(1){ c = *p++; if(c!=' '){ p--; break;//goto q0 } } }else if(c==0){//goto q3 break; }else *i++ = c; } *i=0; printf(in); return 0; }
-
int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; while(1){//q0 c = *p++; if(c==' '){//goto q1 while(1){ c = *p++; if(c!=' '){ break;//goto q0 } } }else if(c==0){//goto q3 break; } *i++ = c; } *i=0; printf(in); return 0; }
-
der letzte post war falsch bei sowas wie " \0"!
-
so sollts doch reichen? schrieb:
Nein, denn in q1 wird ja mindestens 1 Leerzeichen übernommen.
Wenn du also in q1 verbleibst und kein q2 einführst, dann übernimmst du alle leerzeichen.Denn von wo soll bei deiner DEA bzw, die State Machine denn Wissen, wann ein Leerzeichen zu übernehmen ist und wann nicht?
-
so hab ich doch auch nur Q0,Q1,Q2
#include <stdio.h> #include <stdlib.h> int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; Q0: while(1){ c = *i++ = *p++; if(c==0){ goto Q2; }else if(c==' '){ goto Q1; } } Q1: while(*p==' '){ p++; } goto Q0; Q2: printf(in); return 0; }
-
also ich denke mir ist klar warum man 4 knoten braucht
#include <stdio.h> #include <stdlib.h> enum{S_COPY_CHAR,S_SPACE,S_END,S_SPACE_SPACE}; int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; char state = S_COPY_CHAR; while(1){ switch(state){ case S_COPY_CHAR: c = *i++ = *p++; switch(c){ case 0 : state = S_END; break; case ' ': state = S_SPACE; break; } break; case S_SPACE: c = *p++; switch(c){ case ' ': /*state = S_SPACE_SPACE;*/ break; default : state = S_SPACE_SPACE; break; } break; case S_SPACE_SPACE: p--; state = S_COPY_CHAR; break; case S_END: puts(in); return 0; break; } } }
-
rolleyes schrieb:
int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; while(1){//q0 c = *p++; if(c==' '){//goto q1 while(1){ c = *p++; if(c!=' '){ break;//goto q0 } } }else if(c==0){//goto q3 break; } *i++ = c; } *i=0; printf(in); return 0; }
Wie sicherst du denn bei dir die Leerzeichen?
Bei deinem Code werden die komplett ignoriert, und wenn man deinen Code in so etwas ändert:#include <stdio.h> int main(void) { char in[] = "ha ha ha ha ha ha"; char *i = in; char *p = in; char c; while(1){//q0 c = *p++; if(c==' '){//goto q1 while(1){ c = *p++; if(c!=' '){ break;//goto q0 } } *i++ = c; }else if(c=='\0'){//goto q3 break; } *i++ = c; } *i=0; printf("%s",in); return 0;
Dann werden die Leerzeichen auch nicht gesichert, weil sich die Breakanweisung auf die erste while Schleife bezieht und nicht auf die zweite.
Fügt man das *i++ = c; vor der geschleiften Klammer ein, dann werden wieder zu viele Leerzeichen gesichert.
-
ich auch schrieb:
Ich habe nochmal eine korrigierte Fassung der DEA Grafik hochgeladen.
http://img267.imageshack.us/img267/1221/deaw.pngDeine DEA wird immer von q2 nach q0 springen.
D.h. das passiert bei dir schon bei der ersten 0.
Wenn aber darauf eine zweite 0 kommt, dann bist du schon wieder bei q0.Und das kann so nicht richtig sein.
Eigentlich mußt du in q1 so lange verbleiben, bis die letzte 0 kommt und dann wird mit dieser 0 nach q2 gesprungen.Da das AFAIK so aber bei einer DEA nicht realisierbar ist, müßte man das irgendwie anders lösen.
Im Prinzip braucht man so etwas:http://img526.imageshack.us/img526/2161/deaproblem.png
Kennt sich hier jemand besonders gut mit DEAs aus und wie man das genannte Problem korrekt in ein DEA Diagramm realisiert?
-
Der letzte DEA hat das Problem, dass er fordert, dass nach dem Leerzeichen unbeding nochmal ein Zeichen kommen muss, dass keins ist.
Ich würde sagen wir brauchen drei Zustände:
A: letztes gelesenes Zeichen war kein Leerzeichen
B: letztes gelesenes Zeichen war Leerzeichen
C: FinalzustandA ist der Startzustand
- Bei Eingabe von \0 geht es sowohl von A, als auch von B zu C, das Zeichen wird dabei mit ausgegeben.
- Eingabe eines Nicht-Leerzeichens geht von A nach A (und gibt das Zeichen aus) und von B nach A (und gibt das Zeichen aus).
Eingabe eines Leerzeichens führt von A nach B (das Zeichen wird ausgegeben)
Eingabe eines Leerzeichens führt von B nach B (das Zeichen wird *nicht* ausgegeben).Das sollte es doch schon tun, oder?
-
Du meinst so:
-
Wenn man das in Code umsetzt, dann würde es wohl eher so wie automatos Code aussehen, also in Form einer State Machine, anstatt eines Parsers der ne Schleife durchläuft.
Richtig?
-
So, ich habe mir jetzt folgenden Code ausgedacht und das mit der DEA am Ende doch sein gelassen. Denn bei der brauche ich ja noch eine Statevariable.
Den Code habe ich ansonsten aber noch dahingehend erweitert, daß sämtliche Tabs aus dem String entfernt werden.
Das mit den Leerzeichen, daß nur jeweils ein Leerzeichen zwischen Wörtern bestehen bleibt, bleibt gleich.Hier der Code:
/* Entfernt nachfolgende Leerzeichen und Tabs von einem String */ void strip(char s[], int len) { char ziel[len]; int i, z=0; for (i=0; i < len-1; i++) { if (s[i] == '\t') /* Tabs sollen nicht nach ziel[] kopiert werden */ { do { i++; } while (s[i] == '\t'); } if (s[i] == ' ' ) { ziel[z] = s[i]; // Es soll nur ein einziges Leerzeichen zwischen zwei Wörtern gesichert werden. z++; do { /* In dieser Schleife bleiben wir solange, * solange das Zeichen ein Tab oder Leerzeichen ist. * Diese beiden Zeichen werden nicht nach ziel[] kopiert. */ i++; } while ((s[i] == ' ') || (s[i] == '\t')); } ziel[z] = s[i]; z++; } ziel[z] = '\0'; /* Rest von String ziel wird abgeschnitten */ strcpy(s, ziel); /* Nur String s ist in der aufrufenden Funktion sichtbar, daher sichern wir das Ergebnis wieder in s. */ }
Ich weiß, der Code ist nicht der eleganste, aber er funktioniert und ich habe in selbst geschrieben.
Ansonsten gefällt mir noch der Code von "ich nix DEA" sehr, ich wollte aber etwas eigenes haben. Das anpassen an die Regel mit den Tabs wäre aber auch nicht mehr so schwierig.Zum Schluß habe ich noch eine Frage.
Gibt es ein Programm, daß die Anzahl der Vergleiche (also IF Abfragen, While Bedingungen usw.) zählt?Ansonsten habe ich mir noch überlegt, die beiden IF Abfragen in der obersten Ebene der FOR Schleife zusammenzuführen und dann innerhalb der IF Abfrage das eine Leerzeichen abzufragen, aber ich denke so brauche ich eine IF Abfrage weniger, womit der Code effizienter ist als wenn ich die TABS und Leerzeichen in einer if Abfrage zusammenführe. Außerdem müßte ich dann nicht extra aufpassen, was geschehen sollte, wenn er mit einem TAB in die erste IF Abfrage einsteigt und dann gleich darauf ein leerzeichen folgt.
Denn so etwas führt nur zu Komplikationen mit dem Leerzeichen:... // ab For Schleife if (s[i] == ' ') || (s[i] == '\t')) { if (i] == ' ') { ziel[z] = s[i]; // Es soll nur ein einziges Leerzeichen zwischen zwei Wörtern gesichert werden. z++; } do { /* In dieser Schleife bleiben wir solange, * solange das Zeichen ein Tab oder Leerzeichen ist. * Diese beiden Zeichen werden nicht nach ziel[] kopiert. */ i++; } while ((s[i] == ' ') || (s[i] == '\t')); }
Wenn er da nämlich mit einem TAB einsteigt, dann wird das Leerzeichen nicht gesichert und jedesmal in der While Schleife nach einem Leerzeichen abzufragen ist auch keine Lösung, denn dann hat man ja wieder doppelte Leerzeichen die nicht gesichert werden sollen.
So gesehen ist obige Lösung besser, zumal sie auch funktioniert.BTW, ist der Code gut kommentiert oder sind die Kommentare zu lang?
Was könnte man da besser machen? Sammle hier noch Erfahrung.
-
DEA zu C schrieb:
Ansonsten gefällt mir noch der Code von "ich nix DEA" sehr...
also mir auch
-
_-- schrieb:
DEA zu C schrieb:
Ansonsten gefällt mir noch der Code von "ich nix DEA" sehr...
also mir auch
Ist das dein eigener?
Von deinem Anmeldedatum her könnte das zutreffen.
-
Einfügen schrieb:
Ist das dein eigener?
du solltest dir mal lieber ne mütze schlaf gönnen statt hier die anmeldedaten von iwelchen leuten zu studieren