If I am not allowed to use the <string.h> library, how can I easily compare values of a string. I have a data file with 6 possible values for one member of a structure. All I need to do is create a loop to count how many of each value is present in an array of structs. The problem is, I cannot figure out how to compare the value and thus when to increment the counter.
for (i = 0; i < datasize; i++){
if (struct.membervalue == given)
givencount++;
if (struct.membervalue == given2) // But I can't compare them with the ==
givencount2++ ; // because they are strings.
}
EDIT: predefined enum that I MUST USE
typedef enum {
penny = 1,
nickel = 5,
dime = 10,
quarter = 25
}changeT;
I have the value "penny" how do I compare to this or relate it?
bool isEqual(const char *string1, const char *string2)
{
do
{
if (*string1 != *string2) return false;
if (*string1 == 0) return true;
++string1;
++string2;
} while (1);
}
Update: The enum doesn't change anything. You still have to identify the string "penny" before you can assign it the value for a penny.
You can try the following function:
int str_cmp(const unsigned char* str1, const unsigned char* str2)
{
int result;
do {
result = (int)*str1 - (int)*str2;
str1++;
str2++;
} while((!result) && (*str1|*str2))
return result;
}
Output is a positive if str1>str2, negative if str1<str2 and zero if they are equal.
Fastest one:
int strcmp(const char *s1, const char *s2) {
int ret = 0;
while (!(ret = *(unsigned char *) s1 - *(unsigned char *) s2) && *s2)
++s1, ++s2;
if (ret < 0) {
ret = -1;
}
else if (ret > 0) {
ret = 1 ;
}
return ret;
}
/*These variants could point to invalid memmory, but dont de-reference it.*/
int isEqual(const char *string1, const char *string2)
{
while (*string1 == *string2++)
if ( 0 == *string1++ ) return 1;
return 0;
}
/* This variant is NULL-resistent. For both NULL return true.*/
int isEqual(const char *string1, const char *string2)
{
if ( !string1 || !string2 ) return string1 == string2 ;
while (*string1 == *string2++)
if ( 0 == *string1++ ) return 1;
return 0;
}
These are only the function to compare strings. In order to help more we need to see the code you are trying. It could be something like:
if (isEqual(data.membervalue, "penny" ) pennycount++;
else
if (isEqual(data.membervalue, "nickel") nickelcount++;
And the enum you provided is not of great help to count. It is useful to calculate the "monetary" total.
int Total= penny * pennycount + nickel * nickelcount ... ;
If all you need is the total, thing get simpler:
if (isEqual(data.membervalue, "penny" ) Total += penny;
else
if (isEqual(data.membervalue, "nickel") Total += nickel;
Related
It is possible to convert integer to string in C without sprintf?
There's a nonstandard function:
char *string = itoa(numberToConvert, 10); // assuming you want a base-10 representation
Edit: it seems you want some algorithm to do this. Here's how in base-10:
#include <stdio.h>
#define STRINGIFY(x) #x
#define INTMIN_STR STRINGIFY(INT_MIN)
int main() {
int anInteger = -13765; // or whatever
if (anInteger == INT_MIN) { // handle corner case
puts(INTMIN_STR);
return 0;
}
int flag = 0;
char str[128] = { 0 }; // large enough for an int even on 64-bit
int i = 126;
if (anInteger < 0) {
flag = 1;
anInteger = -anInteger;
}
while (anInteger != 0) {
str[i--] = (anInteger % 10) + '0';
anInteger /= 10;
}
if (flag) str[i--] = '-';
printf("The number was: %s\n", str + i + 1);
return 0;
}
Here's an example of how it might work. Given a buffer and a size, we'll keep dividing by 10 and fill the buffer with digits. We'll return -1 if there is not enough space in the buffer.
int
integer_to_string(char *buf, size_t bufsize, int n)
{
char *start;
// Handle negative numbers.
//
if (n < 0)
{
if (!bufsize)
return -1;
*buf++ = '-';
bufsize--;
}
// Remember the start of the string... This will come into play
// at the end.
//
start = buf;
do
{
// Handle the current digit.
//
int digit;
if (!bufsize)
return -1;
digit = n % 10;
if (digit < 0)
digit *= -1;
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
//
if (!bufsize)
return -1;
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first.
// Now reverse the string.
//
--buf;
while (start < buf)
{
char a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
Unfortunately none of the answers above can really work out in a clean way in a situation where you need to concoct a string of alphanumeric characters.There are really weird cases I've seen, especially in interviews and at work.
The only bad part of the code is that you need to know the bounds of the integer so you can allocate "string" properly.
In spite of C being hailed predictable, it can have weird behaviour in a large system if you get lost in the coding.
The solution below returns a string of the integer representation with a null terminating character. This does not rely on any outer functions and works on negative integers as well!!
#include <stdio.h>
#include <stdlib.h>
void IntegertoString(char * string, int number) {
if(number == 0) { string[0] = '0'; return; };
int divide = 0;
int modResult;
int length = 0;
int isNegative = 0;
int copyOfNumber;
int offset = 0;
copyOfNumber = number;
if( number < 0 ) {
isNegative = 1;
number = 0 - number;
length++;
}
while(copyOfNumber != 0)
{
length++;
copyOfNumber /= 10;
}
for(divide = 0; divide < length; divide++) {
modResult = number % 10;
number = number / 10;
string[length - (divide + 1)] = modResult + '0';
}
if(isNegative) {
string[0] = '-';
}
string[length] = '\0';
}
int main(void) {
char string[10];
int number = -131230;
IntegertoString(string, number);
printf("%s\n", string);
return 0;
}
You can use itoa where available. If it is not available on your platform, the following implementation may be of interest:
https://web.archive.org/web/20130722203238/https://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/atoi_8c-source.html
Usage:
char *numberAsString = itoa(integerValue);
UPDATE
Based on the R..'s comments, it may be worth modifying an existing itoa implementation to accept a result buffer from the caller, rather than having itoa allocate and return a buffer.
Such an implementation should accept both a buffer and the length of the buffer, taking care not to write past the end of the caller-provided buffer.
int i = 24344; /*integer*/
char *str = itoa(i);
/*allocates required memory and
then converts integer to string and the address of first byte of memory is returned to str pointer.*/
Indian Currency format is 12345 → "12,345" (for odd length) and 123456 → "1,23,456" (for even length). I have included all possibilities such as
1. Minus sign: "-12,345".
2. Decimal Point: "-12,345.345" or "12,345.123".
3. Zero Condition 000000.123 → "0.123".
4.Minus and Zero Condition '-000000.123' -> "-0.123"
int currencyFormatter(char av_currency[], int av_strLen, char *ap_formattedNumber)
{
char flag = 'N'; //Taking a Flag to know whether thier is a decimal Point in Currency or not
int lengthOf = 0, index = 0, i = 0, j = 0;
char *decAr = NULL;
char *tmpCurrency = NULL;//Taking two Pointers one for Array with Commas(tmpCurrency) and decAr pointer for decimal Point array
char *s = NULL;
s = strstr(av_currency, ".");//Checking for decimal Point in array
if (s > 0)
{
flag = 'D'; // Changing Flag to show Decimal Point is Present in Array
s = strchr(av_currency, '.');
index = s - av_currency; //Index at which Decimal Point is present
av_strLen = strlen(av_currency) - index; // calculated formula to know length of an array needed to contain decimal point and Numbers after that
decAr = (char*)malloc(av_strLen*sizeof(char*));//allocated Memory using malloc
decAr[av_strLen] = '\0';
memmove(decAr, &av_currency[index], av_strLen); //memmove from decimal till end of array.
av_currency[index] = '\0';
if (!decAr)//Handled Null Condition for Pointer
{
return -1;//All errors for Negative Number
}
}
lengthOf = strlen(av_currency) + (strlen(av_currency) / 2); // Derived Formula(It Works for Indian Currency Format) to know the length of an array is needed to contain numbers and Commas Together.
tmpCurrency = (char*)malloc(lengthOf*sizeof(char*));
strrev(av_currency); //Reversed Array as commas comes at multiple of 3. eg=12345 reverse=54321 wdComma=543,21 index is 3 if number would had been bigger commas would had come at 3,6.
while (av_currency[i] != '\0')
{
if (j % 3 == 0 && j >= 3 && av_currency[i] != '-')//all Commas come at multiple of 3 when you reverse an amount
{
tmpCurrency[j] = ',';//If an , is found Increment only J as
is used as index number to store in tmpcurrency
j++;
continue;
}
tmpCurrency[j] = av_currency[i];//storing the Value in tmpCurrency
i++;//Incrementing
j++;//Incrementing
}
tmpCurrency[j] = '\0';//Null Condition
if (!tmpCurrency) // Checking for NULL Pointer
{
return -2; //all errors for Negative value
}
flag == 'D' ? strcpy(av_currency, (strcat(strrev(tmpCurrency), decAr))) : strcpy(av_currency, (strrev(tmpCurrency)));//Ternary Operator
strcpy(ap_formattedNumber,av_currency);//Copying formated number into original array
free(tmpCurrency);//Releasing the memory
free(decAr);//Releasing the Memory
return 0;
}
I have solution for above question.
Please try this code.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
char *printComma(double input_number,char *demo,char ap_it[],char ap_type[])
{
char *result = NULL;
char *lp_decimal_number = NULL;
char *main_number = NULL;
char *decimal_pos = NULL;
char zero[1] = {0};
int i = 0;
int j = 0;
int z = 0;
int cnt = 0;
int decimal_index = 0;
int lp_decimal_numberLen = 0 ;
int flag_dec = 0;
int flag_minus = 0 ;
int length_main;
int k = 0;
int length_demo=0;
sprintf(demo,"%lf",input_number);
if(strcmp(ap_type,"P") == 0)
{
if(strcmp(ap_it,"A") == 0 || strcmp(ap_it,"B") == 0)
{
sprintf_s(demo,40,"%0.4lf",input_number);
}
else
{
sprintf_s(demo,40,"%0.2lf",input_number);
}
}
else
{
sprintf_s(demo,40,"%.0lf",input_number);
}
length_demo = strlen(demo); // finds the length of original string
result = (char *)malloc((length_demo+10)*sizeof(char));
main_number = (char *)malloc((length_demo+50)*sizeof(char));
z = strspn(demo[0] == '-' ? (demo + 1) : demo , "0");
if(z != 0)
{
if(demo[0] != '-')
{
memcpy(main_number,&demo[z],length_demo);
main_number[length_demo]='\0';
}
else
{
puts(main_number);
main_number[length_demo]='\0';
flag_minus=1;
}
}
else
{
memcpy(main_number,&demo[0],length_demo);
main_number[length_demo]='\0';
}
length_main=strlen(main_number);
decimal_pos = strstr(main_number,".");
if(decimal_pos > 0)
{
decimal_index = decimal_pos - main_number ; // Getting postion of decimal
lp_decimal_numberLen = length_main - decimal_index; // Calculating the endpoint for decimal number
if(length_main > 3) //Copying the decimal part to a separate array
{
lp_decimal_number = (char *) malloc(lp_decimal_numberLen+1);
memcpy( lp_decimal_number, &main_number[decimal_index], lp_decimal_numberLen );
lp_decimal_number[lp_decimal_numberLen] = '\0';
flag_dec=1;
main_number[decimal_index]='\0';
}
}
//logic for comma starts here
strrev(main_number);
i = 0;
while(main_number[i] != '\0')
{
if (j%3 == 0 && j>=3 && main_number[i]!='-' && main_number[i]!='$')
{
result[j] = ',';
cnt++;
j++;
continue;
}
else if(cnt==1 || cnt==2)
{
result[j] = main_number[i];
}
else
{
result[j] = main_number[i];
}
i++;
j++;
}
result[j] = '\0';
if(flag_dec==0)
{
if(flag_minus==0)
return(strrev(result));
else
{
strcat(result,"-");
return(strrev(result));
}
}
else
{
if(flag_minus==0)
return(strcat(strrev(result),lp_decimal_number));
else
{
strcat(result,"-");
return(strcat(strrev(result),lp_decimal_number));
}
}
}
int main()
{
double number;
char num[25] = {0};
char it_type[] = "A";
char ap_type[] = "P";
char *formattedNumber = NULL;
printf("\n Enter the number n: ");
scanf("%lf",&number);
formattedNumber=printComma(number,num,it_type,ap_type);
printf("\n Final Result = %s ",formattedNumber);
getch();
return 0;
}
Do only positive values with your function!
Check if the value is negative before calling the function; call the function with the positive value; if it was negative to start with, add the minus sign afterwards.
int needssign = 0;
if (val < 0) needssign = 1;
indianformat(res, abs(val));
if (needssign) sprintf(res, "-%s", res);
Or make your current function a helper function and use the code above for the new improved function for formatting in Indian format.
Hi,
Say i have string like "888820c8". How do i fetch that 3 bits in an int in c programming language?
UPDATE 1 -
This is what i was able to do
static const char* getlast(const char *pkthdr)
{
const char *current;
const char *found = NULL;
const char *target = "8888";
int index = 0;
char pcp = 0;
size_t target_length = strlen(target);
current = pkthdr + strlen(pkthdr) - target_length;
while ( current >= pkthdr ) {
if ((found = strstr(current, target))) {
printf("found!\n");
break;
}
current -= 1;
}
if(found)
{
index = found - pkthdr;
index += 4; /*go to last of 8188*/
}
printf("index %d\n", index);
/* Now how to get the next 3 bits*/
printf("pkthdr %c\n", pkthdr[index]);
pcp = pkthdr[index] & 0x7;
printf("%c\n", pcp);
return pcp;
}
Clearly i know the last part of my program is wrong and any inputs would be helpful. thanks!
Update 2:
Thanks pratik for the pointer.
Does the below code look good now?
static char getlast(const char *pkthdr)
{
const char *current;
const char *found = NULL;
const char *tpid = "8188";
int index = 0;
char *pcp_byte = 0;
char pcp = 0;
int pcp2 = 0;
char byte[2] = {0};
char *p;
unsigned int uv =0 ;
size_t target_length = strlen(tpid);
current = pkthdr + strlen(pkthdr) - target_length;
//printf("current %d\n", current);
while ( current >= pkthdr ) {
if ((found = strstr(current, tpid))) {
printf("found!\n");
break;
}
current -= 1;
}
found = found + 4;
strncpy(byte,found,2);
byte[2] = '\0';
uv =strtoul(byte,&p,16);
uv = uv & 0xE0;
char i = uv >> 5;
printf("%d i",i);
return i;
}
The code that you have locates the character that contains the 3 bits that you want. That character will be a digit ('0' thru '9'), an uppercase letter ('A' thru 'F') or a lowercase letter ('a' thru 'f'). So the first task is to convert the character to its numeric equivalent, e.g. like this
unsigned int value;
if ( sscanf( &pkthdr[index], "%1x", &value ) != 1 )
{
// handle error: the character was not a valid hexadecimal digit
}
At this point, you have a 4-bit value, but you want to extract the upper three bits. That can be done with shifting and masking, e.g.
int result = (value >> 1) & 7;
printf( "%d\n", result );
Note that if you want to return the 3-bit number from the function, the function prototype needs to be changed to return an int, e.g.
static int getlast(const char *pkthdr)
{
// ...
return result;
}
Read this string char array
Char data[8] = "888820c8"
(data[4]&0xe0) >> 5 is your ans
I was going through some Amazon interview questions on CareerCup.com, and I came across this interesting question which I haven't been able to figure out how to do. I have been thinking on this since 2 days. Either I am taking a way off approach, or its a genuinely hard function to write.
Question is as follows:
Write a function in C that can find if a string is a sub-string of another. Note that a mismatch of one character
should be ignored.
A mismatch can be an extra character: ’dog’ matches ‘xxxdoogyyyy’
A mismatch can be a missing character: ’dog’ matches ‘xxxdgyyyy’
A mismatch can be a different character: ’dog’ matches ‘xxxdigyyyy’
The return value wasn't mentioned in the question, so I assume the signature of the function can be something like this:
char * MatchWithTolerance(const char * str, const char * substr);
If there is a match with the given rules, return the pointer to the beginning of matched substring within the string. Else return null.
Bonus
If someone can also figure out a generic way of making the tolerance to n instead of 1, then that would be just brilliant.
In that case the signature would be:
char * MatchWithTolerance(const char * str, const char * substr, unsigned int tolerance = 1);
This seems to work, let me know if you find any errors and I'll try to fix them:
int findHelper(const char *str, const char *substr, int mustMatch = 0)
{
if ( *substr == '\0' )
return 1;
if ( *str == '\0' )
return 0;
if ( *str == *substr )
return findHelper(str + 1, substr + 1, mustMatch);
else
{
if ( mustMatch )
return 0;
if ( *(str + 1) == *substr )
return findHelper(str + 1, substr, 1);
else if ( *str == *(substr + 1) )
return findHelper(str, substr + 1, 1);
else if ( *(str + 1) == *(substr + 1) )
return findHelper(str + 1, substr + 1, 1);
else if ( *(substr + 1) == '\0' )
return 1;
else
return 0;
}
}
int find(const char *str, const char *substr)
{
int ok = 0;
while ( *str != '\0' )
ok |= findHelper(str++, substr, 0);
return ok;
}
int main()
{
printf("%d\n", find("xxxdoogyyyy", "dog"));
printf("%d\n", find("xxxdgyyyy", "dog"));
printf("%d\n", find("xxxdigyyyy", "dog"));
}
Basically, I make sure only one character can differ, and run the function that does this for every suffix of the haystack.
This is related to a classical problem of IT, referred to as Levenshtein distance.
See Wikibooks for a bunch of implementations in different languages.
This is slightly different than the earlier solution, but I was intrigued by the problem and wanted to give it a shot. Obviously optimize if desired, I just wanted a solution.
char *match(char *str, char *substr, int tolerance)
{
if (! *substr) return str;
if (! *str) return NULL;
while (*str)
{
char *str_p;
char *substr_p;
char *matches_missing;
char *matches_mismatched;
str_p = str;
substr_p = substr;
while (*str_p && *substr_p && *str_p == *substr_p)
{
str_p++;
substr_p++;
}
if (! *substr_p) return str;
if (! tolerance)
{
str++;
continue;
}
if (strlen(substr_p) <= tolerance) return str;
/* missed due to a missing letter */
matches_missing = match(str_p, substr_p + 1, tolerance - 1);
if (matches_missing == str_p) return str;
/* missed due to a mismatch of letters */
matches_mismatched = match(str_p + 1, substr_p + 1, tolerance - 1);
if (matches_mismatched == str_p + 1) return str;
str++;
}
return NULL;
}
Is the problem to do this efficiently?
The naive solution is to loop over every substring of size substr in str, from left to right, and return true if the current substring if only one of the characters is different in a comparison.
Let n = size of str
Let m = size of substr
There are O(n) substrings in str, and the matching step takes time O(m). Ergo, the naive solution runs in time
O(n*m)
With arbitary no. of tolerance levels.
Worked for all the test cases I could think of. Loosely based on |/|ad's solution.
#include<stdio.h>
#include<string.h>
report (int x, char* str, char* sstr, int[] t) {
if ( x )
printf( "%s is a substring of %s for a tolerance[%d]\n",sstr,str[i],t[i] );
else
printf ( "%s is NOT a substring of %s for a tolerance[%d]\n",sstr,str[i],t[i] );
}
int find_with_tolerance (char *str, char *sstr, int tol) {
if ( (*sstr) == '\0' ) //end of substring, and match
return 1;
if ( (*str) == '\0' ) //end of string
if ( tol >= strlen(sstr) ) //but tol saves the day
return 1;
else //there's nothing even the poor tol can do
return 0;
if ( *sstr == *str ) { //current char match, smooth
return find_with_tolerance ( str+1, sstr+1, tol );
} else {
if ( tol <= 0 ) //that's it. no more patience
return 0;
for(int i=1; i<=tol; i++) {
if ( *(str+i) == *sstr ) //insertioan of a foreign character
return find_with_tolerance ( str+i+1, sstr+1, tol-i );
if ( *str == *(sstr+i) ) //deal with dletion
return find_with_tolerance ( str+1, sstr+i+1, tol-i );
if ( *(str+i) == *(sstr+i) ) //deal with riplacement
return find_with_tolerance ( str+i+1, sstr+i+1, tol-i );
if ( *(sstr+i) == '\0' ) //substr ends, thanks to tol & this loop
return 1;
}
return 0; //when all fails
}
}
int find (char *str, char *sstr, int tol ) {
int w = 0;
while (*str!='\0')
w |= find_with_tolerance ( str++, sstr, tol );
return (w) ? 1 : 0;
}
int main() {
const int n=3; //no of test cases
char *sstr = "dog"; //the substr
char *str[n] = { "doox", //those cases
"xxxxxd",
"xxdogxx" };
int t[] = {1,1,0}; //tolerance levels for those cases
for(int i = 0; i < n; i++) {
report( find ( *(str+i), sstr, t[i] ), *(str+i), sstr, t[i] );
}
return 0;
}
Looking for a proven to work algorithm for production.
Did see this example
but not finding much else on the web or in books.
i.e.
file_10.txt > file_2.txt
Thanks.
Here is a (tested) comparison function that does the job. It understands only unsigned integers, not signed integers or floating point:
#include <stdlib.h>
#include <ctype.h>
/* like strcmp but compare sequences of digits numerically */
int strcmpbynum(const char *s1, const char *s2) {
for (;;) {
if (*s2 == '\0')
return *s1 != '\0';
else if (*s1 == '\0')
return 1;
else if (!(isdigit(*s1) && isdigit(*s2))) {
if (*s1 != *s2)
return (int)*s1 - (int)*s2;
else
(++s1, ++s2);
} else {
char *lim1, *lim2;
unsigned long n1 = strtoul(s1, &lim1, 10);
unsigned long n2 = strtoul(s2, &lim2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
s1 = lim1;
s2 = lim2;
}
}
}
If you want to use it with qsort, use this auxiliary function:
static int compare(const void *p1, const void *p2) {
const char * const *ps1 = p1;
const char * const *ps2 = p2;
return strcmpbynum(*ps1, *ps2);
}
And you can do something on the order of
qsort(lines, next, sizeof(lines[0]), compare);
The basic sort function would be standard C qsort(). It is parameterized to take a comparison function, and the comparison function is what you would need to write to do the natural ordering.
Your cross-referenced question includes a C implementation of a comparison function.
A Google search 'natural sort c' shows a SourceForge implementation.
I assume you already know the C standard library qsort() function:
void qsort(void *base,
size_t nel,
size_t width,
int (*compar)(const void *, const void *);
That last parameter is a function pointer, which means you can pass any function to it. You could use strcmp(), in fact, but that would give you ASCIIbetical, and you specifically want a natural sort.
In that case, you could write one pretty easily:
#include <ctype.h>
int natural(const char *a, const char *b)
{
if(isalpha(*a) && isalpha(*b))
{
// compare two letters
}
else
{
if(isalpha(*a))
{
// compare a letter to a digit (or other non-letter)
}
else if(isalpha(*b))
{
// compare a digit/non-letter to a letter
}
else
{
// compare two digits/non-letters
}
}
}
Some of the elses could be cleared up if you just return early, but there's a basic structure. Check ctype.h for functions like isalpha() (if a character is part of the alphabet), isdigit(), isspace(), and more.
Here's a version for Qt, that also supports unicode:
int strcmpbynum(const QString& s1, const QString &s2) {
int i1 = 0; // index in string
int i2 = 0;
while (true) {
if (s2.length() == i2) // both strings identical or s1 larger than s2
return s1.length() == i1 ? 0 : 1;
if (s1.length() == i1) return -1; // s1 smaller than s2
unsigned short u1 = s1[i1].unicode();
unsigned short u2 = s2[i2].unicode();
if (u1 >= '0' && u1 <= '9' && u2 >= '0' && u2 <= '9') {
// parse both numbers completely and compare them
quint64 n1 = 0; // the parsed number
quint64 n2 = 0;
int l1 = 0; // length of the number
int l2 = 0;
do {
++l1;
n1 = n1 * 10 + u1 - '0';
if (++i1 == s1.length()) break;
u1 = s1[i1].unicode();
} while (u1 >= '0' && u1 <= '9');
do {
++l2;
n2 = n2 * 10 + u2 - '0';
if (++i2 == s2.length()) break;
u2 = s2[i2].unicode();
} while (u2 >= '0' && u2 <= '9');
// compare two numbers
if (n1 < n2) return -1;
if (n1 > n2) return 1;
// only accept identical numbers if they also have the same length
// (same number of leading zeros)
if (l1 < l2) return -1;
if (l1 > l2) return 1;
} else {
// compare digit with non-digit or two non-digits
if (u1 < u2) return -1;
if (u1 > u2) return 1;
++i1;
++i2;
}
}
}