Frage

Aus Gründen vollständig mit Ich bin nicht einverstanden, aber „The Powers (von Anti-Usability) Das Be“ zu verordnen trotz meiner Einwände weiter, ich habe eine Sortierroutine, die Grund strcmp tut () mit seinem Namen zu sortieren vergleicht. Es funktioniert großartig; es ist schwer, dass man etwas falsch zu laufen. Doch in der 11. Stunde, ist schon entschieden, dass Einträge, die mit einer Zahl beginnen sollten NACH Einträgen kommen, die mit einem Buchstaben beginnen, im Gegensatz zu der ASCII-Bestellung. Sie zitieren der EBCDIC Standard Zahlen haben Buchstaben hinter so die vorherige Annahme nicht eine universelle Wahrheit ist, und ich habe keine Kraft, dieses Argument zu gewinnen ... aber ich schweife ab.

Darin liegt mein Problem. Ich habe alle entsprechenden Referenzen ersetzt mit einem neuen Funktionsaufruf nonstd_strcmp strcmp, und jetzt müssen die Änderungen implementieren, um die Sortier Änderung zu erreichen. Ich habe eine FreeBSD-Quelle als meine Basis verwendet: http: //freebsd.active-venture.com/FreeBSD-srctree/newsrc/libkern/strncmp.c.html

 if (n == 0)
  return (0);
 do {
  if (*s1 != *s2++)
   return (*(const unsigned char *)s1 -
    *(const unsigned char *)(s2 - 1));
  if (*s1++ == 0)
   break;
 } while (--n != 0);
 return (0);

Ich glaube, ich könnte einige Zeit weg nehmen müssen, um wirklich darüber nachdenken, wie es getan werden sollte, aber ich bin sicher, ich bin nicht der einzige, der das Gehirn-Leblosigkeit von just-vor-Release spec Änderungen erfahren hat.

War es hilfreich?

Lösung

In diesem speziellen Fall mit nur Großbuchstaben (wie in den Kommentaren vom OP erwähnt) und Ziffern 0-9, könnte man weglassen auch die Auftragstabelle und stattdessen multiplizieren beiden unterschiedlichen Charaktere von 4 und vergleichen die Ergebnisse modulo 256. der Bereich von ASCII Ziffern (48 bis 57) nicht überlaufen 8 Bit (57 × 4 = 228), aber der Bereich von Großbuchstaben (65 bis 90), wird (65 × 4 = 260). Wenn wir die multiplizierten Werte modulo 256 zu vergleichen, wird der Wert für jeden Buchstaben kleiner sein als die jede Ziffer: 90 × 4% 256 = 104 <192 = 48 × 4

Der Code könnte etwa wie folgt aussehen:

int my_strcmp (const char *s1, const char *s2) {
    for (; *s1 == *s2 && *s1; ++s1, ++s2);
    return (((*(const unsigned char *)s1) * 4) & 0xFF) - \
           (((*(const unsigned char *)s2) * 4) & 0xFF);
}

Natürlich ist die Reihenfolge Tischlösung weitaus vielseitigen im Allgemeinen, da es eine eine Sortierreihenfolge für jedes Zeichen dieser Lösung ermöglicht die Definition sinnvoll ist, nur für diesen speziellen Fall mit Groß Buchstaben vs Ziffern . (Aber zum Beispiel auf dem Mikrocontroller-Plattformen, spart auch die geringe Menge an Speicher, der von der Tabelle verwendet wird, kann ein echter Vorteil sein.)

Andere Tipps

Was Sie tun müssen, ist für jedes Zeichen eine Bestelltabelle zu erstellen. Dies ist auch der einfachste Weg, Groß- und Kleinschreibung Vergleiche auch zu tun.

if (order_table[*s1] != order_table[*s2++])

Beachten Sie, dass Zeichen könnte unterzeichnet werden, in welchem ??Fall der Index auf den Tisch könnte negativ werden. Dieser Code ist für signierte Zeichen nur:

int raw_order_table[256];
int * order_table = raw_order_table + 128;
for (int i = -128;  i < 128;  ++i)
    order_table[i] = (i >= '0' && i <= '9') ? i + 256 : toupper(i);

Wenn Sie Ihre Kräfte-dass-sein wie alle die anderen Mächte-that-sein, dass ich den Weg laufen haben, sollten Sie es eine Option machen (auch wenn es versteckt):

  

Sortierung:

     

o Zahlen nach Buchstaben

     

o Buchstaben nach Zahlen

oder noch schlimmer, sie könnten herausfinden, dass sie wollen Zahlen numerisch sortiert werden (zum Beispiel „A123“ kommt nach „A15“), dann kann es sein

  

o Zahlen nach Buchstaben

     

o Buchstaben nach Zahlen

     

o Smart-Zahlen nach Buchstaben

     

o Buchstaben nach Smart-Zahlen

Dies wird in das eigentliche Problem der Diagnose, nicht das Symptom. Ich wette, es gibt eine leichte Chance, dass sie ihre Meinung auf der 11. Stunde und der 59. Minute ändern können.

Sie können eine Lookup-Tabelle verwenden ASCII zu EBCDIC zu übersetzen, wenn Zeichen zu vergleichen; -)

Während im allgemeinen Übereinstimmung mit den oben genannten Antworten, denke ich, dass es albern ist Lookups für jede Iteration der Schleife zu tun, es sei denn, Sie denken, dass die meisten Vergleiche unterschiedliche erste Zeichen haben werden, wenn Sie könnten stattdessen tun

char c1, c2;
while((c1 = *(s1++)) == (c2 = *(s2++)) && c1 != '\0');
return order_table[c1] - order_table[c2];

Auch würde ich empfehlen die order_table mit einem statischen Initialisierer Konstruktion, die Geschwindigkeit zu verbessern (keine Notwendigkeit, jedes Mal zu erzeugen - oder überhaupt) und vielleicht auch die Lesbarkeit

Hier ist, was eine ziemlich gute Umsetzung der Zeichenfolge sein sollte eine vergleichen ähnliche von anderen Beiträgen beschrieben.

static const unsigned char char_remap_table[256] = /* values */

#define char_remap(c) (char_remap_table[(unsigned char) c])

int nonstd_strcmp(const char * restrict A, const char * restrict B) {
     while (1) {
          char a = *A++;
          char b = *B++;
          int x = char_remap(a) - char_remap(b);
          if (x) {
               return x;
          }
          /* Still using null termination, so test that from the original char,
           * but if \0 maps to \0 or you want to use a different end of string
           * then you could use the remapped version, which would probably work
           * a little better b/c the compiler wouldn't have to keep the original
           * var a around. */
          if (!a) { /* You already know b == a here, so only one test is needed */
               return x;  /* x is already 0 and returning it allows the compiler to
                           * store it in the register that it would store function
                           * return values in without doing any extra moves. */
          }
     }
}

Darüber hinaus, dass Sie die Funktion verallgemeinern könnten die char_remap_table als Parameter zu nehmen, die Sie leicht erlauben würden, später verschiedene Abbildungen verwenden, wenn Sie benötigt werden.

int nonstd_strcmp(const char * restrict a, const char * restrict b, const char * restrict map);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top