Problem mit Überprüfung auf Umlaute

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Hallo Leute,

ich habe noch ein einziges kleines Problem mit meinem Programm.
Und zwar:
Ich überprüfe einen eingegebenen Text auf ungültige Zeichen etc. Allerdings sind in meiner Überprüfung bisher keine Umlaute gültig. Daher habe ich eine Liste

Code: Alles auswählen

Umlaute=['Ä','ä','Ü','ü','Ö','ö']
erstellt sowie eine Zeichenliste...
Hier mal der Teil der Abfrage...

Code: Alles auswählen

word=wort_eingabe.get()
        for i in range(0,length_w):
            if not(word[i]>='a' and word[i]<='z'):
                if not(word[i]>='A' and word[i]<='Z'):
                    if word[i] != ' ':
                        if word[i] not in Zeichen:
                            if word[i] not in Umlaute:
                                raise
        else:
            WORT=word
            wort_eingabe.config(state=DISABLED)
    except:
        showerror('Fehler!!!',u'Sie dürfen keine Sonderzeichen außer den folgenden eingeben!\n{     , ; . : ? ! " & / ( )     }')
        WORT=''
        wort_eingabe.delete(0,END)
Die Variable "length_w" ist hier die Länge des eingegebenen String. So wie es jetzt ist, sind Umlaute angeblich ungültig, d.h. er springt zu except.
Bitte nicht meckern, weil der Teil mit den if's wahrscheinlich schöner gehen würde. Es geht über diesen Teil alles außer die Umlaute; sobald ich diese Liste mit zur Prüfung einbeziehe und einen Umlaut eingebe, erscheint die Fehlermeldung.
Wäre schön, wenn mir jemand helfen könnte.

MFG evil4president
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Evil4President hat geschrieben:Wäre schön, wenn mir jemand helfen könnte.
Nimm reguläre Ausdrücke. Den Code verstehst du doch selbst in einer Woche nicht mehr.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
OldBoy
User
Beiträge: 41
Registriert: Samstag 12. Januar 2008, 20:39

Keep it simple, es geht auch ohne regex:

Code: Alles auswählen

import string

valid = set(string.ascii_letters + '������')

for c in word:
    if c in valid:
        print c, 'is valid'
    else:
        print c, 'is invalid'
Gruss

OldBoy
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Warum hast du set benutzt? Es würde reichen, wenn es ein tuple ist oder sogar nur ein string...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Habs jetzt mal versucht mit der ASCII-Liste....
Entweder verknüpf ich dauernd meine ASCII Liste falsch mit de Umlauten, oder ich mach sonstwas falsch.

Code: Alles auswählen

valid = [string.ascii_letters]  #+Umlaute + 'Ü' + 'ü' + 'Ä' + 'ä' + 'Ö' + 'ö'#
for i in word:
            #if not(word[i]>='a' and word[i]<='z'):
                #if not(word[i]>='A' and word[i]<='Z'):
                    #if word[i] != ' ':
                        #if word[i] not in Zeichen:
                            #if word[i] not in Umlaute:
                                #raise
                            #raise
            if i in valid:
                WORT=word
                wort_eingabe.config(state=DISABLED)
            else:
                raise
Habe jetzt die valid-Liste schon auf allen mir denkbaren Weisen zusammengesetzt. Jedoch werden die Umlaute nie angenommen...
Rein mit der ASCII-Liste gehts auch nicht. Kann das eventuell an dem Entry-Widget liegen?
Ich habe schon versucht zu der Gültigkeitsliste die Umlaute einzeln zu addieren, die Liste Umlaute zu addieren. Alles ohne Erfolg.
Ich versteh das einfach nicht...
OldBoy
User
Beiträge: 41
Registriert: Samstag 12. Januar 2008, 20:39

1. Umlaute im Programmtext

werden Umlaute im Programmtext verwendet muss am Programmanfang das Encoding einstellen (je nach Rechner z.B. 'cp1252', 'mac-roman', 'iso8859-1' etc.)

Code: Alles auswählen

# -*- coding: <encoding-name> -*-

umlaut = 'äöüÄÖÜ'
2. warum verwende ich set

geht (in diesem Fall etwas) schneller. Das Suchen in einem String oder einer Liste dauert länger wenn String/Liste sehr lang sind. Das Suchen in einem Set ist immer gleich schnell

3.

ich will überprüfen, ob ein einzelner Buchstabe gültig ist:

if c in valid: ...

möglich:

valid = set(string.ascii_letters) ist ein Set von einzelnen Buchstaben
valid = list(string.ascii_letters) ist eine Liste von einzelnen Buchstaben
valid = string.ascii_letters ist ein einzelner String, in dem ich aber auch problemlos suchen kann

nicht möglich:

valid = [string.ascii_letters] ist eine Liste mit nur einem Element, und dieses ist derString aller Buchstaben.

HTH

OldBoy
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

So wird das nicht funktionieren, da bei dir valid eine liste ist. Nimm die Klammern weg, dann wird auch innerhalb string.ascii-letters gesucht 8also das was du eigentlich vor hast).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

So, habe das mit der Liste schonmal behoben, vielen Dank für die Erklärung, wieso es dort nicht ging, habe das nicht berücksichtigt.
Meine valid-Liste sieht jetzt so aus (Das coding war übrigens schon drin).

Code: Alles auswählen

#-*- coding: cp1252 -*-
import string
valid = string.ascii_letters + 'ÜüÄäÖö'
Allerdings werden immernoch keine Umlaute akzeptiert.
Ich bin ratlos... Desweiteren hätte ich noch ein kleines weiteres Problem, was allerdings evtl behoben wird wenn die Umlaute akzeptiert werden...
Nachdem meine Fehlermeldung über die errorbox angezeigt wird, erscheint in der IDLE immer der Traceback, dass der Buchstabe (in meinem Fall speziell der eingegebene Umlaut) nicht im vorgegebenen Wertebereichs des ASCII Codes liegt...

Code: Alles auswählen

for a in range(0,length_w):
        if 90<(ord(WORT[a])+zahl)<97:
Allerdings habe ich noch einen "elif" ergänzt, der abfrägt, ob der Buchstabe in der Liste Umlaute liegt... Dann tritt eine andere Operation ein... Jedoch verbleibt der Ablauf immer im angegebenen if...
Allerdings wäre mir momentan wichtiger, dass ich die Umlaute überhaupt gültig einlesen kann.

MFG
BlackJack

Wenn Umlaute im Spiel sind, sollte man IMHO auf Unicode setzen. Dieses Byteketten-Gefrickel mit `str()` fällt spätestens dann auf die Nase, wenn man Kodierungen verarbeiten will, bei denen nicht mehr ein Zeichen == ein Byte gilt.
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Ich weiß, ich stelle mich wahrscheinlich gerade etwas dumm an, aber wie kann man die gesamten Strings auf Unicodezeichen umstellen? wenn es das ist, was du meinst...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Evil4President hat geschrieben:Ich weiß, ich stelle mich wahrscheinlich gerade etwas dumm an, aber wie kann man die gesamten Strings auf Unicodezeichen umstellen?
Vor alle Strungs ein ``u`` setzen. Etwa ``u"Hallo Welt"``.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Evil4President hat geschrieben:Allerdings werden immernoch keine Umlaute akzeptiert.
Allerdings wäre mir momentan wichtiger, dass ich die Umlaute überhaupt gültig einlesen kann.
Aus deinem Code oben kann man schließen, dass du eine GUI mit Tkinter verwendest. Zeig doch mal den Codeausschnitt und den Traceback zu den Umlauten, dann kann dir konkreter geholfen werden.

Ohne GUI funktioniert es nämlich problemlos, z.B. so:

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-
import string

def neueszeichen(ch):
    # mach irgendwas mit dem Zeichen
    return "#"

zeichenvorrat = string.ascii_letters+"ÄÖÜäöü"
textalt = raw_input("Gib den Text ein: ")
textneu = ""
for ch in textalt:
    if ch in zeichenvorrat:
        ch = neueszeichen(ch)
    textneu += ch
print textneu
Ausgabe:

Code: Alles auswählen

Gib den Text ein: Bist du 17? Nöö, älter!
#### ## 17? ###, #####!
BlackJack

@Pütone: Funktioniert aber auch nur wenn Skript-Kodierung und die Kodierung der Eingabe übereinstimmen und wenn es sich um eine Kodierung handelt, bei der jedes Zeichen durch ein Byte dargestellt wird.
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Wie ich die Ausgabe als Unicode setze wusste ich, ich hab das so verstanden dass bem Auslesen des Entry-Feldes direkt als Unicode ausgelesen werden soll. Das weiß ich nicht...
Habe jetzt mal meine try und excepts rausgemacht. Vorher bekam ich nie einen Traceback, da der Fehler über mein except abgefangen wurde...
Muss ich mir mal merken, dass ich dann am besten die excepts mal wegmache, um das genauer aufzuschlüsseln.
Hier der Codeausschnitt und der Traceback:

Code: Alles auswählen

valid = string.ascii_letters + 'ÜüÄäÖö'
for i in word:
        if i in valid:
            WORT=word
            wort_eingabe.config(state=DISABLED)
        else:
            print 'Fehler'

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python25\lib\lib-tk\Tkinter.py", line 1403, in __call__
    return self.func(*args)
  File "C:/Users/Lukas/Schule/Informatik/20.05.2008/Hausaufgabe/Tests/Hausaufgabe ohne Zerlegung in Definitionen3.py", line 75, in chiffrieren
    if i in valid:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xdc in position 52: ordinal not in range(128)
Soweit ich das verstanden habe, kann er den eingegebenen Umlaut im Entry-Feld nicht verarbeiten und stößt deshalb auf diesen Fehler. Ich schätze man müsste wirklich einstellen, dass er den String direkt als Unicode einliest. Aber korrigiert mich, falls ich falsch liege.
Wäre gut, wenn mir jemand einen Tipp geben könnte, wie sich der Fehler beheben lässt.

MFG
BlackJack

Es ist genau umgekehrt. Der Inhalt vom `Entry` kommt als Unicode-Objekt wenn ein Umlaut enthalten ist und `valid` macht Probleme, weil das *kein* Unicode ist.

Code: Alles auswählen

In [249]: valid = 'abc...aöü'

In [250]: u'a' in valid
---------------------------------------------------------------------------
<type 'exceptions.UnicodeDecodeError'>    Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.UnicodeDecodeError'>: 'ascii' codec can't decode byte 0xc3 in position 7: ordinal not in range(128)
Wenn man Zeichenketten und Unicode-Objekte mischt, dann versucht Python die Zeichenkette in Unicode um zu wandeln und nimmt dabei ASCII als Kodierung an. Was zu der Ausnahme da oben führt, wenn die Zeichenkette etwas enthält, was nicht im ASCII-Zeichensatz enthalten ist.
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Achso. Vielen Dank schonmal an alle. Habe jetzt die valid-Liste als Unicode String erstellt, jetzt kommt auch kein Fehler mehr wenn ich Umlaute eingebe. Allerdings kommt jetzt ein Fehler wenn ich Sonderzeichen eingebe...
Hier mal meine Liste:

Code: Alles auswählen

valid = u'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz' + u'ÜüÄäÖö' + u',;.:?"&/()§'

Allerdings habe ich auch noch ein Problem innerhalb eines if's.
So sieht mein if-Teil aus:

Code: Alles auswählen

for a in range(0,length_w):
        if 90<(ord(WORT[a])+zahl)<97:
            number=(ord(WORT[a])+zahl)-90
            geheim +=chr(64+number)
        elif (ord(WORT[a])+zahl)>122 and WORT[a] not in Umlaute:
            number=(ord(WORT[a])+zahl)-122
            geheim += chr((96+number))
        elif WORT[a]==' ':
            geheim += ' '
        elif WORT[a] in Zeichen:
            geheim += WORT[a]
        elif WORT[a] in Umlaute:
            geheim += WORT[a]
        else:
            geheim += chr(ord(WORT[a])+zahl)
Entschuldigt schonmal, dass es ein wenig umständlich gemachht ist, aber die Verbesserung mit slices füge ich bald noch ein... Würde das ganze aber gerne so mal lauffähig haben. Wenn ich jetzt einen Umlaut eingebe, dann müsste doch der teil "elif WORT[a] in Umlaute" eintreten, d.h. er sollte den Umlaut einfach stehen lassen, da ansonsten abstruse Zeichen herauskommen. Wieso verschiebt er trotzdem das Zeichen innerhalb der ASCII Tabelle... Die Sache, dass der Wert größer als 122 ist, wird doch ausgeschlossen, wenn das Zeichen ein Umlaut wäre... Die Bedingung mit größer 122 sollte nur eintreten, wenn man beispielsweise das "Z" verschiebt...
Wäre schön, wenn mir hierbei auch jemand helfen könnte...
Und entschuldigt, wenn ich mich etwas dumm anstelle bei solchen Sachen ;-)
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Ok, das Problem mit den Sonderzeichen habe ich gerade selbst gelöst. Hatte oben in der valid-Liste übersehen, dass mir noch ein Leerzeichen und das Ausrufezeichen fehlten.... :-)

Aber das Problem mit dem Vershcieben der Umlaute besteht weiterhin...
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Evil4President hat geschrieben:Aber das Problem mit dem Vershcieben der Umlaute besteht weiterhin...
Ich verstehe allmählich nicht, wo dein Problem noch ist. Es wurde doch eigentlich alles mehrmals und von verschiedenen Seiten durchgekaut.

Ist es nicht das, was du willst:

Code: Alles auswählen

import string

zeichenvorrat = string.ascii_letters+"ÄÖÜäöü"
delta = 5

def kodiere(ch):
    try:
        return zeichenvorrat[(zeichenvorrat.index(ch)+delta) % len(zeichenvorrat)]
    except ValueError:
        return ch

textalt = "Bist du 17? Nö, älter!"
textneu = ""
for ch in textalt:
    textneu += kodiere(ch)
print textneu
Ausgabe:

Code: Alles auswählen

Gnxy iz 17? Sd, cqyjw!
Der ganze Weg über die elifs und die ASCII-Codenummern ist doch überflüssig.
Evil4President
User
Beiträge: 83
Registriert: Dienstag 15. Januar 2008, 15:39
Kontaktdaten:

Im Prinzip is das schon so wie ich es will, nur so habe ich es ja auch, nur in abgewandelter Form... Es wird ja auch alles korrekt verschlüsselt, nur die Umlaute werden zu sehr seltsamen Zeichen, da sie in einem sehr unregelmäßig verteiltren Zahlenbereich der ASCII Tabelle liegen. Ich wollte oben in meiner for-Schleife testen, ob der i-te Buchstabe des Wortes in meiner Liste Umlaute drin ist. Falls er das ist, soll der Umlaut beim verschlüsselten Text einfach stehen bleiben; rundherum wird alles verschlüsselt. Allerdings scheint das "elif" in dem geprüft wird, ob der Buchstabe in Umlaute enthalten ist, nicht korrekt abzulaufen... Ich wollte fragen wieso.

Ich persönlich habe nur zwei Erklärungen, allerdings keine Ahnung wie ich darüber auf eine Lösung komme. Zur Erläuterung:

Die Zahlenwerte der Umlaute liegen alle über 122, d.h. er springt im Programmablauf in das elif in dem gefragt wird, ob der Zahlenwert des Buchstaben + die Zahl um die verschoben wird größer ist als 122. Diese Bedingung habe ich jedoch mit der Bedingung verknüpft, dass der Buchstabe nicht in meiner Liste Umlaute ist. Also sollte er doch folglich, wenn ich einen Umlaut eingebe nichtmehr in diesem elif weiterarbeiten, sondern zu dem springe, in dem abgefangen wird, wenn der Buchstabe ein Umlaut ist.
Das Problem, dass ich Umlaute garnicht erst weiterverarbeien kann, ist ja bereits dank eurer Hilfe gelöst ;-)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ich verstehe nicht, was du willst.
Was ist denn an meinem Beispielcode so, dass du es nicht willst?
Warum hängst du so an den ASCII-Codes und willst die Verschiebung unbedingt auf die ASCII-Code (also die Codenummern) beziehen?
Klar, die Umlaute hängen da irgendwo >127 quer drin. Also bekommst du natürlich irgendwelche Sonderzeichen, wenn du zum ASCII-Code einen Zahlenwert addierst und das entsprechende Zeichen nimmst.

Auf welche Zeichen möchtest du die Umlaute denn abbilden?


:?:
Antworten