Skip to content

Instantly share code, notes, and snippets.

@raidzero
Last active August 29, 2015 13:56
Show Gist options
  • Save raidzero/9330247 to your computer and use it in GitHub Desktop.
Save raidzero/9330247 to your computer and use it in GitHub Desktop.
Version number comparator
/*
* 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