jaiesh
jaiesh

Reputation: 146

ARRAYS in C a hassle

I have been trying to program a UNIX style shell command prompt in C. Within this program I need it to keep track of the commands that have already been used, so the user can recall the last command by entering 'r'. I made a globally initialized array to hold strings. Whenever the array of characters a user entered needs to be saved, I add it to the global array. I have tried memcpy, simply copying each value using a loop, and just copying the pointer. None of these have been working. I am not super familiar with C and I am sure it is a pointer problem.

Whenever I copy the pointer of inputBuffer to my global array string (it does get copied), however upon leaving the setup function this pointer disappears? I am not exactly sure what I am doing wrong.

Test:

(1)user input --> ls

string[0] = ls

(2)user input --> r

inputBuffer = ls

string[recent] = ls

incorrectly does...

inputBuffer = r

string[recent] = r

(I have included the relevant parts of the code.)

 #define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
    #define SAVED_BUFFER 100


    char *string[SAVED_BUFFER];
    int p = 0;
    int recent = -1;
    int stringSize = 0;

    void setup(char inputBuffer[], char *args[],int *background)
    {
        int length, /* # of characters in the command line *

        /* read what the user enters on the command line */
        length = read(STDIN_FILENO, inputBuffer, MAX_LINE);  

        start = -1;
        if (length == 0)
            exit(0);            /* ^d was entered, end of user command stream */
        if (length < 0){
            perror("error reading the command");
            exit(-1);           /* terminate with error code of -1 */
        }

        if (inputBuffer[0] == 'r' && inputBuffer[1] == '\n' && stringSize > 0) {
            int k;  

            memcpy(inputBuffer, string[recent], strlen(string[recent]) + 1);
            printf("%s",inputBuffer);
            printf("%s",string[recent]);

        }
        else {  

            string[p] = inputBuffer;
            printf("%s", string[0]);

            stringSize++;
            recent++; // one behind strings current array location, to get history
            p++; // current string array spot
        }

    }

    int main(void)
    {
        char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
        int background;             /* equals 1 if a command is followed by '&' */
        char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */


        while (1) {            /* Program terminates normally inside setup */
        background = 0;
        printf("COMMAND2->");

            fflush(0);

        setup(inputBuffer, args, &background);       /* get next command */
        }
    }

Upvotes: 0

Views: 143

Answers (2)

sth
sth

Reputation: 229593

When you "save the input buffer" you actually only store a pointer to the inputBuffer array:

string[p] = inputBuffer;

The actual data is not copied, you just store a pointer to the global input buffer. When the next input replaces the old content of inputBuffer, you will see the new content even if you access it through string[recent].

The calls to memcpy don't actually do anything, since the passed input and output buffer all refer to the same memory.

To actually store a copy of the data you have to allocate new memory to store the copy. Since you are dealing with strings, this is most easily done with strdup(), which duplicates a string:

string[p] = strdup(inputBuffer);

Later, once you are done with such a copy and don't need it anymore you have to free the memory used by the copy:

free(string[p]);

Upvotes: 3

Robert Martin
Robert Martin

Reputation: 17157

Have you tried changing

char *string[SAVED_BUFFER];

to

char string[SAVED_BUFFER][MAX_LINE];

I think that's how you're treating it in the code

Upvotes: 1

Related Questions