Archive

Posts Tagged ‘parsing’

Parsing command line arguments in C++

March 17, 2019 4 comments

One of the things which have frustrated me since I first started programming has been the difficulty in using command line arguments provided to one’s application. Everyone of us is aware of the standard formulation of the main function:

int main(int argc, char** argv);

Here argc is the number of arguments (separated by spaces), including the name of the application binary itself. Then argv is an array of C-style strings, each containing an argument. This leads to the most commonly used style of categorising the arguments:

app.exe -h --long argument_text

What annoyed me all these years is not having a built-in way to parse command line arguments in C++. Sure, there’s the getopt [2] way if one uses Linux or a similar OS. There are a range of argument parser libs or APIs in frameworks, such as gflags [3], Boost Program Options [4], POCO [5], Qt [6] and many others.

What these do not provide is a simple, zero-dependency way to add argument parsing to C++, while also being as uncomplicated as possible. This led me to put together a simple command line argument parsing class, which does exactly what I desire of such an API, without any complications.

Meet Sarge [1] and its integration test application:

#include "../src/sarge.h"

#include 


int main(int argc, char** argv) {
	Sarge sarge;
	
	sarge.setArgument("h", "help", "Get help.", false);
	sarge.setArgument("k", "kittens", "K is for kittens. Everyone needs kittens in their life.", true);
	sarge.setDescription("Sarge command line argument parsing testing app. For demonstration purposes and testing.");
	sarge.setUsage("sarge_test ");
	
	if (!sarge.parseArguments(argc, argv)) {
		std::cerr << "Couldn't parse arguments..." << std::endl;
		return 1;
	}
	
	std::cout << "Number of flags found: " << sarge.flagCount() << std::endl;
	
	if (sarge.exists("help")) {
		sarge.printHelp();
	}
	else {
		std::cout << "No help requested..." << std::endl;
	}
	
	std::string kittens;
	if (sarge.getFlag("kittens", kittens)) {
		std::cout << "Got kittens: " << kittens << std::endl;
	}
	
	return 0;
}

Here one can see most of the Sarge API, with the setting of arguments we are looking for, followed by the application description and usage, as it'll be printed if the user requests the help view or our code decides to print it in the case of missing options or similar.

The Sarge class implementation itself is very basic, using nothing but the STL features, specifically the vector, map, memory, iostream and string headers, in as of writing 136 lines of code.

When asked to parse the command line arguments, it will scan the argument list (argv) for known flags, flags which require a value, and unknown flags. It'll detect unknown flags and missing values, while allowing for short options (single-character) to be chained together.

I'll be using Sarge for my own projects from now on, making additions and tweaks as I see fit. Feel free to have a look and poke at the project as well, and let me know your thoughts.

Maya

[1] https://github.com/MayaPosch/Sarge
[2] https://en.wikipedia.org/wiki/Getopt
[3] https://github.com/gflags/gflags
[4] http://www.boost.org/doc/libs/1_64_0/doc/html/program_options.html
[5] https://pocoproject.org/docs/Poco.Util.OptionProcessor.html
[6] http://qt.io

Categories: C++, Projects Tags: , ,