View previous topic :: View next topic |
Author |
Message |
matsuo
Joined: 17 Feb 2012 Posts: 11
|
How to separate char? |
Posted: Sun Apr 15, 2012 9:41 am |
|
|
Hi
I have a problem about separate (split) word from rs232
Sample.
Getc=1/100-------> rs232
I need separate from ("/") and get
A=1
B=100
But how? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Apr 15, 2012 11:58 am |
|
|
CCS sample program EX_STR shows you separate words.
Then you convert from ASCII to whatever.
Mike |
|
|
matsuo
Joined: 17 Feb 2012 Posts: 11
|
|
Posted: Sun Apr 15, 2012 7:16 pm |
|
|
thanks you for advice...but how to used?
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Apr 16, 2012 12:36 am |
|
|
I think the code in EX_STR is difficult to understand and does not provide the functionality asked for here.
You could write your own input parser. Use strchr() to search for the '/' character, then use atoi() to convert the data before the '/' and again for the data after the '/' character.
Another option would be to use the sscanf function but this is not included with the CCS compiler. Here is a link to an implementation in the Code Library. But if this is a school assignment I wouldn't recommend to copy that code, it would be too obvious it is a code copy. Good for reference though. |
|
|
matsuo
Joined: 17 Feb 2012 Posts: 11
|
|
Posted: Mon Apr 16, 2012 8:36 am |
|
|
Mike Walne wrote: | CCS sample program EX_STR shows you separate words.
Then you convert from ASCII to whatever.
Mike |
This is output
Code: | 10/200
STATISTICS:
You entered 1 word(s).
You entered 1 unique word(s).
You entered 5 number(s).
Enter a string of text. The maximum number of characters is 50. |
It show number only but how to modify |
|
|
darkrush
Joined: 29 Sep 2011 Posts: 18 Location: Colombia
|
|
Posted: Mon Apr 16, 2012 9:57 am |
|
|
you can use this function if the length is always the same.
Code: | char *strndup(char *str, size_t len)
{
register size_t n;
register char *dst;
n = strlen(str);
if (len < n)
n = len;
dst = (char *) malloc(n+1);
if (dst) {
memcpy(dst, str, n);
dst[n] = '\0';
}
return dst;
} |
It would be something like this for 10/200:
Code: |
char *c1, *c2;
c1 = strndup(data_rs232,2);//10
c2 = strndup(data_rs232+3,3);//200
free(c1); //free allocated memory
free(c2);
|
If you can manipulate the data you receive try sending it with a fixed length and it's done. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Apr 16, 2012 10:33 am |
|
|
Aaarrgghh. Please don't use malloc on a small embedded PIC processor!
I know the compiler does support this language feature, but with malloc you run the risk of memory fragmentation. You definitely don't want that to happen. Much better to declare a large buffer on the stack which is guaranteed to be released when you exit your processing function. |
|
|
darkrush
Joined: 29 Sep 2011 Posts: 18 Location: Colombia
|
|
Posted: Mon Apr 16, 2012 11:06 am |
|
|
ckielstra wrote: | with malloc you run the risk of memory fragmentation |
Yeah, I agree with that, it happened to me, that's why you can see the "free()" after you use the function.
Xavier |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
|
darkrush
Joined: 29 Sep 2011 Posts: 18 Location: Colombia
|
|
Posted: Mon Apr 16, 2012 2:10 pm |
|
|
I know is off topic, but the is there any modification to the function to make it more efficient for an embedded device?
I ran many simulations before and the memory is always freed an reused without problem, I think the problem is the malloc implementation.
Xavier |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Mon Apr 16, 2012 2:29 pm |
|
|
the most efficient way in a PIC is to use statically allocated arrays. So for example, instead of:
Code: |
char *strndup(char *str, size_t len) ;
|
do:
Code: |
void strndup(char *src, char*dest, size_t len) ;
|
Mind you, I didn't look at your algorithm at all, but the gist is that rather than output a pointer, pass in the destination pointer, so that way you can statically allocate arrays and just pass them in. |
|
|
matsuo
Joined: 17 Feb 2012 Posts: 11
|
|
Posted: Mon Apr 16, 2012 11:34 pm |
|
|
darkrush wrote: | you can use this function if the length is always the same.
Code: | char *strndup(char *str, size_t len)
{
register size_t n;
register char *dst;
n = strlen(str);
if (len < n)
n = len;
dst = (char *) malloc(n+1);
if (dst) {
memcpy(dst, str, n);
dst[n] = '\0';
}
return dst;
} |
It would be something like this for 10/200:
Code: |
char *c1, *c2;
c1 = strndup(data_rs232,2);//10
c2 = strndup(data_rs232+3,3);//200
free(c1); //free allocated memory
free(c2);
|
If you can manipulate the data you receive try sending it with a fixed length and it's done. |
it's error at "malloc" , how to fix it. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Apr 17, 2012 2:16 am |
|
|
matsuo wrote: | it's error at "malloc" , how to fix it. | This is what I was afraid of...
You ignore the whole discussion as to why it is better not to use malloc. You were given a routine that seems to do what you want and without understanding what it does you copy/paste it and then run into problems.
Your original question is not so difficult to solve. See my earlier post where I pointed you to the functions strchr() to search the string and atoi() to convert a string to integer. Using these functions it should be only a couple of lines and no need for malloc().
Try to make a function yourself. When you get stuck then post whatever code you have and we will guide you. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 17, 2012 2:20 am |
|
|
I wasn't suggesting that EX_STR provided the code to solve your problem, nor that it was easy.
Most of the functions you need are used in that example.
Ckielstra has outlined the basics of what you need to do.
What I'm suggesting is that you cut some code for yourself, then come back when you run into problems.
Assuming that your input from the RS232 is always of the form xxxxx/yyyyy where x and y are variable numbers of digits.
Also that it's in a character array original[] properly terminated with a zero.
If you want something that's simpler to follow, you could:-
(1) Clear two arrays numertor[], denominator[]; and set two indicees i & j to zero.
(2) Compare original[i] with '/'.
(3) If FALSE then copy original[i] to numerator[i]; i++; loop back to (2)
(4) If TRUE then i++; proceed to (5)
(5) Compare original[i] with zero terminator.
(6) If FALSE then copy original[i] to denominator[j]; i++; j++; loop back to (5).
(7) If TRUE proceed to (8).
(8) Convert numerator[] & denominator[] arrays from ASCII to your chosen number format.
(9) Job done.
Mike |
|
|
matsuo
Joined: 17 Feb 2012 Posts: 11
|
|
Posted: Tue Apr 17, 2012 3:01 am |
|
|
I try this but it not work
Code: | #define BUFFER_SIZE 5
char array[BUFFER_SIZE];
char first[];
char second[];
int8 start=0;
int j=0;
int i=0;
#INT_RDA
void receive()
{
array[i]=getc();
if ((array[i]=='/')||j>0)
{
strcpy(second,array+i);
j++;
i++;
}
else if (!(array[i]=='/')&&j==0)
{
strcpy(first,array);
i++;
}
else
{
}
if (i>=BUFFER_SIZE)
{
i= 0;
j= 0;
start=1;
}
}
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE){
if (start){
printf(first);
printf(second);
start = 0;
}
}
} |
|
|
|
|