What is the best way to read a string as a command with a whitespace separated argument?
An answer to this question on Stack Overflow.
Question
I'm currently writing a primitive shell that lets user input few basic commands: ls, cat etc. I'm taking from the user an input like: ls /home/someUser/someDirectory and storing this in a character array, say input. I've written a few little such functions ls, cat etc. that take an argument and print to stdout the expected result.
What I'd like to know is: what would be the best way to break this input up into a command and argument? For the said example, I'd like to get two different chunks: ls and /home/someUser/someDirectory, so that I can check what command the user wants to execute with what argument. Sure, I can maintain pointers and check the first few characters of the array and compare them and then proceed to the character after whitespace and parse the argument accordingly, but that would be very tedious and inefficient. Is there a better way to do this, possibly an in-built function?
Thanks in advance.
Answer
You could try using strtok:
#include <string.h>
#include <stdio.h>
int main(){
char example_input[80] = "ls /home/user/directory/file.ext";
const char s[2] = "-";
char *token = strtok(example_input, " ");
/* walk through other tokens */
while( token != NULL ){
printf("%s\n", token );
token = strtok(NULL, s);
}
return(0);
}
Escape characters will be somewhat trickier.
If you only need to divide the string into command and argument this may work:
#include <string.h>
#include <stdio.h>
void cmd_ls(const char *arg){
printf("lsing %s\n",arg);
}
void cmd_pwd(const char *arg){
printf("pwding %s\n",arg);
}
int main(){
char example_input[80] = "psdwd /home/user/directory/file.ext";
const char s[2] = "-";
//Find command, assuming it ends at the first space
//Points to first space in string, will eventually point to beginning of
//command
char *command = strchr(example_input, ' ');
//Will point to beginning of argument
char *argument = NULL;
//If command is not NULL, then there is at least one space, so the string has
//the form "<COMMAND> X" where X is either '\0' (string terminator) or another
//character. If the string contains a space, edit it so that there is a
//terminator after the command. If there is an argument, return a pointer to
//its beginning (which may be a space).
if(command!=NULL){
*(command) = '\0'; //Terminate command string
if(*(command+1)!='\0') //If there are argument characters, point to them
argument = command+1;
}
command = example_input; //Point command to beginning of command
//Do I recognise this command?
if(strcmp(command,"ls")==0){
cmd_ls(argument);
} else if(strcmp(command,"pwd")==0) {
cmd_pwd(argument);
} else {
printf("Unrecognised command!\n");
}
return(0);
}