0

I was writing a code where i will ask a user for a command input, then i have to sperate the string into substring using " " (space) as delimiter. below is my code...

        //some code above...
        printf("\nEnter command: ");
        fgets(comd, 20, stdin);
        printf("\nrecived: %s\n", comd);

        comd[strlen(comd)-1] = '\0'; //putting null at the end instead of "\n"
        //scanf("\n%[^\n]%*c", comd); 
        
        if(strcmp(comd, "exit") != 0 && strcmp(comd, "EXIT") != 0)
        {
            int i = 1, arg = (strocc(comd, ' ')); //strocc() returns total occurance of the char passed...
            char* rest = comd, args[arg+1][15], *tok;

            tok = strtok_r(comd, " ", &rest);
            strncpy(args[0], tok, strlen(tok));
            printf("\ncommand: %s Arguments: %s  Total arguments: %d\n",  args[0], rest, arg);

            while(i < arg+1)
            {   
                strcpy(comd, rest);
                tok = strtok_r(comd, " ", &rest);
                strncpy(args[i], tok, strlen(tok));
                printf("%s, (%d)\n", args[i], i); //printing all arguments one by one...
                i++;
            }

            //some more code...
        }

but after tokenizing my origional string there is most of the time some grabage in the tokened string i.e.

//output

Enter command: ./q3 ./q2 23
recieved: ./q3 ./q2 23 

//printed tokenized string
command: ./q3� Arguments: ./q2 23  Total arguments: 2
./q2, (1)
23I?t�, (2)

i tried assigning my string 'tok and args[]' to null before puting char init but it didn't worked

  • 1
    Edit the question to provide a [mre]. – Eric Postpischil Mar 05 '23 at 11:59
  • 3
    `strncpy(args[0], tok, strlen(tok));` you do not copy zero terminating char – KamilCuk Mar 05 '23 at 12:05
  • OT, but `comd[strlen(comd)-1] = '\0'; //putting null at the end instead of "\n"` is wrong. The string won't have a `\n` if you read an empty string (such as by hitting `EOF`) it will write to `comd[-1]`, or if the string doesn't end with `\n` because more characters were entered that can fit in the length passed to `fgets()`. See [**Removing trailing newline character from fgets() input**](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – Andrew Henle Mar 05 '23 at 12:38
  • Questions seeking debugging help should generally provide a [mre] of the problem, which includes a function `main` and all `#include` directives. This allows other people to easily test your program, by simply using copy&paste. – Andreas Wenzel Mar 05 '23 at 13:21

1 Answers1

2

Your approach with the function strocc

int i = 1, arg = (strocc(comd, ' ')); //strocc() returns total occurance of the char passed...

is in general invalid. The user can type more spaces between words or type a trailing space. In this case your code will have undefined behavior.

The function strtok_r is not a standard C function. It is better to use standard C function strtok_s.

In this call of strncpy

strncpy(args[i], tok, strlen(tok));

there is not copied a string because the terminating zero character '\0' is not stored in the destination array. At least you could write

strncpy( args[i], tok, 15 );

args[i][14] = '\0';
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    `strtok_s()` may not be available - it's part of the optional Annex K. It's not widely supported outside of Microsoft, although I think it's been a recent addition to `glibc`. Offhand, I think the Microsoft `strtok_s()` semantics might differ from the C standard's `strtok_s()` semantics, **but** I believe the Microsoft `strtok_s()` semantics actually perfectly match POSIX `strtok_r()` semantics. I'm pretty certain I used a `#ifdef _WIN32 #define strtok_r strtok_s #endif` hack recently in some customer code that needs to be compiled on both Windows and POSIX systems. – Andrew Henle Mar 05 '23 at 12:45
  • yes seems to work thanks, i assumed that strcpy() will do that for me but after looking into it, the strcpy()/ strncpy() donot put '\0' at the end of the coppied string EDIT: taking about trncpy( args[i], tok, 15 ); args[i][14] = '\0'; – Qaisar Mateen Mar 05 '23 at 12:46
  • @QaisarMateen strcpy copies the full string including the terminating zero. The problem is that the destination array can be smaller than the copied string. In this case you should dynamically allocate an array for each string. – Vlad from Moscow Mar 05 '23 at 12:49