#include <stdio.h>
#define SECTOR_SIZE_DEFAULT 512LL
#define KILOBYTE_SIZE 1000LL
#define MEGABYTE_SIZE 1000000LL
#define GIGABYTE_SIZE 1000000000LL
#define TERABYTE_SIZE 1000000000000LL
#define KIBIBYTE_SIZE 1024LL
#define MEBIBYTE_SIZE 1048576LL
#define GIBIBYTE_SIZE 1073741824LL
#define TEBIBYTE_SIZE 1099511627776LL
typedef enum {
DIGIT_UNIT_BYTE,
DIGIT_UNIT_KILOBYTE,
DIGIT_UNIT_MEGABYTE,
DIGIT_UNIT_GIGABYTE,
DIGIT_UNIT_TERABYTE,
DIGIT_UNIT_KIBIBYTE,
DIGIT_UNIT_MEBIBYTE,
DIGIT_UNIT_GIBIBYTE,
DIGIT_UNIT_TEBIBYTE
} DigitUnit;
/* Inefficiently removes all spaces from a string, in-place. */
static void
strip_string (char* str)
{
int i;
for (i = 0; str[i] != 0; i++) {
if (isspace (str[i])) {
int j;
for (j = i + 1; str[j] != 0; j++)
str[j - 1] = str[j];
}
}
}
/* Find non-number suffix. Eg: find_suffix("32Mb") returns a pointer to
* "Mb". */
static char*
find_suffix (const char* str)
{
while (str[0] != 0 && (isdigit (str[0]) || strchr(",.-", str[0])))
str++;
return (char *) str;
}
static DigitUnit
parse_unit_suffix (const char* suffix)
{
if (strlen (suffix) > 1 && tolower (suffix[1]) == ‘i‘) {
switch (tolower (suffix[0])) {
case ‘k‘: return DIGIT_UNIT_KIBIBYTE;
case ‘m‘: return DIGIT_UNIT_MEBIBYTE;
case ‘g‘: return DIGIT_UNIT_GIBIBYTE;
case ‘t‘: return DIGIT_UNIT_TEBIBYTE;
}
} else if (strlen (suffix) > 0) {
switch (tolower (suffix[0])) {
case ‘b‘: return DIGIT_UNIT_BYTE;
case ‘k‘: return DIGIT_UNIT_KILOBYTE;
case ‘m‘: return DIGIT_UNIT_MEGABYTE;
case ‘g‘: return DIGIT_UNIT_GIGABYTE;
case ‘t‘: return DIGIT_UNIT_TERABYTE;
}
}
return -1;
}
long long unit_parse (const char *str)
{
char *suffix;
long long byte = -1;
long long byte_block = 1;
strip_string (str);
suffix = find_suffix (str);
DigitUnit unit = parse_unit_suffix (suffix);
switch (unit) {
case DIGIT_UNIT_BYTE:
break;
case DIGIT_UNIT_KILOBYTE:
byte_block = KILOBYTE_SIZE;
break;
case DIGIT_UNIT_MEGABYTE:
byte_block = MEGABYTE_SIZE;
break;
case DIGIT_UNIT_GIGABYTE:
byte_block = GIGABYTE_SIZE;
break;
case DIGIT_UNIT_TERABYTE:
byte_block = TERABYTE_SIZE;
break;
case DIGIT_UNIT_KIBIBYTE:
byte_block = KIBIBYTE_SIZE;
break;
case DIGIT_UNIT_MEBIBYTE:
byte_block = MEBIBYTE_SIZE;
break;
case DIGIT_UNIT_GIBIBYTE:
byte_block = GIBIBYTE_SIZE;
break;
case DIGIT_UNIT_TEBIBYTE:
byte_block = TEBIBYTE_SIZE;
break;
}
double temp = 0;
if (sscanf (str, "%lf", &temp) == 1)
byte = temp * byte_block;
return byte;
}
int main(int argc, char **argv)
{
if (argc > 1)
printf ("%lld\n", unit_parse (argv[1]));
}
原文:http://www.cnblogs.com/the-capricornus/p/4064697.html