#include <stdio.h> #include <stdlib.h> #include <string.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 { BASE_BINARY, BASE_DECIMAL } Base; 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; char * unit_format_custom (long long n, DigitUnit unit) { char *str = malloc(64); memset (str, 0, 64); float f; int len; char *suffix; switch (unit) { case DIGIT_UNIT_BYTE: { sprintf (str, "%lld%s", n, "B"); break; } case DIGIT_UNIT_KILOBYTE: { f = (float) n / KILOBYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "K"); break; } case DIGIT_UNIT_MEGABYTE: { f = (float) n / MEGABYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "M"); break; } case DIGIT_UNIT_GIGABYTE: { f = (float) n / GIGABYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "G"); break; } case DIGIT_UNIT_TERABYTE: { f = (float) n / TERABYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "T"); break; } case DIGIT_UNIT_KIBIBYTE: { f = (float) n / KIBIBYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "Ki"); break; } case DIGIT_UNIT_MEBIBYTE: { f = (float) n / MEBIBYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "Mi"); break; } case DIGIT_UNIT_GIBIBYTE: { f = (float) n / GIBIBYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "Gi"); break; } case DIGIT_UNIT_TEBIBYTE: { f = (float) n / TEBIBYTE_SIZE; sprintf (str, "%.1f", f); len = strlen(str); suffix = (*(str + (len - 1)) == '0') ? str + len - 2 : str + len; memset (suffix, 0, 2); sprintf (suffix, "%s", "Ti"); break; } } return str; } static char * unit_format (long long n, Base base) { DigitUnit unit = DIGIT_UNIT_BYTE - 1; long long tmp = n; if (base == BASE_DECIMAL) { while (tmp > 0) { tmp /= 1000; unit++; } } else if (base == BASE_BINARY) { while (tmp > 0) { tmp /= 1024; unit++; if (unit == DIGIT_UNIT_KILOBYTE) { unit = DIGIT_UNIT_KIBIBYTE; } } } return unit_format_custom (n, unit); } int main(int argc, char **argv) { printf ("%s\n", unit_format_custom (25678, DIGIT_UNIT_KILOBYTE)); printf ("%s\n", unit_format (4096, BASE_BINARY)); printf ("%s\n", unit_format (4096, BASE_DECIMAL)); printf ("%s\n", unit_format (8192, BASE_BINARY)); printf ("%s\n", unit_format (8192, BASE_DECIMAL)); return 0; }