我正在学习C.对于课堂练习,我尝试使用if... else if... else...
语句将冗长的switch
块转换为更高效的C代码。有两个问题:
/
或-
的支持,并且还必须支持/c
,/c.abc
的可变长度,其中.
和任何内容以下是可选的。char *argv[]
可以接受unix文件路径。现有的块看起来像这样:
#include <strings.h>
int main(int argc, char* argv[])
{
int i;
for (i=1; i<argc; i++)
{
if (!strcasecmp(argv[i], "/a") || !strcasecmp(argv[i], "-a"))
/* Do something */
else if (!strcasecmp(argv[i], "/b") || !strcasecmp(argv[i], "-b"))
/* Do something */
else if (!strncasecmp(argv[i], "/c", 2) || !strncasecmp(argv[i], "-c", 2))
/* Do something */
else if (!strcasecmp(argv[i], "/d") || !strcasecmp(argv[i], "-d"))
/* Do something */
else if ((argv[i][0] == '/' || argv[i][0] == '-') && (!argv[i][2] || argv[i][2] == '.'))
{
/* Error message */
return 1;
}
else
{
/* For unix filepaths. */
}
return 0;
}
我最初的想法是在switch
上使用argv[i][1]
来避免/
或-
问题。例如:
if ((argv[i][0] == '/' || argv[i][0] == '-') && (!argv[i][2] || argv[i][2] == '.'))
{
switch(argv[i][1])
{
case 'a':
/* Do something */
break;
case 'b':
/* Do something */
break;
case 'c':
/* Do something and process any characters after the . */
break;
case 'd':
/* Do something */
break;
default:
/* Error message */
return 1;
}
}
else
{
/* Unix filepaths and anything else. */
}
到目前为止,switch
完成了大部分任务。不幸的是,声明if ((argv[i][0] == '/' || argv[i][0] == '-') && (!argv[i][2] || argv[i][2] == '.'))
也会接受无效的标记,例如/a.
。
从/c
移除可变长度的案例(例如/c.abc
或switch
)是另一种可能性,但后来我不确定如何确保其他案例有字符串长度为两个字符,但不接受/c
有效。
是否有更好或更有效的方法将if... else if... else...
块转换为switch
?
感谢任何帮助。
答案 0 :(得分:0)
可以通过一次仅考虑argv[i]
的一个字符来完成:
#include <strings.h>
int main(int argc, char* argv[])
{
int i;
for (i=1; i<argc; i++)
{
switch(argv[i][0])
{
case '/':
case '-':
switch(argv[i][1])
{
case '\0':
/* No further characters in argv[i]; Do something? Print error? */
/* As per suggestion of @Mohit Jain. */
break;
case 'a':
/* Do something */;
break;
case 'b':
/* Do something */;
break;
case 'c':
/* Do something */;
break;
case 'd':
/* Do something */;
break;
default:
if(!argv[i][2] || ('.' == argv[i][2])) // a little danger here...
{
/* Error message */
return 1;
}
else
{
/* For unix filepaths. */
}
break;
}
break;
default:
/* Error message */
return 1;
}
}
return 0;
}
答案 1 :(得分:0)
在你的用例中,我不认为你会通过拥有来节省很多工作 一个开关,特别是当你添加错误处理
时首先尝试将工作分解为功能以使您的主要功能 更具可读性
执行一个检查语法的函数,例如
int syntaxOk(char* arg)
{
if ( (strlen(arg) < 2) // too short
|| (arg[0] != '-' && arg[0] != '/') // invalid format
{
printSyntax();
return 0;
}
return 1;
}
和一个写可用语法的函数
void printSyntax()
{ ... }
在你的主要文件中,有一个参数的ptr,使其更具可读性:
char* arg = argv[i];
现在将实际命令char转换为小写(ctype.h)
int ch = tolower( arg[1] );
您可能需要提取可选的变长命令 所以有一个缓冲区我们可以把它放在那里,比如在&#39; c&#39;所以 一个功能
int doC(char* argv)
{
size_t len = strlen(argv);
if ( len > 2 && arg[2] == '.' )
{
char cOption[64] = {0};
strncpy(cOption, arg + 3, sizeof(cOption));
// do something
return 1;
}
else if ( len == 2 )
{
// do something else?
return 1;
}
else
{
printSyntax();
return 0;
}
}
你可以动态地使cOption取决于参数的大小,但我留给你试试。例如char* cOption = malloc(len+1);
而不是固定大小或取决于您的编译器版本,您可以使用可变大小的数组。
然后你的switch语句看起来像这样:
switch (ch)
{
case 'a':
doA();
break;
case 'b':
doB();
break;
case 'c':
if (!doC(argv))
{
printSyntax();
}
break;
case 'd':
doD();
break;
default:
printSyntax();
break;
}