Mathias Brodala: (C) Überschüssiges Leerzeichen

Beitrag lesen

Hallo Martin.

[…] Scheint so, als müsste man zur Ermittlung der Stringlänge in Zeichen, nicht Bytes, den String von Anfang bis Ende durchmarschieren, die Schritte mitzählen, und den Index dabei immer um das Ergebnis von mblen(s[i]) weitersetzen. Die Anzahl der Schritte, nicht der Index, ist dann die Stringlänge.

Nicht ganz. Was ist, wenn in Mitten normaler Zeichen ein fehlerhaft kodiertes Zeichen auftritt? Ich habe mich hier entschieden, dieses dennoch bei der Ermittlung der Gesamtlänge zu berücksichtigen, weshalb meine etwas umständlichere Lösung nun wie folgt aussieht:

int mstrlen(const char*);  
int mstrlen(const char *s) {  
  
  int i, k, l = 0, t;  
  
  for (i = 0; s[i] != '\0'; ++i) {  
  
    t = mblen(&s[i], MB_CUR_MAX);  
  
    // Bei ungültigem Byte Länge nicht erhöhen  
    if (t > -1) {  
  
      l += t;  
    }  
  
    // Bei Auftreten eines Multibyte-Zeichens  
    if (t > 1) {  
  
      // Nachfolgende Bytes durchlaufen  
      for (k = 1; k < t; ++k) {  
  
        /* Nachfolgende unvollständige Bytes gehören  
           zum Multibyte-Zeichen */  
        if (mblen(&s[i + k], MB_CUR_MAX) == -1) {  
  
          --l;  
        }  
      }  
    }  
  }  
  
  return l;  
}

(Ich hätte hier im Übrigen nie gedacht, dass mir einmal ein Programmablaufplan Schwächen im Algorithmus offenbart.)

Beispielhaft angewandt:

int main(void) {  
  
  char s[] = "Oberfläche←?";  
  setlocale(LC_CTYPE, "");  
  
  printf("s = %s\n", s);  
  printf("\nstrlen: %d, mstrlen: %d\n", strlen(s), mstrlen(s));  
  
  return EXIT_SUCCESS;  
}

$ ./test
s = Oberfläche←𝄞

strlen: 18, mstrlen: 12

(𝄞 soll laut Wikipedia ein Notenschlüssel sein und war das einzige UTF-8-kodierte Zeichen von 4 Byte Länge, was ich auftreiben konnte.)

Was hältst du von meiner Lösung?

Einen schönen Montag noch.

Gruß, Mathias

--
sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
debian/rules