Last active
August 29, 2015 13:56
-
-
Save raidzero/9330247 to your computer and use it in GitHub Desktop.
Version number comparator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Uses stdin to evaluate a statement such as "2.5.3" <= 2.4". Returns strings "True" or "False" to terminal | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#define DEBUG 0 | |
// helpers | |
int count_chars(char*, char); | |
int* split_vers(char*, char*); | |
int main(int argc, char* argv[]) | |
{ | |
char* exp; // this is the expression being tested | |
// do we have args? | |
if (argc == 2) | |
{ | |
exp = malloc(strlen(argv[1] + 1) * sizeof(char)); | |
strcpy(exp, argv[1]); | |
} | |
else | |
{ | |
if (isatty(fileno(stdin))) // real terminal? | |
{ | |
printf("Enter expression to test: "); // print data entry prompt if a real term | |
} | |
exp = malloc(256); | |
fgets(exp, 256, stdin); | |
} | |
// split up expression into 3 parts, vers1, logical operator and vers2 | |
char* sVers1 = strtok(exp, " "); | |
char* comp = strtok(NULL, " "); | |
char* sVers2 = strtok(NULL, " "); | |
// strip the last char if its a newline | |
if (sVers2[strlen(sVers2)] == '\n') | |
{ | |
sVers2[strlen(sVers2)-1] = '\0'; | |
} | |
#if DEBUG | |
printf("1: '%s'\ncomp: '%s'\n1: '%s'\n", sVers1, comp, sVers2); | |
#endif | |
// count the dots in version1 and 2 | |
int iVers1count = count_chars(sVers1, '.'); | |
int iVers2count = count_chars(sVers2, '.'); | |
// what if no dots are found in the versions? | |
if (iVers1count == 0 || iVers2count == 0) | |
{ | |
printf("Error: Must have versions with dot notation.\n"); | |
exit(255); | |
} | |
// split the versions into an array using a dot delimiter | |
int* aVers1 = split_vers(sVers1, "."); | |
int* aVers2 = split_vers(sVers2, "."); | |
// which is longest? | |
int hiLen = (iVers1count > iVers2count) ? iVers1count + 1: iVers2count + 1; | |
int loLen = (iVers1count < iVers2count) ? iVers1count + 1: iVers2count + 1; | |
#if DEBUG | |
printf("hi: %d\n", loLen); | |
printf("lo: %d\n", hiLen); | |
#endif | |
/* just use ints to store comparisons, enums dont work with switch | |
high = 1 | |
low = -1 | |
equal = 0 | |
null = -999 | |
*/ | |
// array to record comparisons for indices between versions | |
int* comparisons = malloc((hiLen + 1) * sizeof(int*)); | |
int i; | |
// iterate over the longest, storing the comparison result | |
for(i=0; i<hiLen; i++) | |
{ | |
if (aVers1[i] > aVers2[i]) | |
{ | |
#if DEBUG | |
printf("aVers1[%d] > aVers2[%d]\n", i, i); | |
#endif | |
comparisons[i] = 1; | |
} | |
else if ( aVers1[i] < aVers2[i]) | |
{ | |
#if DEBUG | |
printf("aVers1[%d] < aVers2[%d]\n",i, i); | |
#endif | |
comparisons[i] = -1; | |
} | |
else | |
{ | |
#if DEBUG | |
printf("aVers1[%d] = aVers2[%d]\n", i, i); | |
#endif | |
comparisons[i] = 0; | |
} | |
} | |
free(aVers1); | |
free(aVers2); | |
int compCount = i; // how many comparisons do we have | |
#if DEBUG | |
printf("%d comparisons stored.\n", compCount); | |
#endif | |
int finalResult = 0; // assume equal | |
// test for full equality | |
for (i=0; i<compCount; i++) | |
{ | |
#if DEBUG | |
printf("comparisons[%d]: %d\n", i, comparisons[i]); | |
#endif | |
if (comparisons[i] != 0) | |
{ | |
finalResult = -999; | |
#if DEBUG | |
printf("comparisons[%d] is not equal.\n", i); | |
#endif | |
//break; | |
} | |
else | |
{ | |
#if DEBUG | |
printf("comparisons[%d] is equal.\n", i); | |
#endif | |
} | |
} | |
if (finalResult == 0) | |
{ | |
goto END; | |
} | |
// now that we know the versions arent equal... | |
for (i=0; i<compCount; i++) | |
{ | |
// is this number equal | |
if (comparisons[i] == 0) | |
{ | |
continue; // just move on to next | |
} | |
// if we got here then we have reached the first non-equal comparison | |
finalResult = comparisons[i]; // :) | |
break; | |
} | |
free(comparisons); | |
free(exp); | |
int result = 1; // true or false | |
END: | |
switch (finalResult) | |
{ | |
case 1: | |
result = strstr(comp, ">") ? 0 : 1; | |
break; | |
case -1: | |
result = strstr(comp, "<") ? 0 : 1; | |
break; | |
case 0: | |
result = strstr(comp, "=") ? 0 : 1; | |
break; | |
} | |
if (result == 0) | |
{ | |
printf("True\n"); | |
} | |
else | |
{ | |
printf("False\n"); | |
} | |
exit(result); | |
} | |
int count_chars(char* s, char c) | |
{ | |
int sLen = strlen(s); | |
int i; | |
int count = 0; | |
for(i=0; i<sLen; i++) | |
{ | |
if (s[i] == c) | |
count++; | |
} | |
#if DEBUG | |
printf("\"%s\" has %d \'%c\'s in it.\n", s, count, c); | |
#endif | |
return count; | |
} | |
int* split_vers(char* version, char* delim) | |
{ | |
int count = count_chars(version, *delim); | |
int* vArray = malloc((count+1) * sizeof(int)); | |
int i = 0; | |
char* vNum; | |
for (i=0; i<=count; i++) | |
{ | |
if (i == 0) vNum = strtok(version, delim); | |
if (vNum != NULL) | |
{ | |
vArray[i] = atoi(vNum); | |
#if DEBUG | |
printf("vArray[%d]: %s\n", i, vNum); | |
#endif | |
vNum = strtok(NULL, "."); | |
} | |
} | |
return vArray; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment