Reputation: 19
Here is part of my my c program.
cmdline = "ls | sort -r "
char * cmd1 = strtok(cmdline, "|");
char * cmd2 = strtok(NULL, "");
sscanf(cmd1,"%s",cmd1);
sscanf(cmd2,"%s",cmd2);
I am try to get the output as
cmd1 = "ls"
cmd2 = "sort -r"
But the output I get is
cmd1 = "ls"
cmd2 = "sort"
I found out that the sscanf function make the "-r" disappear. But I have no idea how can I trim " sort -r " become "sort -r". and also " sort -r -r " become "sort -r -r"
I try
sscanf(cmd2, "%s %s %s", cmd3, cmd4, cmd5);
But it cant do the trick because the number of element is fixed.
So what can I do to solve this issue?
Upvotes: 0
Views: 69
Reputation: 26345
When using strtok
you must make sure that the string you are tokenizing is mutable, as strtok
overwrites the delimiter characters with NUL bytes, forming the tokens in existing memory.
For example, it is important to know the difference between these two objects:
const char *immutable = "pointer to a string literal.";
char mutable[] = "a character array, initialized by a string literal.";
To trim leading space, you can find the first non-space character, and move it and all subsequent characters to the front. strspn
(and strcspn
) are useful functions for finding spans of characters.
Alternatively, in this case, you could advance the pointer until it points to the first non-space character. This strategy doesn't work when you need to retain the base pointer, however (e.g., to pass to free
).
To trim trailing space, you can start from the end of the string, working backwards til you find the first non-space character, and place a NUL terminating byte after it.
Here is an example of a basic trimming function.
Note that, in this example, the contents of tokens
have the same lifetime as cmd
. Additionally, trim
does not compress whitespace inside the string (e.g., sort -r
).
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define MAX_TOKENS 8
char *trim(char *s) {
size_t i = 0;
size_t ll = strspn(s, " ");
if (ll) {
while (s[ll])
s[i++] = s[ll++];
s[i] = '\0';
} else
i = strlen(s);
while (i && s[i - 1] == ' ')
i--;
s[i] = '\0';
return s;
}
int main(void) {
char cmd[] = "ls | sort -r| foo | | bar ";
char *tokens[MAX_TOKENS];
char *tok;
size_t n = 0;
tok = strtok(cmd, "|");
while (n < MAX_TOKENS && tok) {
tokens[n++] = trim(tok);
tok = strtok(NULL, "|");
}
for (size_t i = 0; i < n; i++)
printf("%zu:[%s]\n", i, tokens[i]);
}
Output:
0:[ls]
1:[sort -r]
2:[foo]
3:[]
4:[bar]
Upvotes: 1