2012-12-10 31 views
-2

下面的代碼應該可以像shell一樣工作。它具有上一個和下一個選項,歷史功能,退出和執行命令。類Shell程序C

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#define BUFFER_SIZE 256 
#define HISTORY_LENGTH 128 

int executeCommand(char*cmd) 
{ 
    return(!strcmp(cmd,"e\n")); 
} 

int exitCommand(char*cmd) 
{ 
    return (!strcmp(cmd,"exit\n")); 
} 

int previousCommand(char*cmd) 
{ 
    return (!strcmp(cmd,"p\n")); 
} 

int nextCommand(char*cmd) 
{ 
    return (!strcmp(cmd,"n\n")); 
} 

void execute(char *line) 
{ 
    line[strlen(line)-1]='\0'; 
    char **arguments; 
    char* temp; 
    int i=0; 
    arguments=(char**)malloc(sizeof(char)*10); 
    temp=strtok(line," "); 
    arguments[i]=malloc(strlen(temp)*sizeof(char)); 
    if(arguments[i]!=NULL) 
    { 
     strcpy(arguments[i],temp); 
     i++; 
    } 
    else 
    { 
     printf("Out of memory"); 
    } 
    while(temp!=NULL) 
    { 
     temp=strtok(NULL," "); 
     if(temp==NULL){ 
      arguments[i]=NULL; 
     } 
     else{ 
      arguments[i]=malloc(strlen(temp)*sizeof(char)); 
      if(arguments[i]!=NULL) 
      { 
       strcpy(arguments[i],temp); 
       i++; 
      } 
     } 
    } 
    printf("%s ",arguments[0]); 
    printf("%s ",arguments[1]); 
    printf("%s ",arguments[2]); 
    execvp(arguments[0],arguments); 
} 

int main(int argc, char*argV[]) { 
    int i; 
    char *cmd=(char*)malloc(sizeof(char)*BUFFER_SIZE); 
    char **history=NULL; 
    int historylength=0; 
    int currentCommand=0; 
    history=(char**)malloc(sizeof(char)*BUFFER_SIZE); 
    do{ 
     fgets(cmd,BUFFER_SIZE-1,stdin); 
     if(exitCommand(cmd)) 
      break; 
     else 
      if(previousCommand(cmd)) 
      { 
       if(currentCommand>0) 
        printf("%s",history[--currentCommand]); 
       else if(currentCommand==0) 
       { 
        currentCommand=historylength; 
        printf("%s",history[--currentCommand]); 
       } 
      } 
      else 
       if(nextCommand(cmd)) 
       { 
        if(currentCommand<historylength) 
         printf("%s",history[currentCommand++]); 
       } 
       else 
        if(executeCommand(cmd)) 
        { 
         execute(history[--currentCommand]); 
        } 
        else 
        { 
         history[historylength]=malloc(strlen(cmd)*sizeof(char)); 
         if(history[historylength]!=NULL) 
         { 
          strcpy(history[historylength],cmd); 
          currentCommand=++historylength; 
         } 
         else 
         { 
          printf("Out of memory"); 
          break; 
         } 
        } 

    } while(1); 

    free(cmd); 

    for(i=0;i<historylength;i++) 
     free(history[i]); 
    free(history); 

    return 0; 
} 

我想使這個工作的功能貓。我輸入e cat main.c,我期望它執行cat命令,但它沒有做任何事情,我在這裏做錯了什麼?我不是專業人士,所以我感謝所有的幫助。

+0

由於你是C的新手,有一點可以幫助你提高可讀性,那就是使用「else if」而不是其他塊,而在塊中使用if。它會減少你的嵌套層次並使你的代碼更具可讀性。 – RonaldBarzell

+0

我應該爲你的代碼引入一些更好的縮進,因爲你的if/else if結構是非常不可讀的。當你將你的邏輯分解成更小的部分時,找到一個bug也更容易。 – Kylo

回答

3

這是不正確的:

arguments=(char**)malloc(sizeof(char)*10); 

作爲argumentschar**,所以代碼需要分配sizeof(char*)。更改爲:

arguments = malloc(10 * sizeof(*arguments)); 

同樣錯誤爲history也。此外,請參閱Do I cast the result of malloc?

沒有比需要被分配爲char*strcpy()寫入終止空字符少一個char。變化:

arguments[i]=malloc(strlen(temp)*sizeof(char)); 

到:

arguments[i] = malloc(strlen(temp) + 1); 

sizeof(char)被保證是1並且可以從尺寸計算被省略。

防止i超過分配給arguments的內存的邊界。由於目前的代碼沒有防止i超過909i的有效值,因爲arguments被分配到10元素)。

+0

通過阻止您在代碼中指出$ i

+0

將'i <10'添加到'while'循環終止條件。 – hmjd

+0

我已經完成了你所建議的所有更改,但是當涉及cat命令時,它保持不變。我該怎麼做才能讓它執行呢? –