switch + goto (bzw. utf8)
-
ich hasse ja eigtl so nen bit-gefrickel in meinem quellcode...^^
aber die idee hier
tmp = tmp & (0xef>>length);
ist klasse - danke! : >die schleife am ende würdest du lassen?!
oder durch nen switch ersetzen?
oder was ganz anderes?bb
-
unskilled schrieb:
ich hasse ja eigtl so nen bit-gefrickel in meinem quellcode...^^
aber die idee hier
tmp = tmp & (0xef>>length);
ist klasse - danke! : >die schleife am ende würdest du lassen?!
oder durch nen switch ersetzen?
oder was ganz anderes?bb
ja und nein.
ich hab mal ganz neu angesetzt und die fehlerprüfing rausgemacht.
(bitte nicht erschrecken!)template <typename InputIterator> static ucs4 get_ucs4_from_utf8(InputIterator &iter, InputIterator end) { ucs4 result=*iter++; if(result>128) return result; maske<<=1; result=(result<<6)|(*iter++&0x5f); if(result&maske) return result&...; maske<<=1; result=(result<<6)|(*iter++&0x5f); if(result&maske) return result&...; maske<<=1; result=(result<<6)|(*iter++&0x5f); return result&maske; }Das sieht danach aus, als könnte man ne schleife draus machen. und dann wieder mit der fehlerprüfung rein.
und zur größten not könnte man die masken so schreibenconst ucs4 B32_00000000_00000000_00000000_00001111=0x0000000f; const unsigned char B8_011111111=127;oder vielleicht leckerer keine schleife aber immer
if(iter==end) goto fehlerum den throw-code nur einmal zu haben. klingt schnell und nicht zu kompliziert. dann ich nicht mehr das doofe maske<<=1.
-
unskilled schrieb:
while ist auch komplett sinnlos, oder?
Ich sehe ich habe es mit einem Liebhaber des "switch" Konstrukts zu tun. "switch" ist vorallem in C sinnvoll, da es dort häufig notwendig ist, Integer als Typid zu benutzen, und manuell Dispatching nachbauen muß. Das entfällt in sauberem C++ komplett. Es bleiben wenige Fälle übrig in denen es sinnvoll ist, in C++ switch zu verwenden. Genauso wenig kann man auf "goto" immer verzichten, das Verlassen mehrfach verschachtelter schleifen ist sonst zu umständlich. Aber das dürfte eine der wenigen sinnvollen Anwendungsfälle sein.
Im konkreten Fall ist switch definitiv nicht sinnvoll. Die vielen "goto"s sind mehr als deutlich ein Hinweis auf schlechtes Design.
P.S. Wenn man schon ein Schleifenkonstrukt abschaffen will, weil es nicht orthogonal zu anderen Sprachkonstrukten ist, dann nimmt man besser die "for"-Schleife: siehe Oberon.
-
@volkard - uff, darüber schlaf ich erst mal ne nacht
danke 
bb
-
Ich hab deinen Quellcode mal ein wenig vergewaltigt:
template <typename InputIterator> static ucs4 get_ucs4_from_utf8(InputIterator &iter, InputIterator end) { ucs4 result = ucs4(*iter++); if(result < 128) return result; //standard ascii character if(!(result & 64)) goto error; //10xx xxxx if(iter==end) goto error; ucs mask = 16; //0001 0000 result = (result << 6) | (*iter++ & 0x3F); //... 0011 1111 if(result & (mask <<= 7)) return result; if(iter==end) goto error result = (result << 6) | (*iter++ & 0x5F); if(result & (mask <<= 7)) return result; if(iter==end) goto error result = (result << 6) | (*iter++ & 0x5F); if(result & (mask <<= 7)) return result; error: throw std::runtime_error("wrong utf8 encoding"); }zumindest compiliert es - könnte sein, dass es auch noch funktioniert ;o)
übrigens: ich hatte im eingangspost auch gefragt, inwiefern man bei der namensgebung der labels aufpassen muss - ich hab noch keine antwort darauf gesehen(ich hoffe, ich hab sie nicht überlesen^^)
bb
-
Hm... es gelten erst mal die üblichen Benennungsregeln für Bezeichner. Der ist auch nur in der Funktion sichtbar, nirgendwo sonst, das macht also keine Probleme.
-
Ad aCTa schrieb:
Der ist auch nur in der Funktion sichtbar, nirgendwo sonst, das macht also keine Probleme.
Gut - das wusste ich nämlich nicht... Danke
-
Dieses "goto error" kann aber die Fehlersucher erheblich erschweren.
Begründung: Im Stacktrace erscheint die Stelle an der der throw ausgelöst wurde, in dem Beispielfall immer das Ende der Funktion. Man könnte nicht unterscheiden an welcher der vier Stellen denn der Fehler aufgetreten ist.
Statt dessen würde ich das z.B. mit einer kleinen Hilfsfunktion lösen:
inline void Check(bool bedingung, char message) { if( !bedingung ) throw std::runtime_error(message); } template <typename InputIterator> static ucs4 get_ucs4_from_utf8(InputIterator &iter, InputIterator end) { ucs4 result = ucs4(*iter++); if(result < 128) return result; //standard ascii character Check( result & 64, "wrong utf8 encoding"); Check( iter!=end, "wrong utf8 encoding"); ucs mask = 16; //0001 0000 result = (result << 6) | (*iter++ & 0x3F); //... 0011 1111 if(result & (mask <<= 7)) return result; Check( iter!=end, "wrong utf8 encoding"); result = (result << 6) | (*iter++ & 0x5F); if(result & (mask <<= 7)) return result; Check( iter!=end, "wrong utf8 encoding"); result = (result << 6) | (*iter++ & 0x5F); Check(result & (mask <<= 7), "wrong utf8 encoding"); return result; }Jetzt erscheint im Stacktrace immer die Stelle an der der Fehler auch aufgetreten ist. UNd ganz ohne goto...
-
mist, da wollte ich einmal goto haben und schon wird es mir ausgeredet.
-
ok - da hatet ich zwar auch drüber nachgedacht, dachte mir dann aber, dass es mal völlig egal ist, wo genau der fehler auftritt - das einzig wichtige war für mich halt, dass es eine nicht standard-utf8 codierung war...
bb