2015-02-02 10 views
0

저는 현재 숙제를위한 간단한 쉘을 만들고 있는데 문제가 있습니다. 다음은 문제와 관련된 조각 코드입니다 (누락 된 것이 있으면 일부 조각을 잊어 버렸을 수 있습니다).fgets와 chdir가 이상하게 함께 C로 작동합니다

eatWrd는 문자열에서 첫 번째 단어를 반환하고 그 단어를 빼냅니다 문자열.

wrdCount는 묵시적으로 문자열에있는 단어의 수를 반환합니다.

이 코드 중 하나라도 응답에 필요하다면, 나는 그들에게 문제를 일으키지 않는다고 거의 100 % 긍정적이라고 말해주십시오.

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#define MAX 100 

int main(void) 
{ 
    char input[MAX]; 
    char *argm[MAX]; 
    memset(input, 0, sizeof(input)); 
    memset(argm, 0, sizeof(argm)); 

    while(1){ 
    printf("cmd:\n"); 
    fgets(input, MAX-1, stdin); 

    for(i=0;i < wrdCount(input); i++){ 
     argm[i] = eatWrd(input); 
    } 
    argm[i] = NULL; 

    if (!strncmp(argm[0],"cd" , 2)){ 
     chdir(argm[1]); 
    } 

    if (!strncmp(argm[0],"exit", 4)){ 
     exit(0); 
    } 

    memset(input, 0, sizeof(input)); 
    memset(argm, 0, sizeof(argm)); 
    } 
} 

어쨌든,이 루프 (예 : 고양이, LS 등) execvp는을 사용하여 다른 많은 명령, 작동, 내가 CD를 사용할 때, 그것은 내가 쉘을 종료하려고 할 때를 제외하고 예상대로 작동, 실제로 나가려면 여러 번의 종료 호출이 필요합니다. (결과적으로 종료 호출 수가 정확히 cd라고 부르는 횟수와 같습니다). 세션 중에 cd를 사용하지 않으면 종료 호출이 하나만 걸립니다. 무슨 일이 일어나고 있는지 잘 모르겠다. 어떤 도움을 주셔서 감사합니다. 고마워요. 여기

는 eatWrd입니다 :

char* eatWrd(char * cmd) 
{ 
    int i = 0;   // i keeps track of position in cmd 
    int count = 0;  // count keeps track of position of second word 
    char rest[MAX_LINE]; // rest will hold cmd without the first word 

    char * word = (char *) malloc(MAX_LINE); //word will hold the first word 
    sscanf(cmd, "%s", word);     //scan the first word into word 

    // iterate through white spaces, then first word, then the following white spaces 
    while(cmd[i] == ' ' || cmd[i] == '\t'){ 
    i++; 
    count++; 
    } 

    while(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '\n' && cmd[i] != '\0'){ 
    i++; 
    count++; 
    } 

    while(cmd[i] == ' ' || cmd[i] == '\t'){ 
    i++; 
    count++; 
    } 

    // copy the rest of cmd into rest 
    while(cmd[i] != '\n' && cmd[i] != '\0'){ 
    rest[i-count] = cmd[i]; 
    i++; 
    } 
    rest[i-count] = '\0'; 

    memset(cmd, 0, MAX_LINE); 
    strcpy(cmd, rest);  //move rest into cmd 
    return word;    //return word 
} 

을 그리고 여기 wrdCount입니다 :

int wrdCount(char *sent) 
{ 
    char *i = sent; 
    int words = 0; 

    //keep iterating through the string, 
    //increasing the count if a word and white spaces are passed, 
    // until the string is finished. 
    while(1){ 
    while(*i == ' ' || *i == '\t') i++; 

    if(*i == '\n' || *i == '\0') break; 

    words++; 

    while(*i != ' ' && *i != '\t' && *i != '\n' && *i != '\0') i++; 
    } 
    return words; 
} 
+0

추가/누락 된'cmd :'프롬프트가 있습니까? 그리고 디버거를 사용해보십시오. 그것은 곧 당신의 문제를 지적 할 것입니다. –

+0

그리고 gdb가 heppening이라고하는 것은 무엇입니까 – pm100

+0

당신은'wrdCount' 또는'eatWrd'을 보이지 않습니다. 나는 분명히이 시점에서 의심 스러울 것이다. – lurker

답변

0

코드에이 변화는 나를 위해 작동 :

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <unistd.h> 
#define MAX 100 

char *eatWrd(char **line) { 
    char *next_c = *line; 
    char *word_start = NULL; 

    while (isspace(*next_c)) next_c += 1; 

    if (*next_c) { 
     word_start = next_c; 
     do { 
      next_c += 1; 
     } while (*next_c && ! isspace(*next_c)); 
     *next_c = '\0'; 
     *line = next_c + 1; 
    } 

    return word_start; 
} 

int main(void) 
{ 
    char input[MAX]; 
    char *argm[MAX]; 

    while(1) { 
     int word_count = 0; 
     char *next_input = input; 

     printf("cmd:\n"); 
     fgets(input, MAX, stdin); 

     do { 
       argm[word_count] = eatWrd(&next_input); 
     } while (argm[word_count++]); 
     /* The above always overcounts by one */ 
     word_count -= 1; 

     if (!strcmp(argm[0], "cd")){ 
      chdir(argm[1]); 
     } else if (!strcmp(argm[0], "exit")) { 
      exit(0); 
     } 
    } 
} 

eatWrd() 내 변화를주의한다 데이터를 이동시킬 필요가 없으며 문자열을 미리 파싱 할 필요가 없습니다. 기대할 단어 몇 개를 말하십시오. 나는 당신의 구현이 좀 더 복잡 할 것 같아서 따옴표 또는 일부를 처리 할 수는 있지만 같은 일반적인 접근법을 절대적으로 따를 수 있습니다.

또한 strncmp() 대신 !strcmp()을 사용하여 명령 일치 조건을 수정했습니다.

+0

감사합니다 많이, 이것은 매우 통찰력이 있었고, 나는 당신의 대답을 upvote하지만 투표에 충분한 평판을 아직 가지고 있지 않다 – quigs

+0

@quigs, 내가 대답을 받아 들일 수있는 전통적인 일을 당신의 질문에 적절히 대답했다면 (옆에있는 체크 표시를 클릭하여). 당신은 그것을 위해 담당자가 필요하지 않습니다. –