CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PCM's strlenc vs. CCS's strchr

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PCM's strlenc vs. CCS's strchr
PostPosted: Tue Oct 02, 2007 8:18 pm     Reply with quote

I found PCM's GPS (thread dated 2003) code and he uses a unique function strlenc to locate a character within a string.

http://www.ccsinfo.com/forum/viewtopic.php?t=4402&highlight=strlenc

1. I couldn't find any other reference to the strlenc function on CCS.

2. I found offhand references on Google, but nothing really to compare.

3. I'm assuming that he used a hand rolled function because CCS hadn't provided the strchr function yet. AND, I can replace strlenc with strchr?

I looked in string.h and it looks as though strchr would do what PCM had intended with strlenc.

Thanks,

John


BTW, Thank-you PCM Programmer for the code. It looks like it will save A LOT of time and is much more elegant than I could ever hope for in my own spaghetti....
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 8:44 pm     Reply with quote

strchr() scans a string for the first occurrence of a specified character
and returns a pointer to it. It returns NULL if the character is not found.
It's a standard C function.

strlenc() is, I believe, a custom function. It does something different.
It finds the length of the string before the occurrence of a character.
It doesn't return a pointer.
Code:

// Find the length of string, up to, but not including
// the char c.  Ie., if the char is at the start of the string,
// 0 is returned.  If the char is the 2nd char in the string,
// 1 is returned, etc.  Return 0xff if the char is not found.

char strlenc(char *strptr, char c)
{
char count = 0;
char temp;

while(1)
  {
   temp = *strptr++;
   if(temp == 0)            // Quit if end of string is found
     {
      count = 0xff;         // Return 0xff to show that c was not found
      break;
     }
   if(temp == c)
      break;
   count++;
 }

return(count);

}
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 9:08 pm     Reply with quote

Thank-you. Now that you explain that, I see that. I was also looking in the string.h file and seeing that many of the functions return a pointer (I assume that is the * prior to the function name?

It also looks like I'm going to have to change a lot of your code because of a different format of sentence... all the commas are there even if the data field is empty. But it will be a good exercise and you've given a good starting point.

I see that you use strchr16 which I assume is the same as strchr... except I'm not sure why the 16 is on the function name. Maybe a special function for LONG strings? But that doesn't make sense....

Thanks,

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 9:17 pm     Reply with quote

That was a bug fix, for the vs. 2.xxx compiler. strchr() works OK
in the current compiler.
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 9:20 pm     Reply with quote

Thanks for the explanation.

I'm writing my own strccnt based on how you did the strlenc. After that I should be able to finish it up.

Thanks again,

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 9:32 pm     Reply with quote

Just in case:
Code:

// Count the number of occurrences of the specified character
// in a string.

char strccnt(char *strptr, char c)
{
char count = 0;
char temp;

while(1)
  {
   temp = *strptr++;
   if(temp == 0)         // Quit when end of string is found
      break;
   if(temp == c)
      count++;
  }

return(count);
}
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 9:35 pm     Reply with quote

Here are the two approaches I came up with. I'd love to hear the pros and cons of each of these from a pro and how they relate to yours.

Code:
// Find the number of characters 'c' in the target string
char strccnt(char *strptr, char c)
{
   char count = 0;
   char temp;
   
   temp = *strptr;         // get the first character of the string
   
   while(temp != 0x00)      // continue to the null terminator
   {
      if(temp == c)         // if the character is equal to search character
         count++;            // increment the character counter
      temp = *strptr++;      // move to next charcter in the string
   }
   return(count);
}

// Find the number of characters 'c' in the target string
char strccntXX(char *strptr, char c)
{
   char count = 0;
   char temp;
   
   while(*strptr != 0x00)   // continue to the null terminator
   {
      if(*strptr == c)      // if the character is equal to search character
         count++;            // increment the character counter
      *strptr++;            // move to next charcter in the string
   }
   return(count);
}



BTW, Thanks for the spoon feeding. It's always appreciated.... even more the later it gets.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 02, 2007 10:13 pm     Reply with quote

Assuming that they work, you can just look at the .LST file and see
which routines are more efficient. I don't really spend a lot of time
trying improve little routines like this. They're only called a few times
and speed is not usually important. If it works, then it's good enough.
inservi



Joined: 13 May 2007
Posts: 128

View user's profile Send private message

PostPosted: Wed Oct 03, 2007 2:15 am     Reply with quote

Hello jecottrell,

I think that in your first routine, you test the first char two time because you post increment *strptr ?

in the second routine, you declaring temp for nothing ?

Best regards,
dro.
_________________
in médio virtus
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Wed Oct 03, 2007 8:48 am     Reply with quote

Ahhhh..... Thank-you. I looked up the pre and post increment in a shallow book and carried on. After your comments, I went to my O'reilly 'Practical C' and read in depth. It did a lot better at explaining when things happen.

Here is corrected code:

Code:
// Find the number of characters 'c' in the target string
char strccnt(char *strptr, char c)
{
   char count = 0;
   char temp;
   
   temp = *strptr;         // get the first character of the string
   
   while(temp != 0x00)      // continue to the null terminator
   {
      if(temp == c)         // if the character is equal to search character
         count++;            // increment the character counter
      temp = *strptr + 1;      // move to next charcter in the string
   }
   return(count);
}

// Find the number of characters 'c' in the target string
char strccntXX(char *strptr, char c)
{
   char count = 0;
   //char temp;  leftover from modifying previous function (delete)
   
   while(*strptr != 0x00)   // continue to the null terminator
   {
      if(*strptr == c)      // if the character is equal to search character
         count++;            // increment the character counter
      *strptr++;            // move to next charcter in the string
   }
   return(count);
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 03, 2007 8:51 am     Reply with quote

Like PCM said, this function is so small, it is not worth the effort optimizing.

That said, there is a general design issue with the PIC processors that not everybody is aware of: pointers are not efficiently handled by the processor. To get the value of a pointer on a PIC18 the processor has to load the indirect addressing register FSR and then retrieve the value, a total of 10 clock cycles, even more on a PIC16. This is the reason for PCM introducing the temp variable, it saves a pointer access.

I like to demonstrate an efficient concept for when you have to walk a buffer like in the above functions. Using the FSRx registers in combination with the POSTINC or POSTDEC registers the address pointer will be incremented or decremented by the hardware saving two valuable clock cycles. Another large saving is that the pointer is only initialized once. The resulting function is about 26 bytes smaller than the alternatives from earlier in this thread.

Code:
// #word FSR0 = GETENV("SFR:FSR0L")   // #word is in the Aug-2007 manual but not yet supported in my v4.038
int16 FSR0;
#locate FSR0 = GETENV("SFR:FSR0L")
#byte INDF0 = GETENV("SFR:INDF0")
#byte POSTINC0 = GETENV("SFR:POSTINC0")

// Find the number of characters 'SearchChar' in the target string.
char strccnt_FSR(char *StrPtr, char SearchChar)
{
  char Count = 0;

  FSR0 = StrPtr;    // load pointer register FSR0 with start address of string.
  while (INDF0)     // equal to (*StrPtr) but more efficient.
  {
    if (POSTINC0 == SearchChar)  // POSTINC0 is equal to (*StrPtr++)
      Count++;
  }
  return Count;   
}
This concept is also efficient when you have to work with two different pointers because the PIC has a total set of three addressing registers (FSR0, FSR1, FSR2).

Edit 1: I found out why #word is failing, it is a new directive not supported in my v4.038


Last edited by ckielstra on Wed Oct 03, 2007 9:30 am; edited 1 time in total
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Wed Oct 03, 2007 8:58 am     Reply with quote

Thank-you for the explanation.

That sheds light on why PCM also used a similar approach in the GPS code that this all relates to. I was just assuming the more complex the code, the more efficient it would be..... (great assumption, huh?)

A generalization would be: If you are going to refer back to the value of a pointer numerous times, put it in a variable.... then refer back to the variable?

John
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 03, 2007 9:24 am     Reply with quote

jecottrell wrote:
A generalization would be: If you are going to refer back to the value of a pointer numerous times, put it in a variable.... then refer back to the variable?
Yes, that pretty much sums it up. Cool
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group