On 2012-04-05 16:51, Nils Müller <
tras...@arcor.de> wrote:
> Am 05.04.2012 16:01, schrieb Wolf Behrenhoff:
>
>> ich glaube, du musst mal ein vollständiges lauffähiges (aber kurzes!)
>> Programm hier zeigen. Ich verstehe dein Problem auch nicht ganz,
>> insbesondere nicht, was die wide_char tun soll.
>
> Das Problem, das Skript läuft innerhalb einer ncurses Umgebung. Somit ist
> das Skript weder kurz (50Kb) noch ohne ncurses lauffähig.
Kürze es auf etwas zusammen, das kurz genug ist, dass Du es hier posten
kannst. Ncurses dürften die meisten haben.
> Ich habe mal ein paar Snapshots gemacht.
>
> Hier sieht man den ganzen Text:
>
http://dl.dropbox.com/u/4616166/snap.png
>
> Hier wird einfach ab Position 10 abgeschnitten:
> $name_size_max = 10;
> $name = substr($name,0,$name_size_max);
Unter der Annahme, dass $name hier ein (UTF-8-kodierter) Byte-String und
kein Character-String ist: Hier schneidest Du nach 10 *Bytes* ab,
nicht nach 10 *Zeichen*.
Also:
e3 81 8a e3 82 82 e3 81 97 e3 82 8d e3 83 8d e3 82 bf e9 80 9f e5 a0 b1
-------- -------- -------- -------- -------- -------- -------- --------
お も し ろ ネ タ 速 報
<--------------------------->
10 Bytes
Du gibst also vom 4. Zeichen nur mehr das erste Byte aus.
Hie wandelst Du den Byte-String in einen Character-String um.
$name besteht nun aus 8 Zeichen, nicht aus 24 Bytes.
> $name_size_max = int($name_size_max / 2)+1;
$name_size_max hat nun den Wert 6.
> $name = substr($name,0,$name_size_max);
Du nimmst also die ersten 6 Zeichen von $name.
>
http://dl.dropbox.com/u/4616166/snap2.png
>
>
> Anmerkung:
> - Das "+" Zeichen am Ende der Zeichenkette setze ich damit man sieht,
> dass der Name gekürzt wurde.
>
> - Wie man auf dem Bild "Snap1" sieht, wird anstelle des chinesischen Symbols eine
> "06" ausgegeben und die Farbe des "+" Zeichens ist nicht korrekt (obwohl ich das
> "+" inklusive Farbcode erst später anfüge!).
Das liegt wahrscheinlich daran, dass Du vom 4. Zeichen nur ein Byte
ausgibst. Danach gibt ncurses den Steuerungscode für "grüne
Vordergrundfarbe" aus, und der arme Terminal-Emulator, der erwartet,
dass da jetzt die nächsten zwei Bytes von ろ kommen, verschluckt sich
daran. Um zu erklären, warum da jetzt "06" steht und nichts anderes,
müsste man sich ansehen, was ncurses und der Terminal-Emulator da genau
machen.
> - Auf dem Bild "Snap2" soll ab dem 10 Zeichen getrennt werden, aber "testお" sind
> keine 10 Zeichen.
Klar. Du schneidest ja nach 6 Zeichen ab. Es sollten also 6 Zeichen
sein, warum man nur 5 sieht, kann ich nicht erklären. Bist Du sicher,
dass der Code, den Du oben gepostet hast, der ist, den Du für diese
Screenshots verwendet hast?
Ich habe eine Grundregeln für den Umgang mit Strings in Perl:
Wenn Strings einen Text (also eine Folge von Zeichen, nicht eine
Folge von Bytes) repräsentieren, dann sind sie immer Character-Strings.
Daraus folgen ein paar abgeleitete Regeln:
1) Source-Code ist in UTF-8 geschrieben und verwendet »use utf8;«. Auf
diese Art sind String-Konstanten immer richtig.
2) Jeder Text-Input, der von außen hereinkommt, wird so früh wie möglich
dekodiert: Beim Lesen von Files mittels I/O-Layer (z.B. »open(my $fh,
'<:encoding(UTF-8)', $filename)«, beim Lesen aus einer Datenbank
mittels entsprechender Optionen (leider für jede Datenbank anders),
etc. Wenn gar nichts anderes hilft, dann ein expliziter Aufruf von
decode()).
3) Ein Zeichen ist ein Zeichen ist ein Zeichen und mich interessiert
nicht, wie das intern abgespeichert ist. length() liefert mir die
Länge in Zeichen, substr($s, 0, 10) liefert mir die ersten 10
Zeichen, m/x(..)/ die ersten zwei Zeichen nach dem x; egal, ob das
lateinische oder chinesische Zeichen sind.
[Stolperstein: Normalisierungsformen: Um die muss man sich u.U. doch
kümmern]
4) Die Umwandlung in Bytes für den Output erfolgt so spät wie möglich:
Im I/O-Layer, im Datenbank-Interface, oder notfalls mittels
explizitem Aufruf von encode() unmittelbar vor der Ausgabe.
hp
--
_ | Peter J. Holzer | Deprecating human carelessness and
|_|_) | Sysadmin WSR | ignorance has no successful track record.
| | |
h...@hjp.at |
__/ |
http://www.hjp.at/ | -- Bill Code on
as...@irtf.org