意义何在
这个东西有什么用呢 就是你在进行Win32API编程的时候,你写的 WinMain (wWinMain)函数它传入的可不是 argc 和 argv ,是一整个的 LPSTR lpCmdLine (或者LPWSTR)。
那么,怎么优雅地解析这个 lpCmdLine 呢?(支持 Unicode)
下面给出一种解决方案。
注:该库仍不完善,示例也没有覆盖到所有的可能情况,它甚至连启用 CaseInsensitive 都不支持。但是这是一个 “活跃” 的项目,所以会尽快完善。
主体介绍
主要思路:定义一个优雅的 StringList 类,通过 std::stringstream 进行参数的分割,然后就可以优雅的用 string::find 一样的代码进行参数解析了 :P
更新
V1 (2023-05-04) 仅 StringList 库部分代码 实现基础解析
V2 自己在改Bug和兼容性 没有上传
代码部分
stringlist.h
#pragma once
#include <string>
#include <sstream>
#include <vector>
namespace std {
template <typename _tcType>
class _tagStringList {
using _tagString = std::basic_string<_tcType, std::char_traits<_tcType>, std::allocator<_tcType>>;
using _tagStringStream = std::basic_stringstream<_tcType, std::char_traits<_tcType>, std::allocator<_tcType>>;
private:
public:
static const size_t npos = -1;
struct size_t_d {
size_t a, b;
size_t_d(){};
size_t_d(size_t _a,size_t _b):a(_a),b(_b){}
};
std::vector<_tagString> list;
_tagStringList(_tagString __Source) {
if (!__Source.empty()) {
_tagStringStream slstr; _tagString tmpstr;
slstr << __Source;
while (slstr >> tmpstr) {
list.push_back(tmpstr);
}
}
}
size_t findItem(string _item, size_t beginItem = 0) {
for(size_t i = 0; i < list.size(); i++) {
if(list[i]==_item) return i;
}
return npos;
}
size_t_d findItemContent(string _itemc, size_t beginItem = 0, size_t beginContent = 0) {
size_t lsp;
for(size_t i = 0; i < list.size(); i++) {
if((lsp = list[i].find(_itemc, beginContent)) != _tagString::npos) return size_t_d(i, lsp);
}
return size_t_d(npos, npos);
}
inline size_t size() { return list.size(); }
inline _tagString operator [] (size_t pos) { return list[pos]; }
inline _tagString at(size_t pos) { return list.at(pos); }
using iterator = typename::std::vector<_tagString>::iterator;
inline iterator begin() { return list.begin(); }
inline iterator end() { return list.end(); }
};
using StringList = _tagStringList<char>;
using wStringList = _tagStringList<wchar_t>;
} //namespace std
//local clear
#undef _tagString
#undef _tagStringStream
paramparser.h
// 还没完全实现 先不放了
使用示例
#include <windows.h>
#include <string>
#include <stdio.h>
#include "stringlist.h"
using namespace std;
#define USER_DEFINED_HELP_DOCUMENT "[HELP NOT INCLUDED]"
int ReadConfig(string Filename = "") {
///TODO: Read your config here.
/*
FILE *pf;
if (Filename.empty()) fopen_s(&pf, "scuconfig", "rb");
else fopen_s(&pf, Filename.c_str(), "rb");
if (pf == NULL) return false; //Doesn't have a config file.
//fread_s(&UserSettings, sizeof(UserSettings), sizeof(UserSettings), 1, pf);
fread(&UserSettings, sizeof(UserSettings), 1, pf);
return true;*/
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
string strCmdLine(lpCmdLine); //convert LPSTR to string.
if (strCmdLine.empty()) { //if no parameters got...
///TODO: do anything you want!!!
} else { //Ohh, user wants to do something.
StringList arglist(strCmdLine);
size_t posbuf;
//If user is asking for help ducument
if (arglist.findItem("-h")!=StringList::npos) {
printf("%s", USER_DEFINED_HELP_DOCUMENT);
return 0;
}
//If user specify config file.
if ((posbuf=arglist.findItem("-c"))!=StringList::npos) ReadConfig(arglist[posbuf]);
else ReadConfig(); //read default config.
//If user enables debug mode.
//This parameter can use with no suffix, or with one suffix.
if ((posbuf=arglist.findItem("-debug"))!=StringList::npos) {
//UserSettings.debug = true;
printf("Debug mode enabled: ");
if (arglist.size()>posbuf+1) {
int debugLevel_temp;
debugLevel_temp = atoi(arglist.at(posbuf+1).c_str());
if(debugLevel_temp&&debugLevel_temp<=4) ; //UserSettings.debugLevel = debugLevel_temp;
printf("level %d", debugLevel_temp);
}
printf("\n");
}
//With a string
if ((posbuf=arglist.findItem("-w"))!=StringList::npos) {
if (arglist.size()>posbuf+1) {
///TODO: just storage arglist.at(posbuf+1);
string mystring = arglist.at(posbuf+1);
}
}
//Default parameter
if ((posbuf=arglist.findItem("-os"))!=StringList::npos) {
string mystring;
if (arglist.size()>posbuf+1) {
mystring = arglist.at(posbuf+1);
} else mystring = string("Default value!");
}
//With a number
if ((posbuf=arglist.findItem("-es"))!=StringList::npos) {
if (arglist.size()>posbuf+1) {
int tmp; tmp = atoi(arglist.at(posbuf+1).c_str());
///TODO: Check if atoi runs into errors, then Storage tmp!
} else { //If it is a must
printf("argument \"-es\" must be followed by an integer!\n");
return 1;
}
}
}
//anything else?
return 0;
}
使用 tdm-gcc 10.3.0 如下命令可以正常编译:
gcc -o test.exe test.cpp -std=c++11 -lstdc++