2017-04-19 1 views
0

셸의 가장 최근 항목 10 개를 인쇄하는 history 명령과 함께 시뮬레이트 된 셸 프로그램을 작성하려고합니다. 문제는 history 명령을 사용할 때 입력 된 행을 인쇄하는 대신 addToHistory의 내부 배열 인수의 이름 인 "history"가 모든 항목에 대해 인쇄된다는 것입니다.배열의 인쇄 요소가 배열 이름을 대신 인쇄합니다.

다음은 코드입니다.

void addToHistory(char *line, char **history, int num) { 
    // insert line into first element of history 
    // move elements backward to make room 
    if(num == 0) { 
     history[0] = line; 
    } 
    else if (num > 1 && num < HISTORY_BUFFER) { 
     printf("%d", num); 
     printf("\n"); 
     for(int i = num-1;i > 0;i--) { 
      history[i] = history[i-1]; 
     } 
     history[0] = line; 
    } 
    else if (num > HISTORY_BUFFER) { 
     printf("%d", num); 
     printf("\n"); 
     for(int i = HISTORY_BUFFER-1;i > 0;i--) { 
      history[i] = history[i-1]; 
    } 
     history[0] = line; 
    } 
} 


int main(void) 
{ 
    char *args[MAX_LINE/2 + 1];    /* command line arguments     */ 
    char *history[HISTORY_BUFFER]; 
    char line[64]; 
    int should_run = 1;      /* flag to determine when to exit program */ 
    int num = 0; 
    while (should_run) { 
     printf("osh> "); 
     fflush(stdout); 
     gets(line);       /* read in the command line    */ 
     printf("\n"); 
     parse(line, args);     // function for splitting input into seperate strings; works fine 
     if (strcmp(args[0], "exit") == 0) { /* is it an "exit"?      */ 
      should_run = 0;     /* exit if it is      */ 
     } 
     else if (strcmp(args[0], "history") == 0) { 
      if (num == 0) { 
       printf("No commands in history. Please enter a command and try again\n"); 
      } 
      else if (num < 10) { 
       for(int i = 0;i < num;i++) { 
        printf("%d ", i); 
        printf(history[i]); 
        printf("\n"); 
       } 
      } 
      else { 
       for(int i = 0;i < 10;i++) { 
        printf("%d ", i); 
        printf(history[i]); 
        printf("\n"); 
       } 
      } 
     } 
     /* snip */ 
     else { 
      addToHistory(line, history, num); 
      num++; 
      // executeProcess(args); 
     } 
    } 
} 

10 개 항목 이후에 생성 된 출력

osh> history 
0 history 
1 history 
2 history 
3 history 
4 history 
5 history 
6 history 
7 history 
8 history 
9 history 

같은 곳 "역사"대신 시간에 쉘에 입력 된대로해야한다. 한 번 입력 한 후 출력은 단순히 0 history', so the behavior is present in all iterations of addToProcess`입니다.

+2

어떤 상황에서도'gets()'를 사용하지 말아야합니다. C99에서는 더 이상 사용되지 않으며 C11에서는 언어에서 완전히 제거되었습니다. –

답변

5

배열의 모든 요소에서 addToHistory 함수에 전달 된 문자열에 대한 포인터를 저장하고 있습니다. 새 명령을 입력 할 때이 문자열을 덮어 쓰므로 기록을 표시하면 모든 항목에 마지막 명령 (이 경우 history)이 표시됩니다.

기록 배열에 저장할 문자열의 복사본을 만들어야합니다. 이렇게하는 가장 쉬운 방법은 문자열의 복사본을 만드는 것입니다. 대신

history[0] = line; 

당신이 있는지 확인해야합니다, 그래서 strdup 동적, 새 문자열에 대한 메모리를 할당하는 strdup 기능을

history[0] = strdup(line); 

사용 주 단지 배열에 문자열을 저장

제거 된 배열의 항목에 free을 호출하면 메모리 누수가 발생합니다. 또한 프로그램을 종료하기 전에 할당 된 항목을 모두 해제해야합니다.

관련 문제