Search code examples
cshelltokenizestrtok

strtok() not reading past the first input piece


I am trying to write a Linux shell replacement for an operating systems class and am having trouble parsing the input strings. I am able to read in the very first line of a string input, but once it reaches any space delimiter, it completely skips everything else and proceeds to a new prompt. Below is the code I have for what I am trying to handle.

while(1){

    //Flush I/O streams to prevent duplicate '#' printing each new line
    fflush(stdout);
    fflush(stdin);

    printf("# ");

    //Take in the input and store it in an auxiliary variable.
    scanf("%s", input);

    strcpy(commandInput, input);

    char *ptr = strtok(commandInput, delimiter); //Parse the command and check what it is below.

    if(strcmp(commandInput, "byebye") == 0){ //End the shell program
        
        exit(1);

    } else if(strcmp(commandInput, "whereami") == 0){ //Get the current working directory

        getCurrentDirectory();
        break;

    } else if(strcmp(commandInput, "movetodir") == 0){
        
        //Store the new directory name once returned 
        strcpy(currentDirectory, changeDirectory());

        break;

    } else {
        //Handles any invalid input strings of any length

        printf("%s\n", ptr);
        while(ptr != NULL){

            printf("%s\n", ptr);
            ptr = strtok(NULL, delimiter);

        }
    }
}

As an example, below is the output I get when I input a random string that has a space between the tokens:

# hi there
hi
hi
# byebye

It should be printing out 'there' as well, but it never reaches it. Any help would be much appreciated!


Solution

  • As I mentioned [in my top comment], do not do fflush on an input stream.

    You are doing:

    scanf("%s",input);
    

    This will only get the first token on a given line. So, if the input line was (e.g.) hello world, the scanf will only put hello into input

    Replace with:

    fgets(input,sizeof(input),stdin);
    

    To account for the newline that fgets leaves in the buffer, be sure that delimiter is something like:

    const char *delimiter = " \t\n";