Vorschlag für eine printf-Erweiterung besonders geeignet für LabVIEW-Funktion „In String formatieren“ (beißt sich nicht mit den in LabVIEW 2011 bereits eingebauten Erweiterungen) Zweck: Sprachlich korrekte Darstellung von Singular- und Pluralformen Abdeckung: Löst das Problem (fast?) aller Sprachen (englisch, deutsch, französisch, spanisch, niederländisch, italienisch, dänisch, schwedisch, norwegisch, portugiesisch, arabisch; russisch, tschechisch, slowakisch, polnisch; Deren Fallzuweisung ist leider verschieden!!! Kein Problem bisher: chinesisch, japanisch, thailändisch, koreanisch; ungarisch, türkisch? (kein Plural nach Zahlen) Unklar: Baskisch, Walisisch, Rätoromanisch, Griechisch, Hebräisch, Persisch, Indische Sprachen, … * Die Zahl kommt stets vorher (Abweichung möglich, siehe unten) * Die Wörter dürfen keine ')' oder '/' enthalten, sollten nicht '%' und '(' enthalten (oder ist Verschachtelung von '%' erlaubt? Gibt mehr Freiheit …) * Runde Klammern ermöglichen gute, „lesbare“ Rückwärtskompatibilität! Kommt auf die printf-Implementation an … Klappt leider nicht in LabVIEW! Formatstring Ausgabe Ausgabe eines alten printf() ──────────────────────────────────────────────────────────────────────────── Ratte%(n) Ratte Ratten Ratte(n) file%(s) file files file(s) Vorschlag in Beispielen englisch: 1 ≠1 unaware printf (mostly) ─────────────────────────────────────────────────────────────── house%(s) house houses house(s) %(is/are) is are (is/are) %(mouse/mice) mouse mice (mouse/mice) cact%(us/i) cactus cacti cact(us/i) deutsch: %(Haus/Häuser) Haus Häuser (Haus/Häuser) Fenster Fenster Fenster Ratte%(n) Ratte Ratten Ratte(n) Stift%(e) Stift Stifte Stift(e) Elko%(s) Elko Elkos Elko(s) Kerb%(tal/täler) Kerbtal Kerbtäler Kerb(tal/täler) arabisch (Problem: Dual, wird ohne Zahl dargestellt): من%3(زل/زلين/ازل) منزل منزلين منازل russisch: дом%6(/а/ов) дом дома домов дом(/а/ов) книг%6(а/и/) книга книги книг книг(а/и/) %6(год|года|лет) год года лет (год|года|лет) Die Mehrzahl derzeitiger printf-Implementationen gibt sinnvollerweise den ganzen Inhalt aus. Der Vorschlag benötigt ein Minimum neuer Zeichen und ist gut menschenlesbar. Er deckt die häufigeren Sprachen besser ab als seltenere (KISS-Prinzip). Der Parser kann einfach gehalten werden und benötigt keine Locale-Information. Er erledigt Standardfälle mit wenig Extra-Zeichen und deckt dabei alle bekannten Sonderfälle ab. Er benötigt - außer zum Festlegen des Falls aus der Zahl – keine sprachliche Kenntnis. Der Parser kann vollständig sequenziell arbeiten. Mehrere Wörter können getrennt oder zusammen aufgeteilt werden: „%d Datei%(en) %(ist/sind) geöffnet.“ (bevorzugt) „%d %(Datei ist/Dateien sind) geöffnet.“ (ungünstig) Der Feldbreite-Bezeichner kodiert: 0 - n!=1 (Normalfall) 1 - n>1 (französisch, brasilianisch) 2 - n%10==1&&n%100!=11?0:n!=0?1:2 (litauisch) 3 - n==1?0:n==2?1:2 (irisch, arabisch) 4 - n==1?0:(n==0||(n%100>0&&n%100<20))?1:2; (rumänisch) 5 - n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2; (litauisch) 6 - n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2; (russisch, koratisch, serbisch, ukrainisch) 7 - n==1?0:n>=2&&n<=4?1:2; (tschechisch, slowakisch) 8 - n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2; (polnisch) 9 - n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3; (slowenisch) Die angegebenen Ausdrücke liefern Zahlen von 0 bis 3 (zumeist nur 0 oder 1) entsprechend den anzugebenden Alternativtexten. Die Alternativtexte sind – für gute lesbare Rückwärtskompatibilität – mit '/' abgetrennt. Der Präzisions-Bezeichner gilt als Überschreiber für die vorhergehende Zahl. Beispiel (n>0): „%.*(Ein Sample wurde/Einige Samples wurden) nicht erfasst!“ Parser-Pseudokode: - Findet '(' (keine Zahl verfügbar: Fehler!) - Entscheidung des Falles anhand Betrag(Zahl) - Parse bis nach n-ten Auftreten von '/', halte an bei ')' oder '\0' - Gib Zeichen aus bis '/' oder ')' oder '\0' also sehr simpel und vollständig sequenziell; kein Puffer nötig (gut für Mikrocontroller) Der in printf enthaltene Zahlenparser (für "%d" usw.) sollte den Betrag der Zahl in einem Speicherplatz hinterlassen. Ist der Speicherplatz zu klein (etwa 16 bit), dann ist eine Modulo-1000-Ausgabe vorzusehen. (Dies führt bei printf("%d %(Nacht/Nächte)",1001) zu „1001 Nacht“.) Bei Gleitkommazahlen (also "%f" u.ä.) wird 99 hinterlassen, wenn diese gebrochen ist, sonst der (ganzzahlige) Betrag. Denn alle(?) Sprachen benutzen die Pluralform für gebrochene Zahlen, etwa „1,1 Sekunden“, entsprechend printf("%f Sekunde%(n)",1.1);. Kommentare und Einwände bitte an heha@hrz.tu-chemnitz.de! heha, 111025 ------------------------------------------------------ Hier gibt es eine funktionsfähige Beispiel-Implementation: siehe "lprintf.zip". Diese setzt auf das CRT-printf() auf und siebt vorher die %()-Konstrukte heraus. Gemeinsame Quellvariablen werden noch nicht verwendet, es ist für Singular/Plural ein weiteres int-Argument zu setzen. Auch ist hier nur Deutsch / Englisch unterstützt. Diese LabVIEW-Erweiterungen sind da logischerweise nicht mit drin: Modifizierer: $ Festlegen der Reihenfolge printf("%2$s, %1$s", "Hans" "Schmidt") -> "Schmidt, Hans" ^ Exponent durch 3 teilbar; Weltzeit # Nachlaufende Nullen entfernen _ Signifikante Stellen printf("%_2f",M_PI) -> "3,1" oder "3.1" {} Einheit mit Einheitenvorsatz printf("%{g}f",0.2/*kg*/) -> "200 g" <> Zeit-Formatierung (mit %-Schachtelung) printf("%^<%.3X %x>T",dt) -> "06:00:00.000 31.12.2000" Formatierungskodes: p Gleitkommazahl mit Einheitenvorsatz printf("%_2p",12000000) -> "12M" (beißt sich mit "pointer"!) t Zeitdifferenz T Absolute Zeit b Binärzahl ; Punkt oder Komma festlegen heha, 120910