-
Parsing string
Hi All!
I need to split string for command and its value.
If i have "imax 1000" i need to get com = "imax", val = "1000".
Code:
void parse_command(char *str)
{
char *chr;
bool is_val = false;
char *com;
char *val;
chr = str;
while(*chr)
{
if(*chr != '\n' && *chr != '\0' && *chr != 32 /*space*/)
{
if(!is_arg)
{
strcat(com, chr);
}
else
{
strcat(val, chr);
}
}
if(*chr == 32)
{
is_arg = true;
}
chr++;
}
printf("%s",com);
printf("%s",val);
}
It compiles ok but in run time programm stops responding.
P.S. It can be more then one spase between two strings.
-
> strcat(com, chr);
> strcat(val, chr);
And where are these pointing?
You have two garbage pointers, so just let loose the hell-hounds.
-
I've changed it:
strcat(com, *chr);
strcat(val, *chr);
Now i get :"\main.c [Warning] passing arg 2 of `strcat' makes pointer from integer without a cast "
-
How about actually creating some memory you can store strings in?
You know, like an array?
Code:
char foo[100] = { 0 };
-
i did so :
Code:
char com[20] = {0};
char val[20] = {0};
The same result.
-
See if this gives you any ideas.
Code:
#include <stdio.h>
int main(void) {
int i, val=0;
char cmd[50]={0};
char str[50]={"imax 1000"};
sscanf(str,"%s %d",cmd,&val);
printf("command: %s value: %d \n",cmd,val);
return 0;
}
-
Unfortunately sscanf is a resource-consuming function, considering the code should run on an atmel chip.
-
It's going to concatenate the strings every loop, not just when you want it to. I'm guessing that's causing buffer overrun which is overriding your str pointer and causing your program to crash.
Use *chr != ' ' instead. It's clearer and comments itself.
You can remove the *chr != '\0' as it's a case that can never happen so is redundant. Or keep it for clarity whatever.
bool is_arg is undefined.
-
> if(*chr != '\n' && *chr != '\0' && *chr != 32 /*space*/)
How many times is this going to be true, resulting in a strcat of a whole string to another string?
> Unfortunately sscanf is a resource-consuming function, considering the code should run on an atmel chip.
Have you run the code on your host machine?
Have you run the code in a debugger to watch what happens?
With a bit of careful prep, you can get 99% of the code to be run on the atmel to run on your host machine, at least to the point where you have a reasonable degree of confidence that it works.
-
Thanks a lot guys for the help.
Did some changes according your suggestion - still no success.
I was trying to work with sscanf on atmel chip - it kills the chip, a lot of stuff going there.
-
Will all of your commands be in the same format? If so, then maybe you can hard code a solution.
Code:
while current element is a letter character
store that character in new array 1
append a null character to new array 1
while current element is a number character
store that character in new array 2
append a null character to new array 2
This assumes you want the number portion as a string, not an integer, as implied in your first post.
-
it'll be command and argument separated by one or more spaces, i think it' a quite trivial task to split the string, can't make up my mind how....yet :)
-
Have you tried strtok? Does this also "kill" your chip? You could also write your own tokenizer which performs this task; the job is tedious but not difficult. The approach used by strtok is to scan through the string character by character. If the current character matches one of the delimiters, replace it by a '\0'. The result is that you have a tokenized set of null-terminated strings.
-
Did it a bit clumsy way but it works.
Code:
void parse_command(char *str)
{
char *chr;
bool is_arg = false;
char com[20] = {0};
char val[20] = {0};
int idx = 0;
chr = str;
while(*chr)
{
if(*chr != 32 /*space*/)
{
if(!is_arg)
{
com[idx++] = *chr;
}
else
{
val[idx++] = *chr;
}
}
if(*chr == 32)
{
is_arg = true;
idx = 0;
}
chr++;
}
com[strlen(com) + 1] = '\0';
val[strlen(val) + 1] = '\0';
printf("%s\n",com);
printf("%s\n",val);
}
-
Solving the problem is what counts. Being "elegant" or something can be a second goal most of the time.
What is the purpose of these lines:
Code:
com[strlen(com) + 1] = '\0';
val[strlen(val) + 1] = '\0';
If you can run strlen on the arguments, then there already is a '\0' there. Do you need to ensure there are two '\0's at the end of the string?
Why not pass in the com and val buffers as arguments to the function? Then you can call it easily from an outer function:
Code:
read_special_command(cmd);
parse_command(cmd, arg1, arg2);
Also its up to you but I like to name it the other way, command_read, command_parse, etc. Then all the "command_" stuff sorts nicely together
EDIT: You can replace
Code:
chr = str;
while (*str)
{
...
chr++;
}
with
Code:
for (chr = str; *str; chr++)
That's what a for loop is for