Learn how to write a small C program that converts memory units to be human readable. main image

Table of contents

Why

Sometimes you may need to convert a large number of bytes that was produced by your program into the appropriate human readable format. For example 297719372 bytes. For human eyes, it is easier to understand 298MB.

Here’s a quick code snippet for you, in case you want to convert your data to human readable format. We’ll do this in C, but you can understand the algorithm and convert it to your preferred language:

How

Importing header files.

#include <stdio.h> 
#include <stdlib.h> // atoll
#include <stdint.h> // uint64_t
#include <inttypes.h> // PRIu64

What are header files?

Header files are used to import the functions and variables that you can use in your program.

  • stdio.h is used to import the functions that are used to read and write data to the console.
  • stdlib.h is used to import the functions for general purposes.
  • stdint.h defines integer types, limits of specified width integer types, limits of other integer types and macros for integer constant expressions.
  • inttypes.h defines macros for printing integers in format that is suitable for the given width.

Define the conversion function.

static const char *human_size(uint64_t bytes_to_convert)
{
	// This function takes an integer as argument and returns a string.
}

Lets add the memory units.

static const char *human_size(uint64_t bytes_to_convert)
{
	char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
}

We need to calculate the length of the suffix array. In this case it is 5, but we’ll leave it this way so you can add more suffixes.

static const char *human_size(uint64_t bytes_to_convert)
{
	char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
	char length = sizeof(suffix) / sizeof(suffix[0]);
}

Now we need to make a loop to calculate the appropriate size.

static const char *human_size(uint64_t bytes_to_convert)
{
	char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
	char length = sizeof(suffix) / sizeof(suffix[0]);

	int i = 0;
	double dblBytes = bytes_to_convert;

	if (bytes_to_convert > 1024) {
		for (i = 0; (bytes_to_convert / 1024) > 0 && i<length-1; i++, bytes_to_convert /= 1024)
			dblBytes = bytes_to_convert / 1024.0;
	}
}

Finally, we output the result.

static const char *human_size(uint64_t bytes_to_convert)
{
	char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
	char length = sizeof(suffix) / sizeof(suffix[0]);

	int i = 0;
	double dblBytes = bytes_to_convert;

	if (bytes_to_convert > 1024) {
		for (i = 0; (bytes_to_convert / 1024) > 0 && i<length-1; i++, bytes_to_convert /= 1024)
			dblBytes = bytes_to_convert / 1024.0;
	}

	static char output[200];
	sprintf(output, "%.02lf %s", dblBytes, suffix[i]);
	return output;
}

Define main function.

The main() function is the first thing gets called when you execute your program.

Here we want to check user command line arguments for the number of bytes to convert. If the user didn’t provide any arguments, it’ll return an error.

int main(int argc, char **argv)
{
	if (argc == 1) {
		fprintf(stderr, "Usage: %s <bytes>\n", *argv);
		return 1;
	}

	uint64_t bytes = atoll(argv[1]);

	printf("%" PRIu64 " Bytes: %s\n", bytes, human_size(bytes));

	return 0;
}

Now we need to convert the command line arguments to a number using the atoll function which converts string to an integer.

int main(int argc, char **argv)
{
	if (argc == 1) {
		fprintf(stderr, "Usage: %s <bytes>\n", *argv);
		return 1;
	}

	uint64_t bytes = atoll(argv[1]);

	printf("%" PRIu64 " Bytes: %s\n", bytes, human_size(bytes));

	return 0;
}

Finally, we call the human_size function to convert the number of bytes to human readable format.

int main(int argc, char **argv)
{
	if (argc == 1) {
		fprintf(stderr, "Usage: %s <bytes>\n", *argv);
		return 1;
	}

	uint64_t bytes = atoll(argv[1]);

	printf("%" PRIu64 " Bytes: %s\n", bytes, human_size(bytes));

	return 0;
}

Full program

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

static const char *human_size(uint64_t bytes_to_convert)
{
  char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
  char length = sizeof(suffix) / sizeof(suffix[0]);

  printf("%d\n", length);

  int i = 0;
  double double_bytes = bytes_to_convert;

  if (bytes_to_convert > 1024)
  {
    for (i = 0; (bytes_to_convert / 1024) > 0 && i < length - 1; i++, bytes_to_convert /= 1024)
      double_bytes = bytes_to_convert / 1024.0;
  }

  static char output[200];
  sprintf(output, "%.02lf %s", double_bytes, suffix[i]);
  return output;
}

int main(int argc, char **argv)
{
  if (argc == 1)
  {
    fprintf(stderr, "Usage: %s <bytes>\n", *argv);
    return 1;
  }

  uint64_t bytes = atoll(argv[1]);

  printf("%" PRIu64 " Bytes: %s\n", bytes, human_size(bytes));

  return 0;
}

Conclusion

In this tutorial, we learned how to convert a number of bytes to a human readable format with a simple function.

We also learned how to handle command line arguments.

Related topics