Numeric Sort Order
Order records by numeric order without converting the text
to a numeric value.
- Declare (simple) numeric ordering field (numeric)
- Field declaration
- Segment Source
-
113: int numeric; /* Flag for numeric comparison. Handle
114: strings of digits with optional decimal
115: point, but no exponential notation. */
- Insert user message text
-
Text insertion
- Segment Source
-
230: -n compare according to string numerical value, imply -b\n\
- Define fraccompare()
-
Function definition
- Segment Source
-
753: /* Compare strings A and B containing decimal fractions < 1. Each string
754: should begin with a decimal point followed immediately by the digits
755: of the fraction. Strings not of this form are considered to be zero. */
756:
757: static int
758: fraccompare (register const char *a, register const char *b)
759: {
760: register int tmpa = *a;
761: register int tmpb = *b;
762:
763: if (tmpa == '.' && tmpb == '.')
764: {
765: do
766: tmpa = *++a, tmpb = *++b;
767: while (tmpa == tmpb && ISDIGIT (tmpa));
768: if (ISDIGIT (tmpa) && ISDIGIT (tmpb))
769: return tmpa - tmpb;
770: if (ISDIGIT (tmpa))
771: {
772: while (tmpa == '0')
773: tmpa = *++a;
774: if (ISDIGIT (tmpa))
775: return 1;
776: return 0;
777: }
778: if (ISDIGIT (tmpb))
779: {
780: while (tmpb == '0')
781: tmpb = *++b;
782: if (ISDIGIT (tmpb))
783: return -1;
784: return 0;
785: }
786: return 0;
787: }
788: else if (tmpa == '.')
789: {
790: do
791: tmpa = *++a;
792: while (tmpa == '0');
793: if (ISDIGIT (tmpa))
794: return 1;
795: return 0;
796: }
797: else if (tmpb == '.')
798: {
799: do
800: tmpb = *++b;
801: while (tmpb == '0');
802: if (ISDIGIT (tmpb))
803: return -1;
804: return 0;
805: }
806: return 0;
807: }
808:
- Define numcompare()
-
Function definition
- Segment Source
-
809: /* Compare strings A and B as numbers without explicitly converting them to
810: machine numbers. Comparatively slow for short strings, but asymptotically
811: hideously fast. */
812:
813: static int
814: numcompare (register const char *a, register const char *b)
815: {
816: register int tmpa, tmpb, loga, logb, tmp;
817:
818: tmpa = UCHAR (*a);
819: tmpb = UCHAR (*b);
820:
821: while (blanks[tmpa])
822: tmpa = UCHAR (*++a);
823: while (blanks[tmpb])
824: tmpb = UCHAR (*++b);
825:
826: if (tmpa == '-')
827: {
828: do
829: tmpa = *++a;
830: while (tmpa == '0');
831: if (tmpb != '-')
832: {
833: if (tmpa == '.')
834: do
835: tmpa = *++a;
836: while (tmpa == '0');
837: if (ISDIGIT (tmpa))
838: return -1;
839: while (tmpb == '0')
840: tmpb = *++b;
841: if (tmpb == '.')
842: do
843: tmpb = *++b;
844: while (tmpb == '0');
845: if (ISDIGIT (tmpb))
846: return -1;
847: return 0;
848: }
849: do
850: tmpb = *++b;
851: while (tmpb == '0');
852:
853: while (tmpa == tmpb && ISDIGIT (tmpa))
854: tmpa = *++a, tmpb = *++b;
855:
856: if ((tmpa == '.' && !ISDIGIT (tmpb))
857: || (tmpb == '.' && !ISDIGIT (tmpa)))
858: return -fraccompare (a, b);
859:
860: if (ISDIGIT (tmpa))
861: for (loga = 1; ISDIGIT (*++a); ++loga)
862: ;
863: else
864: loga = 0;
865:
866: if (ISDIGIT (tmpb))
867: for (logb = 1; ISDIGIT (*++b); ++logb)
868: ;
869: else
870: logb = 0;
871:
872: if ((tmp = logb - loga) != 0)
873: return tmp;
874:
875: if (!loga)
876: return 0;
877:
878: return tmpb - tmpa;
879: }
880: else if (tmpb == '-')
881: {
882: do
883: tmpb = *++b;
884: while (tmpb == '0');
885: if (tmpb == '.')
886: do
887: tmpb = *++b;
888: while (tmpb == '0');
889: if (ISDIGIT (tmpb))
890: return 1;
891: while (tmpa == '0')
892: tmpa = *++a;
893: if (tmpa == '.')
894: do
895: tmpa = *++a;
896: while (tmpa == '0');
897: if (ISDIGIT (tmpa))
898: return 1;
899: return 0;
900: }
901: else
902: {
903: while (tmpa == '0')
904: tmpa = *++a;
905: while (tmpb == '0')
906: tmpb = *++b;
907:
908: while (tmpa == tmpb && ISDIGIT (tmpa))
909: tmpa = *++a, tmpb = *++b;
910:
911: if ((tmpa == '.' && !ISDIGIT (tmpb))
912: || (tmpb == '.' && !ISDIGIT (tmpa)))
913: return fraccompare (a, b);
914:
915: if (ISDIGIT (tmpa))
916: for (loga = 1; ISDIGIT (*++a); ++loga)
917: ;
918: else
919: loga = 0;
920:
921: if (ISDIGIT (tmpb))
922: for (logb = 1; ISDIGIT (*++b); ++logb)
923: ;
924: else
925: logb = 0;
926:
927: if ((tmp = loga - logb) != 0)
928: return tmp;
929:
930: if (!loga)
931: return 0;
932:
933: return tmpa - tmpb;
934: }
935: }
936:
- Dispatch (simple) numeric compare
-
Code insertion
- Segment Source
-
1049: if (key->numeric)
1050: {
1051: if (*lima || *limb)
1052: {
1053: char savea = *lima, saveb = *limb;
1054:
1055: *lima = *limb = '\0';
1056: diff = numcompare (texta, textb);
1057: *lima = savea, *limb = saveb;
1058: }
1059: else
1060: diff = numcompare (texta, textb);
1061:
1062: if (diff)
1063: return key->reverse ? -diff : diff;
1064: continue;
1065: }
- Parse NumOrder option (-n)
-
Code insertion
- Segment Source
-
1694: case 'n':
1695: key->numeric = 1;
1696: break;
- Establish global sort options
-
Code modification
- Segment Source
-
1773: gkey.numeric = gkey.general_numeric = gkey.month = gkey.reverse = 0;
- Propogate global sort options
Segment Element
Code modification
-
2032: && !key->skipeblanks && !key->month && !key->numeric
Segment Element
Code insertion
-
2040: key->numeric = gkey.numeric;
Segment Element
Code modification
-
2046: || gkey.skipeblanks || gkey.month || gkey.numeric