Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解析C中的命令行条目:实现shell_C_Shell_Command Line_Command Line Arguments - Fatal编程技术网

解析C中的命令行条目:实现shell

解析C中的命令行条目:实现shell,c,shell,command-line,command-line-arguments,C,Shell,Command Line,Command Line Arguments,我正在用C实现一个shell,在解析命令行条目时遇到了一些问题。我希望我的解析器方法分离由空格字符分隔的命令行条目,并将结果作为双字符指针返回。也就是说,假设我有“ls-l>ls.txt”,我的解析器应该返回一个字符**r,其中r[0]=“ls”、r[1]=“l”和r[2]=“ls.txt” 下面是我当前解析方法的代码,顺便说一下,这是segfaulting,我不知道如何修复它: char **parser(int *argc, char *s) { char **r;

我正在用C实现一个shell,在解析命令行条目时遇到了一些问题。我希望我的解析器方法分离由空格字符分隔的命令行条目,并将结果作为双字符指针返回。也就是说,假设我有“ls-l>ls.txt”,我的解析器应该返回一个字符**r,其中r[0]=“ls”、r[1]=“l”和r[2]=“ls.txt”

下面是我当前解析方法的代码,顺便说一下,这是segfaulting,我不知道如何修复它:

 char **parser(int *argc, char *s)
 {
     char **r;
     char *t, *m;
     int i,n,size;

     t = malloc(strlen(s)); // firs i used this instead of *r, but i run 
                            // into trouble when i have more than two
                            // argc. ( You see why, right?)
    //strcpy(t,s);
    i = 0;
    size = 5;
    r = malloc(size*sizeof(char *));
    while (( m = strchr(s, ' '))) {
        n = ((int)m) - ((int)s);
        if (i==0) {
          *r = malloc(n);
        } else {
           *r = realloc(*r, n);
        }
        strncpy(*r, s, n);
        *r[n]= '\0';
        s = (char*)(s+n+1);
        if (i == size)
            r = realloc(r, (size = 2*size)*sizeof(char*));
        i++;
        r = (char **)(r + sizeof(char*));
   }

   s[strlen(s)-1] = '\0';
   if ((i<1) || (strlen(s)>1)) {
       *r = s;
   }
   *argcp = ++i;
   return r;
}
char**解析器(int*argc,char*s)
{
字符**r;
字符*t,*m;
int i,n,大小;
t=malloc(strlen(s));//首先我用这个代替了*r,但我运行
//当我有两个以上的时候就有麻烦了
//你明白为什么了吧
//strcpy(t,s);
i=0;
尺寸=5;
r=malloc(大小*大小*字符*);
而((m=strchr,,)){
n=((int)m)-(int)s);
如果(i==0){
*r=malloc(n);
}否则{
*r=realloc(*r,n);
}
strncpy(*r,s,n);
*r[n]='\0';
s=(字符*)(s+n+1);
如果(i==大小)
r=realloc(r,(size=2*size)*sizeof(char*);
i++;
r=(字符**)(r+sizeof(字符*);
}
s[strlen(s)-1]='\0';
如果((i1)){
*r=s;
}
*argcp=++i;
返回r;
}
我知道我的代码并不理想。使用strep可以做得更好,但我主要关心的是如何为我想要返回的双字符指针管理内存

谢谢你的帮助

这是一个快速的尝试

我的C生锈了,所有的铰链都卡住了,所以

前提是您将得到一个指向指针数组的指针。然而,在指针列表末尾的关键细节是参数数据本身。因此,完成后,只需释放返回的指针

未经测试。潜入这里很可能是一次性的错误

编辑,我编译并快速测试了它

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


char **parser(int *argc, char *s) {
    char **r, **rp;
    char *t, *p, *w;
    void *vp;
    int l;

    l = strlen(s); // size of cmd line
    vp = malloc(l + (*argc * sizeof(char *))); // total buffer size
    t = (char *)(vp + (*argc * sizeof(char *))); // offset into buffer for argument copy
    r = (char **)vp;  // start of buffer, start of pointer array to arguments
    strcpy(t, s);  // copy arguments in to buffer
    p = t;  // parsing pointer
    w = t;  // word pointer for each argument
    rp = r;  // storage for first pointer

    while(*p) {  // while not at end of string
        if (*p == ' ') {  // if we find a space
            if (w) {  // if we have a word pointer assigned
                *rp++ = w;  // store the word pointer
                w = NULL;  // set word pointer to null
                *p = '\0';  // terminate argument with a 0
            } // else do nothing continue to skip spaces
        } else {
            if (w == NULL) {  // If we haven't got a new arg yet
                w = p;  // set it
            }  // otherwise, just keep scanning
        }
        p++;  // move along the string
    }
    if (w) {  // clean up at the end if we have an arg
        *rp++ = w;
        w = NULL;  // no reason to set 0 at the end, it's already there from strcpy
    }

    return r;
}

int main() {
    char *cmd = "arg1 arg2";
    int argc = 2;

    char **r = parser(&argc, cmd);

    printf("%s\n",r[0]);
    printf("%s\n",r[1]);
}
#包括
#包括
#包括
字符**解析器(int*argc,char*s){
字符**r,**rp;
字符*t,*p,*w;
void*vp;
int l;
l=strlen(s);//命令行的大小
vp=malloc(l+(*argc*sizeof(char*));//缓冲区总大小
t=(char*)(vp+(*argc*sizeof(char*));//偏移到缓冲区以进行参数复制
r=(char**)vp;//缓冲区的开始,指向参数的指针数组的开始
strcpy(t,s);//将参数复制到缓冲区
p=t;//解析指针
w=t;//每个参数的单词指针
rp=r;//第一个指针的存储
while(*p){//while不在字符串末尾
如果(*p=''){//如果我们找到一个空间
if(w){//如果我们分配了一个单词指针
*rp++=w;//存储单词指针
w=NULL;//将单词指针设置为NULL
*p='\0';//用0终止参数
}//否则不执行任何操作继续跳过空格
}否则{
如果(w==NULL){//如果我们还没有新的参数
w=p;//设置它
}//否则,继续扫描
}
p++;//沿字符串移动
}
如果(w){//如果我们有一个arg,请在末尾清理
*rp++=w;
w=NULL;//没有理由在末尾设置0,它已经在strcpy中了
}
返回r;
}
int main(){
char*cmd=“arg1 arg2”;
int argc=2;
char**r=parser(&argc,cmd);
printf(“%s\n”,r[0]);
printf(“%s\n”,r[1]);
}

注意,在普通shell中,您可以编写
>文件
>文件
,并将标准输出重定向到
文件
。您还可以编写
ls-l | wc-l
ls-l | wc-l
(或混合匹配管道符号周围的间距。也就是说,大多数外壳在有空白的地方都非常灵活。(事实上,
>文件ls-l
ls-l
的输出发送到
文件;
ls>文件-l
!)在表示方面,如果代码有系统地缩进,您的代码将更易于阅读,并且不会沉迷于像
if(…)这样的无端技巧a=…;
全部放在一行上。这只会使你的代码很难阅读。如果你需要帮助,你要确保你的代码易于其他人阅读。这行代码中有很多麻烦
n=((int)m)-(int)s);If(i==0){*r=malloc(n);}else{*r=realloc(*r,n);}
第一行应该是
n=(int)(m-s);
(或者可以省略强制转换)。在
r
malloc()
realloc()
的空格应该是
char*
值的数组(这就是为什么使用
char**r
来声明它)。分配的空间需要是
char*
值的数量,大小需要按
sizeof(*r)
进行缩放。然后,字符串处理会出现严重的管理错误。是时候从第一原则开始重做了。感谢您的第一条评论!我现在就要在解析器中修复它!您需要一个(不断增长的)
char*
值数组,由
char**
指向(因此
r
可以作为变量定义)。对于数组中的每个条目,您需要一个足够长的字符串加上一个空终止符。该字符串将由
r
数组中的一个条目指向:
r[i]=malloc(strlen(str)+1);
或类似。或者,最好使用或实现
strdup()