我有一个用C编写的shell程序,当我试图运行命令"ls |"(只是ls和一个管道,后面没有任何东西)时,我的程序永远循环。你可以忽略modePtr…这个解析器所做的是从用户输入中获取一串字符,所以它正在解析命令"ls |",我猜问题在于没有一个空管道命令会落入的"case",从而导致无限循环?有什么建议吗?
int parse(char *inputString, char *cmdArgv[], char **supplementPtr, int *modePtr)
{
int cmdArgc = 0, terminate = 0;
char *srcPtr = inputString;
//printf("parse fun%sends", inputString);
while(*srcPtr != ' ' && terminate == 0)
{
*cmdArgv = srcPtr;
cmdArgc++;
//printf("parse fun2%sends", *cmdArgv);
while(*srcPtr != ' ' && *srcPtr != 't' && *srcPtr != ' ' && *srcPtr != 'n' && terminate == 0)
{
// Handles redirection/pipes
switch(*srcPtr)
{
// Background mode
case '&':
*modePtr = BACKGROUND;
break;
// Output mode
case '>':
*modePtr = OUTPUT_REDIRECTION;
*cmdArgv = ' ';
srcPtr++;
if(*srcPtr == '>')
{
*modePtr = OUTPUT_APP;
srcPtr++;
}
while(*srcPtr == ' ' || *srcPtr == 't' || *srcPtr == ' ')
srcPtr++;
*supplementPtr = srcPtr;
chop(*supplementPtr);
terminate = 1;
break;
// Input mode
case '<':
*modePtr = INPUT_REDIRECTION;
*cmdArgv = ' ';
srcPtr++;
while(*srcPtr == ' ' || *srcPtr == 't' || *srcPtr == ' ')
srcPtr++;
*supplementPtr = srcPtr;
chop(*supplementPtr);
terminate = 1;
break;
// Pipe mode
case '|':
*modePtr = PIPELINE;
*cmdArgv = ' ';
srcPtr++;
while(*srcPtr == ' ' || *srcPtr == 't' || *srcPtr == ' ')
srcPtr++;
*supplementPtr = srcPtr;
//chop(*supplementPtr);
terminate = 1;
break;
}
srcPtr++;
}
// Process commands when these occur
while((*srcPtr == ' ' || *srcPtr == 't' || *srcPtr == 'n') && terminate == 0)
{
*srcPtr = ' ';
srcPtr++;
}
cmdArgv++;
}
/*srcPtr++;
*srcPtr = ' ';
destPtr--;*/
*cmdArgv = ' ';
return cmdArgc;
}
你可能把问题弄得太复杂了。如果你想让程序读取通过管道传输的列表项…
#define MAXLINELEN 1000
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char line[MAXLINELEN];
FILE *fpin;
fpin=stdin;
while(fgets(line,MAXLINELEN,fpin)!=NULL) printf("%s",line);
}
…然后可以使用strtok()解析每行上的项,或者如果使用"ls -1",则每个列表项无论如何都在唯一的行上。
如果您在普通shell中尝试ls |
,在尝试启动任何操作之前,它将提示您执行管道的其余部分(另一个命令)。没有命令读取输出的管道是无意义的。
这个习惯用法(在代码中重复几次)被打破了:
srcPtr++;
while (*srcPtr == ' ' || *srcPtr == 't' || *srcPtr == ' ')
srcPtr++;
您不能跳过字符串末尾的空' '
!你会立刻陷入"未定义行为"。您需要检查循环逻辑,可能是:
srcPtr++;
while (*srcPtr == ' ' || *srcPtr == 't')
srcPtr++;
if (*srcPtr == ' ')
...no more data in string...