2

この問題を修正するのに 2 日間苦労していますが、何もうまくいかないようです! 私は C でシェルを作成しており、履歴コマンド (ユーザーが指定したすべてのコマンドの履歴を保持します) を実装しようとしています。これは私のコードの簡略版です (不要なコードと関数を削除しました)。

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

int main()
{
int doLoop = 1;
int i=0;
int c=0;
char givenCommand[100];
char *history[20];
char *newlinePos; /* pointer to the '\n' character in the input C string */

/* Print the header */
printf("Operating Systems Shell (Fall 2013)\n");
printf("Iacovos Hadjicosti\n");
printf("\n");

while(doLoop==1) /* Check if it should do the loop again */
{
    printf("CSC327>"); /* Print a new prompt line */
    fgets(givenCommand, sizeof(givenCommand), stdin); /* get input */

    newlinePos = strchr(givenCommand,'\n'); /* point newlinePos to the '\n' character */
    if(newlinePos!=NULL)
    {
        *newlinePos = '\0'; /* replace it with the null character */
    }

    if(strcmp(givenCommand,"exit")==0)
    {
        doLoop = 0; /* Do not do the loop again */
    }
    else if(strcmp(givenCommand,"history")==0)
    {

        for(i=0; i<c; i++)
        {
            printf("%d. %s\n", i+1, history[i]);
        }
    }
    else
    {
        if(strcmp(givenCommand,"")!=0) /* if input was not empty.. */
        {
            printf("Command not found!\n"); /* show wrong command message */
        }
    }       

    history[c] = givenCommand;
    c++;
}
return 0;
}

これは入力を取得し、それを givenCommand に入れ、それがどのコマンドであったかを確認してから、履歴配列に入れます。ユーザーが「history」コマンドを実行すると、履歴配列内のすべてのコマンドが出力されます。代わりに、最後に与えられたコマンドだけを c 回出力します (c は与えられたコマンドの総数です)。

たとえば、ユーザーが「Test1」と入力し、次に「Test2」と入力し、3 回目に「history」と入力すると、次のように出力されます。

1.テスト2

2.テスト2

これを解決する方法について意見はありますか?(私は TCC を使用してコンパイルしています)

4

3 に答える 3

2

ポインタを割り当てる代わりに、 にコピーgivenCommandする必要があります。history

strcpy(history[c], givenCommand);

このhistoryためには、コマンド自体のためのスペースがあるように変更する必要があります。

char history[20][100];

文体上の注意として、各コマンドの -bodycontinue;の最後に置くことができるので、その部分を省略できます。ループをすぐに終了するために使用できます。ifelse"exit"break;

if(strcmp(givenCommand, "exit") == 0){
    break; /* end the loop now */
}

if(strcmp(givenCommand, "history") == 0){
    /* do history stuff */
    continue; /* go back to the beginning of the loop */
}
于 2013-10-24T14:58:17.457 に答える
2

この部分を修正

else if(strcmp(givenCommand,"")==0) /* if input was empty.. */
    {
        printf("Command not found!\n"); /* show wrong command message */
    }

else
    {

    history[c]=malloc(strlen(givenCommand)+1); //allocate memory

    //check malloc allocated memory or failed 

    if(history[c]==NULL)  
        {
        printf("malloc function failed \n"); 
        perror("ERROR");
        exit(EXIT_FAILURE);
        // exit(1); //if you don't want to exit then break loop with break;  
        // As alk suggested, The use of EXIT_SUCCESS and EXIT_FAILURE is 
        // slightly more portable (to non-UNIX environments)   
        // than the use of 0 and some nonzero value like  1  or  -1. 
        }  

    strcpy(history[c], givenCommand); // if you can able to use Unix platform you can also use this instead of allocating memory copyinghistory[c] =strdup( givenCommand );
    c++;
    }

Editedstrdup()は POSIX 固有であるため、Windows では機能しません。

あなたの場合はどうなりますか

char givenCommand[100];静的宣言アドレスは同じです。

when you enter "test1"  

                    getcommandname starting address
                    test1
                    ^
                    | 
history[0]----------|


when you enter "test2"                          
                    getcommandname starting address
                    test2
                    ^
                    | 
history[0]----------|
history[1]----------| 


When you enter "history"                        
                   getcommandname starting address
                   history
                   ^
                   | 
history[0]---------|
history[1]---------| 
history[2]---------|  
于 2013-10-24T15:15:39.110 に答える
0

入力するたびに givenCommand の内容が変化するため、ポインタを入力に保存するのではなく、入力を保存する必要があるため、入力文字列を保存するためにstrcopy関数を使用できる場合があります。

于 2013-10-24T15:29:34.030 に答える