Thread: trying to use strtok() function to parse CL

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    11

    trying to use strtok() function to parse CL

    Hi everybody. I haven't programmed anything in about 8 years, I've read up a little bit on C and need to write a shell in C. I want to use strtok() to take an input from a user and parse it into the command and its arguments.

    for example: copy <file1> <file2> will copy file 2 to file 1, del <file1> will delete a file, etc. The exit command is all I've implemented right now, but even that produces an error when executed...I'm sure I've got a problem with how I've implemented strtok().

    I've tried to implement it below, but when I compile it using gcc (no errors/warnings) and try to execute it I get the following output:

    o-shell>exit
    com = exit
    Segmentation fault (core dumped)


    Here is the code snippet:
    ****************************
    Code:
    char command[50]; //Command line input
    
    char com[10]; //Primary command
    char file1[20]; //File affected by command (if necessary)
    char file2[20]; //2nd file affected by command (if necessary)
    
    char *token; //Used for strtok() function
    
    for(;
    {
    
    printf("o-shell>"); //user prompts for o-shell
    
    scanf("%s", command); //command line input from user
    
    //tokenize the command line input using strtok() function
    //this produces the command as well as any command line arguments
    
    while(token != NULL)
    {
    token = strtok(command, " ");
    strcpy(com, token);
    
    printf("com = %s\n", com);
    
    token = strtok(NULL, " ");
    strcpy(file1, token);
    
    printf("file1 = %s\n", file1);
    
    token = strtok(NULL, " ");
    strcpy(file2, token);
    
    printf("file2 = %s\n", file2);
    }
    ****************************
    When I run the program, I get a segmentation fault. Will this code run OK if there are no arguments, just a command? I'm sure the problem is with strtok() either way. thanks!

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    please give a compilable snippet.

  3. #3
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    strtok is supposed to be used with a pointer to the data only once. after the first call 0 is supposed to be passed.
    In your while loop you alwais call it with the same buffer the first time.
    the second time through the loop the second strtok call will return null.
    calling strcpy with a null pointer crashes the program.
    Kurt

  4. #4
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    Quote Originally Posted by robwhit View Post
    please give a compilable snippet.
    Sorry about that, here's a compilable snippet. I'm only trying to make sure the parsing works. It should exit when the user types exit<ENTER>.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    int main(int argc, char *argv[])
    {
    	char command[50];		//Command line input
    
    	char com[10];			//Primary command
    	char file1[20];			//File affected by command (if necessary)
    	char file2[20];			//2nd file affected by command (if necessary)
    
    	char *token;			//Used for strtok() function
    
    	printf("***************************************************\n");
    	printf("Welcome to O-Shell! A UNIX shell by O Haqqi\n\n");
    	printf("Type 'help' for list of commands, 'exit' to exit\n");
    	printf("***************************************************\n\n");
    
    	for(;;)
    	{
    
    	printf("o-shell>");			//user prompts for o-shell
    
    	scanf("%s", command);		//command line input from user
    
    	//tokenize the command line input using strtok() function
    	//this produces the command as well as any command line arguments
    
    	while(token != NULL)
    	{
    		token = strtok(command, " ");
    		strcpy(com, token);
    
    		printf("com = %s\n", com);
    
    		token = strtok(NULL, " ");
    		strcpy(file1, token);
    
    		printf("file1 = %s\n", file1);
    
    		token = strtok(NULL, " ");
    		strcpy(file2, token);
    
    		printf("file2 = %s\n", file2);
    	}
    
    
    	if (strcmp(com,"exit") == 0)
    	{
    		printf("Exiting o-shell...Goodbye!\n");
    		break;
    	}
    
    	else
    	printf("Invalid command!!!\n");
    
    }
    
    	return 0;
    }

  5. #5
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    Quote Originally Posted by ZuK View Post
    strtok is supposed to be used with a pointer to the data only once. after the first call 0 is supposed to be passed.
    In your while loop you alwais call it with the same buffer the first time.
    the second time through the loop the second strtok call will return null.
    calling strcpy with a null pointer crashes the program.
    Kurt
    So how can I break the user input into 3 (or less) strings? I'm trying to check if the user terminated his input at that point.
    Should I get rid of the while loop and put if(&token == NULL) after the strtok() function, would that fix it? I'm totally confused...sorry like I said I'm a total newbie.

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    you don't initialize token. what is the while loop for anyway?

  7. #7
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    I redid my code and it partially works right now. I can use strtok to find the first input in the command line, but cannot get the arguments.

    The format is <command> <arg1> <arg2>

    So far, I've only implemented 'exit' and 'help'. When I run this code, it compiles fine but I get a segmentation fault. I've placed a couple printf to help debug. One of the problems is that the arguments are not detected/counted.

    Here is the output:

    ************************************************** *
    Welcome to O-Shell! A UNIX shell by O Haqqi

    Type 'help' for list of commands, 'exit' to exit
    ************************************************** *

    o-shell>exit
    exit was entered
    There are 0 arguments
    Command is exit
    Segmentation fault (core dumped)


    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
    char command[50]; //Command line input
    
    //tokens for strtok() funtion
    char * com; //Primary command
    char * arg1; //First argument of command (usually a file name)
    char * arg2; //2nd argument of command (usually a file name)
    
    int args; //Number of arguments entered
    
    printf("************************************************** *\n");
    printf("Welcome to O-Shell! A UNIX shell by O Haqqi\n\n");
    printf("Type 'help' for list of commands, 'exit' to exit\n");
    printf("************************************************** *\n\n");
    
    for(;;)
    {
    
    printf("o-shell>"); //user prompts for o-shell
    
    scanf("%s", command); //command line input from user
    
    printf("%s was entered\n", command);
    
    com = strtok(command, " \r\n\t");
    
    args = 0;
    arg1 = strtok(NULL, " \r\n\t");
    if(arg1) args++; //to see if arguments being tracked
    arg2 = strtok(NULL, " \r\n\t");
    if(arg2) args++; //to see if arguments being tracked
    
    printf("There are %d arguments\n", args);
    printf("Command is %s\n", com);
    printf("File1 is %s\n", arg1);
    printf("File2 is %s\n", arg2);
    
    if ((strcmp(com,"help")) ==0 || (strcmp(com,"Help")) ==0)
    {
    printf("\nO-Shell Help Menu:\n");
    printf("\nhelp - Print help menu\n");
    printf("\nexit - Exit O-Shell\n");
    printf("\ntype <file> - Print contents of <file>\n");
    printf("\ncopy <file1> <file2> - Copy contents of <file1> to <file2>.");
    printf("\n <file2> must be a non-existent file and must be created\n");
    printf("\ndelete <file> - Delete <file>\n\n");
    }
    
    else if ((strcmp(com,"exit")) ==0 || (strcmp(com,"Exit")) ==0)
    {
    printf("Exiting O-Shell...Goodbye!\n");
    break;
    }
    
    else
    printf("Invalid command!!! No operation performed...\n");
    
    }
    
    
    return 0;
    }

  8. #8
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    You're using arg1 and arg2 even if they are NULL.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Code:
    scanf("%s", command);
    this only reads up until the first whitespace so it only reads in the command, not the args.

  10. #10
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    Should I use something other than scanf?

  11. #11
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    http://www.cplusplus.com/reference/c...dio/fgets.html or just do
    Code:
    scanf("%s %s %s\n", command, arg1, arg2);

  12. #12
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    doh. I had tried scanf("&#37;s%s%s") before, I guess the space makes a difference?
    I'll try investigating fgets as well. thanks!

  13. #13
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    Quote Originally Posted by robwhit View Post
    http://www.cplusplus.com/reference/c...dio/fgets.html or just do
    Code:
    scanf("%s %s %s\n", command, arg1, arg2);
    I think this may not work as well as strtok because it requires 3 strings to be input and needs termination after each string. If the user enters <exit> and nothing else, this scanf function will just sit there waiting for more input.
    I need to do a single line input and then parse it into three different string arrays. I will try fgets and see how that works out for me.

  14. #14
    Registered User
    Join Date
    Oct 2006
    Posts
    250
    If you're serious about writing a shell, you may also want to look into lex (flex) and yacc (bison).

  15. #15
    Registered User
    Join Date
    Jun 2007
    Posts
    11
    Quote Originally Posted by MWAAAHAAA View Post
    If you're serious about writing a shell, you may also want to look into lex (flex) and yacc (bison).
    Thanks for the tip. It's not really my own shell, just something basic that implements a copy and delete command. I can do those I think, it's the parsing of the command line that's causing me trouble.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 01:49 PM
  2. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  3. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. I need help with passing pointers in function calls
    By vien_mti in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 10:00 AM