栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

命令行参数解析(c++17)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

命令行参数解析(c++17)

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class CommandLine 
{
public:
	// the possible variables the options may point to
	typedef std::variant Value;

	struct Argument
	{
		std::vector options_;
		Value                    value_;
		std::string              desc_;
	};

public:
	explicit CommandLine() = default;

	// adds a possible option
	void Add(std::vector const& opts, Value const& value, std::string const& desc)
	{
		args_.emplace_back( Argument{ opts, value, desc } );
	}

	void PrintHelp(std::ostream& os = std::cout) const
	{
		const auto maxOptionLength = MaxOptionsLength();
	
		for (auto const& arg : args_) 
		{
			std::string opts;
			
			for (auto const& opt : arg.options_)
				opts += opt + ", ";
	
			// Remove last comma and space and add padding for alignment
			std::stringstream sstr;
			sstr << std::left << std::setw(maxOptionLength) << opts.substr(0, opts.size() - 2);
			
			// Print each argument. Do line wrapping for long descriptions.
			size_t spacePos = 0;
			size_t lineWidth = 0;
			
			while (spacePos != std::string::npos) 
			{
				size_t nextspacePos = arg.desc_.find_first_of(' ', spacePos + 1);
				sstr << arg.desc_.substr(spacePos, nextspacePos - spacePos);
				lineWidth += nextspacePos - spacePos;
				spacePos = nextspacePos;
				
				if (lineWidth > 60) 
				{
					os << sstr.str() << std::endl;
					sstr = std::stringstream();
					sstr << std::left << std::setw(maxOptionLength - 1) << " ";
					lineWidth = 0;
				}
			}
		}
	}

	// if an option is set multiple times, the last one will be finally used. 
	// Unknown flags will cause a warning on std::cerr.
	void Parse(int argc, char* argv[]) const
	{
		// Skip the first argument (name of the program).
		int i = 1;
		
		while (i < argc) 
		{
			// First we have to identify whether the value is separated by a space or a '='.
			std::string flag(argv[i]);
			std::string value;
			bool valueIsSeparate = false;

			// If there is an '=' in the flag, the part after the '=' is actually the value.
			size_t equalPos = flag.find('=');
			
			if (equalPos != std::string::npos) 
			{
				value = flag.substr(equalPos + 1);
				flag = flag.substr(0, equalPos);
			}
			else if (i + 1 < argc)  // Else the following argument is the value.
			{
				value = argv[i + 1];
				valueIsSeparate = true;
			}

			// Search for an argument with the provided flag.
			bool foundArgument = false;
			
			for (auto const& argument : args_) 
			{
				if (std::find(argument.options_.begin(), argument.options_.end(), flag) != std::end(argument.options_)) 
				{
					foundArgument = true;

					// In the case of booleans, there must not be a value present
					if (std::holds_alternative(argument.value_)) 
					{
						if (!value.empty() && value != "true" && value != "false") 
						{
							valueIsSeparate = false;
						}

						*std::get(argument.value_) = (value != "false");
					}
					// In all other cases there must be a value.
					else if (value.empty()) 
					{
						throw std::runtime_error("Failed to parse command line arguments: Missing value for argument "" + flag + ""!");
					}
					// For a std::string, we take the entire value.
					else if (std::holds_alternative(argument.value_)) 
					{
						*std::get(argument.value_) = value;
					}
					// In all other cases we use a std::stringstream to convert the value.
					else  
					{
						std::visit([&value](auto&& arg) {
						  std::stringstream sstr(value);
						  sstr >> *arg; 
						}, argument.value_);
					}

					break;
				}
			}

			// Print a warning if there was an unknown argument.
			if (!foundArgument)
				std::cerr << "Ignoring unknown command line argument "" << flag << ""." << std::endl;

			// Advance to the next flag.
			++i;

			// If the value was separated, we have to advance our index once more.
			if (foundArgument && valueIsSeparate)
				++i;
		}
	}

private:
	// for alignment : Find the argument with the longest combined option length
	uint32_t MaxOptionsLength(void) const
	{
		constexpr auto COMMA_LENGTH = 1U;
		constexpr auto SPACE_LENTH = 1U;
		uint32_t max_len = 0;

		for (auto const& arg : args_)
		{
			uint32_t len = 0;

			for (auto const& opt : arg.options_)
			{
				len += static_cast(opt.size()) + COMMA_LENGTH + SPACE_LENTH;
			}

			max_len = std::max(max_len, len);
		}

		return max_len;
	}

 private:
	std::vector args_;

使用


public:
	void Test(int argc, char* argv[]) const
	{
		std::string usr = "";
		std::string pwd = "";
		std::string code = "";
		
		bool do_auth = false;
		bool print_help = false;

		CommandLine args;
		args.Add({ "-u", "--user" },			&usr, "");
		args.Add({ "-p", "--password" },		&pwd, "");
		args.Add({ "-c", "--code" },			&code, "security code");
		args.Add({ "-a", "--auth" },			&do_auth, "authenticate");
		args.Add({ "-h", "--help" },			&print_help, "Help");

		try
		{
			args.Parse(argc, argv);
		}
		catch (std::runtime_error const& e)
		{
			std::cout << e.what() << std::endl;
			return;
		}

		if (print_help)
		{
			args.PrintHelp();
			return;
		}

		std::cout
			<< "usr : " << usr << std::endl
			<< "pwd : " << pwd << std::endl
			<< "code : " << code << std::endl
			<< "auth: " << do_auth << std::endl
			<< "print help : " << print_help << std::endl;
	}
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/702771.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号