我正在尝试创建CLI(命令行界面)。我现在还不知道我想从它那里得到什么。
注意:当我使用带有散列字符串的switch-case语句来运行命令时,错误开始出现。此外,编译时也不会出现错误。错误可能从任何地方开始,因为我使用printf在cli运行时打印一条表示argc和argv的消息。
下面是我使用的代码:codeycat.cpp
#include <map>
#include <iostream>
using namespace std;
static enum Functions {
undef,
comm_test,
comm_commands
} functions;
static map<string, Functions> mapStringValues;
static void Initialize();
bool samestr(const char *svar, const char *str)
{
if (strcmp(svar, str) == 0)
{
return true;
}
else
{
return false;
}
}
string construct_version(int major, int minor, int patch)
{
string strmajor = to_string(major);
string strminor = to_string(minor);
string strpatch = to_string(patch);
string version = strmajor + "." + strminor + "." + strpatch;
return version;
}
int test(string command)
{
int code = system(command.c_str());
return code;
}
void commands()
{
printf("(test, commands)n");
}
int main(int argc, char *argv[])
{
string doc = "Usage: codeycat [options...] [function] [args...]n"
"Options:n"
"t--help -h: Show this message and exitn"
"t--version -v: Show version and exitn";
string version = construct_version(1, 0, 0);
printf("arg count: %d, args: %s %s %s", argc, argv[0], argv[1], argv[2]);
if (argc < 2)
{
printf("%s", doc.c_str());
return 1;
}
const char command[PATH_MAX] = {*argv[2]};
switch (mapStringValues[command])
{
case undef:
printf("Command not found: %s", command);
case comm_test:
test(argv[3]);
case comm_commands:
cout << "Hello" << endl;
// commands();
}
return 0;
}
void Initialize()
{
mapStringValues["undef"] = undef;
mapStringValues["test"] = comm_test;
mapStringValues["commands"] = comm_commands;
}
运行% ./codeycat
当然返回返回码1(错误),但运行% ./codeycat
与选项--help
,--version
,-h
,-v
或运行其功能不工作。
输出如下:
./codeycat
arg count: 1, args: ./codeycat (null) COLORTERM=truecolorUsage: codeycat [options...] [function] [args...]
Options:
--help -h: Show this message and exit
--version -v: Show version and exit
./codeycat --help
[1] 12372 segmentation fault ./codeycat --help
./codeycat -h
[1] 12416 segmentation fault ./codeycat -h
./codeycat --version
[1] 12459 segmentation fault ./codeycat --version
./codeycat -v
[1] 12501 segmentation fault ./codeycat -v
./codeycat test 'echo Hello'
[1] 12544 segmentation fault ./codeycat test 'echo Hello'
./codeycat commands
[1] 12587 segmentation fault ./codeycat commands
如果不先检查argc,就不能从argv中读取。Argv是一个长度为argc的数组,所以任何大于等于argc的索引都是越界的。这条线
printf("arg count: %d, args: %s %s %s", argc, argv[0], argv[1], argv[2]);
不会崩溃,因为一些printf实现打印"(null)"如果将空指针传递给%s说明符。当你不传递任何参数时,你提前返回,因为argc是1,你打印文档并返回1。
然而,当你传递一个参数时,你没有提前返回,这意味着你到达了这一行
const char command[PATH_MAX] = {*argv[2]};
这会崩溃,因为当argc小于2时,您正在读取argv[2]。如果你传递了两个CLI参数,这一行不会崩溃。此外,这不会创建一个字符串,而是创建一个大小为PATH_MAX的数组,其中元素0是argv[2]的第一个字符。如果你想用argv[2]索引mapStringValues,你需要创建一个std::string。另外,argv[2]是第二个参数,所以如果您希望第一个参数是命令(通常是这种情况),那么您应该从argv[1]中读取。
string command = argv[1];
Switch语句的大小写不会自动断开,这意味着在"case undef:"结尾,您将输入"case comm_test"。
switch (mapStringValues[command])
{
case undef:
printf("Command not found: %s", command);
// this will fall through to case comm_test,
case comm_test:
test(argv[3]);
case comm_commands:
cout << "Hello" << endl;
// commands();
}
即使初始情况为undef,也会调用test(argv[3])。您需要添加break语句,以防止大小写通过
掉落。switch (mapStringValues[command])
{
case undef:
printf("Command not found: %s", command);
// add break to prevent fallthrough
break;
case comm_test:
test(argv[3]);
break;
case comm_commands:
cout << "Hello" << endl;
break;
// commands();
}
最后,您从未调用Initialize(),因此映射始终为空,这意味着每个命令都将导致无法找到。您需要调用Initialize()函数来初始化映射