Seite 1 von 1
Fehler bei Substrings
Verfasst: Dienstag 8. Juli 2008, 17:40
von DrChAoS
Guten Abend,
Da bin ich wieder

. Ich bin gerade dabei einen kleinen Interpreter für eine selbst ausgedachte Sprache in Python zu schreiben. Aber bei der Stringverarbeitung gibt es einen Fehler. Hier erstmal der Code:
Code: Alles auswählen
#!/usr/bin/python
#-*- coding: utf-8 -*-
import sys
i=0
x=[0]*30000
lines=[0]*60000
dat = open(sys.argv[1],"r")
line = dat.readline()
k=0
while line != "":
if line[:1] != "#":
lines[k] = line
k+=1
line = dat.readline()
dat.close()
while 1:
tmp_line = lines[i]
if tmp_line[:1] == ".":
out=""
tok = tmp_line[1:].split(",")
for t in tok:
if t[:1]=="\"" and t[::-1][:1]=="\"" :
out+=t[1:-1]
elif t[:1]=="x":
out+=str(x[int(t[1:])])
else:
print "Error in Line \n%s"%(tmp_line)
exit()
i+=1
Wenn in der Übergebenen Datei (./script.py test.txt) test.txt Das hier steht:
Bekomme ich diesen Fehler:
Code: Alles auswählen
Traceback (most recent call last):
File "asms.py", line 33, in <module>
if tmp_line[:1] == ".":
TypeError: 'int' object is unsubscriptable
Normalerweise sollte der Interpreter folgende Rückgabe machen:
Ich sitze jetzt schon den ganzen Mittag an diesem (vermutlich) total simplen Fehler.
Vielen Dank schonmal im Vorraus.
MfG
Dr.ChAoS
Verfasst: Dienstag 8. Juli 2008, 18:15
von Karl
Naja, schau doch mal auf den Error. int object ist unsubscriptable.
Das heißt tmp_line wird anscheinend zu einem int-Objekt.
Klar, wenn du lines mit 60.000 * [0] initialisierst.
Nach einem durchlauf, wenn i = 1 ist, kommts zu lines[1] -> 0 -> int -> Error
Verfasst: Dienstag 8. Juli 2008, 18:21
von numerix
Was mir spontan auffällt, dass einige Dinge völlig "unpythonisch" und in diesem Falle dadurch sehr ungeschickt gelöst sind.
Es dürfte nicht schaden, wenn du mal das offizielle Tutorial (so weit du es brauchst) durcharbeitest - das wird dir einige Aha-Erlebnisse bescheren und deinen Code auf geschätzte 25% des jetzigen Codes (bei gleicher Funktionalität) zusammenschmelzen.
2 Beispiele:
a) Sieh dir mal die readlines()-Methode von Dateiobjekten an!
b) Die while-Schleife mit Zähler ist hier die ganz falsche Lösung. Du kannst direkt über alle Elemente der Liste (also in deinem Falle alle Zeilen) iterieren.
Verfasst: Dienstag 8. Juli 2008, 18:39
von DasIch
Versuch das Slicing mal zu vermeiden. Ich sehe jetzt Spontan keine Stelle an der das notwendig ist.
Wie auch immer mich würde mal die Syntax interessieren. Das x3 was soll das bewirken und worauf soll die Bedingung in Zeile 27 zutreffen? Ich hab den Code mal neugeschrieben aber dass ist die einzige Zeile deren Sinn ich auch nach einigen Experimenten nich wirklich verstanden habe.
btw. Der Interpreter wird übrigens gar keine Ausgabe machen da nirgendswo ein print vorkommt.
EDIT: Zeile 27 soll den String finden oder? Wirklich unglaublich kompliziert gelöst. Ich glaub da ist doch noch ein Tipp nötig:
Es gibt 'string'.startswith('s') und 'string.endswith('g')

Verfasst: Dienstag 8. Juli 2008, 19:16
von DrChAoS
Karl hat geschrieben:Das heißt tmp_line wird anscheinend zu einem int-Objekt.
Klar, wenn du lines mit 60.000 * [0] initialisierst.
Vielen Dank, das war im Grunde mein größter Denkfehler.
numerix hat geschrieben:a) Sieh dir mal die readlines()-Methode von Dateiobjekten an!
Danke, damit wurde der Code wirklich kürzer und einfacher.
b) Die while-Schleife mit Zähler ist hier die ganz falsche Lösung. Du kannst direkt über alle Elemente der Liste (also in deinem Falle alle Zeilen) iterieren.
Nein, das kann ich nicht machen, denn ich muss den Zähler im späteren Verlaufs des Programms ändern können und das ist so nicht möglich.
@DasIch
Meine "Sprache" basiert ein kleines bisschen auf Brainfuck. x3 heißt dass ich auf das dritte Feld des Arrays x zugreife und den Wert ausgebe.
Hier noch ne kurze Erklärung der Syntax:
Variablen können nur Integer Werte enthalten.
. gibt etwas aus. Strings und Variablen werden durch ein Komma getrennt. Bsp:
# leitet einen Kommentar ein, der übrigens nicht hinter eine Zeile stehen kann^^.
, (Noch nicht implementiert) ließt einen Integer Wert ein.
dann kommen noch weitere dinge wie + - * / etc.. und auch eine If Abfrage. außerdem soll man zwischen den Zeilen springen können (Deswegen die while Schleife mit der Laufvariable)
EDIT: Jetzt hätte ich fast den Aktuellen Source vergessen: (Für diejenigen die es interessiert)
Code: Alles auswählen
#!/usr/bin/python
#-*- coding: utf-8 -*-
import sys
x={}
for t in range(30000):
x[t]=0
lines={}
dat = open(sys.argv[1],"r")
tmp_lines = dat.readlines()
dat.close()
l=0
for k in tmp_lines:
lines[l]=k[:-1]
l+=1
i=0
while i<len(lines):
if lines[i][:1] == "#":
pass
elif lines[i][:1] == ".":
out=""
tok = lines[i][1:].split(",")
for t in tok:
if t[:1]==""" and t[::-1][:1]==""" :
out+=t[1:-1]
elif t[:1]=="x":
out+=str(x[int(t[1:])])
else:
print "Error on Line %i \n%s"%(i+1,lines[i])
exit()
print out
i+=1
Verfasst: Dienstag 8. Juli 2008, 19:34
von DasIch
Die Sprache ist interessant.
Zum Code: Was soll Zeile 21? Benutze einfach pass dann ist klar dass nichts mehr passieren soll und man hat nicht noch ein Objekt rumliegen. Benutze besser Leerzeichen vor und nach Operatoren, das macht den Code besser lesbar und sieht auch besser aus.
Statt einen String umzudrehen kannst du gleich auf das letzte Zeichen mit [:-i] zugreifen.
Verfasst: Dienstag 8. Juli 2008, 19:43
von Karl
Ich hab ja auch letztens einen Brainfuckinterpreter im Showcase gepostet, der aber anscheinend irgendeinen Bug hat.
Ich erinner mich noch gut daran, wie ich aus Gewohnheit eine for-Schleife benutzt habe und dann mit dem Iterator bei einer Schleife zurückspringen wollte

Mit while hat's dann natürlich geklappt

Du hast aber bis jetzt nur die unwichtigen Details deiner kleinen an Brainfuck angelehnten Sprache verraten.
Das wichtigste ist doch, wie du die Schleife realisieren willst.
Dass du auch vorhast, Zellen wie in Brainfuck zu benutzen, schließe ich aus x=[0]*30000, auch wenn ich mir dein "gewurstel" da unten noch nicht angeschaut hab. Du könntest ja wenigstens ein wenig öfter die Space-Taste benutzen

Verfasst: Dienstag 8. Juli 2008, 20:09
von numerix
DrChAoS hat geschrieben:
numerix hat geschrieben:b) Die while-Schleife mit Zähler ist hier die ganz falsche Lösung. Du kannst direkt über alle Elemente der Liste (also in deinem Falle alle Zeilen) iterieren.
Nein, das kann ich nicht machen, denn ich muss den Zähler im späteren Verlaufs des Programms ändern können und das ist so nicht möglich.
In welchem "späteren Verlauf"?
Innerhalb der Schleife jedenfalls nicht. Wenn du direkt über die Elemente der Liste (also über die Zeilen des "Quelltextes") iterierst, brauchst du keine Zählvariable. Die einzige Stelle, wo du die Zeilennummer verwendest, ist die Ausgabe der Zeilennummer bei einer Fehlermeldung.
Kennst du so etwas:
Code: Alles auswählen
datei = open(sys.argv[1],"r")
zeilen = datei.readlines()
datei.close()
for zeile in zeilen:
if not zeile.startswith("#"):
print "Interpretiere %s" %zeile
Und falls du die Zeilennummer für die Fehlermeldung brauchst:
Code: Alles auswählen
for nr,zeile in enumerate(zeilen):
if not zeile.startswith("#"):
print "[%i] Interpretiere %s" %(nr,zeile)
Sowas findet man im Tutorial ...

Verfasst: Dienstag 8. Juli 2008, 20:12
von DrChAoS
Ich werde das so machen wie man es früher in C gemacht hat. Und zwar mit einer Art GOTO. Dazu Werde ich am Anfang die Zeilennummern aller Sprungstellen in ein dict schreiben um später Mit der Laufvariable einfach an die entsprechende Stelle Springen kann.
Und das in Kombination mit einer if Anweisung die im Falle von false die nächste Zeile überspringt macht es möglich Kopfgesteuerte und Fußgesteuerte Schleifen zu programmieren.
Hier ein kleines Beispiel:
Wenn x3 kleiner x2 ist, wird nach :sprung gesprungen. Andernfalls wird der Text "false"
ausgegeben.
Zusätzlich zu ">" will ich noch "<" einbauen. Denn mit diesen zwei Operatoren kann man alles überprüfen.
So ich hoffe dass das so verständlich war

MfG
Dr.ChAoS
//EDIT:
@numerix: Aber Wie will ich dann Schleifen realisieren? Ich springe ja durch das Programm in dem ich die Laufvariable i verändere.
Verfasst: Dienstag 8. Juli 2008, 20:46
von numerix
DrChAoS hat geschrieben:@numerix: Aber Wie will ich dann Schleifen realisieren? Ich springe ja durch das Programm in dem ich die Laufvariable i verändere.
Alles klar; diesen kurzen Hinweis weiter oben hatte ich überlesen.
Ich war davon ausgegangen, dass es ein lineares Programm ist und mich nur auf das bezogen, was der Code bisher macht.
Für Sprünge brauchst du natürlich einen Index.