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

sscanf() for CCS
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Oct 23, 2008 6:02 pm     Reply with quote

In my case:

PCW 4.079.

I'm using the 8/13/04 version, short but without variable arguments. Here's the current version of my test program:

Code:

#include <16F887.h>
#device *=16
#device adc=8
#device PASS_STRINGS=IN_RAM
#zero_ram
#FUSES NOWDT                     //No Watch Dog Timer
#FUSES INTRC_IO                  //Internal RC Osc, no CLKOUT
#FUSES PUT                       //Power Up Timer
#FUSES MCLR                      //Master Clear pin enabled
#FUSES NOPROTECT                 //Code protected from reads
#FUSES NOCPD                     //No EE protection
#FUSES BROWNOUT                  //Reset when brownout detected
#FUSES NOIESO                    //Internal External Switch Over mode disabled
#FUSES NOFCMEN                   //Fail-safe clock monitor disabled
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG                   //No Debug mode for ICD
#FUSES NOWRT                     //Program memory not write protected
#FUSES BORV21                    //Brownout reset at 2.1V
#use delay(clock=8000000,RESTART_WDT)
#use rs232(baud=BAUDRATE,parity=N,xmit=TXD,rcv=RXD,bits=8,errors)


/*$F*************************************************************************
*
* Copyright (C)pa 2004 Mark Norton
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Functional
* Description:  Implementation of sscanf() function for the CCS compiler
*
*****************************************************************************/
#include <string.h>
#include <stdlib.h>

/* Uncomment any of these to reduce the code size
   Note that the HEX is a big hog
*/
#define NO_FLOAT
// #define NO_INT
// #define NO_SIGNED_INT
// #define NO_STRING
// #define NO_HEX

/* *************************************************************************
  DESCRIPTION:  Converts string pointed to by s to an unsigned long (16 bit)
  RETURN: result of the conversion
  ALGORITHM:  none
  NOTES:  the next position in the string is returned in endptr
 *************************************************************************** */
long my_atoul(char *s, char *endptr, int base)
{
  signed long result;
  int index;
  char c;

  index = 0;
  result = 0;
  *endptr = s;

  if (( !s ) || ( !*s ))
    return ( 0 );

  c = *s;

  // increase index if positive sign is detected
  if (c == '+')
  {
    c = *(++s);
  }

  // The number is a decimal number
  if (base == 10)
  {
    while (c >= '0' && c <= '9')
    {
      result = 10*result + (c - '0');
      c = *(++s);
    }
  }
  else if (base == 16)    // The number is a hexa number
  {
    if (c == '0' && (*(s+1) == 'x' || *(s+1) == 'X'))
    {
      s += 2;
      c = *s;
    }

    c = toupper(c);
    while ( 1 )
    {
      if (c >= '0' && c <= '9')
        result = (result << 4) + (c - '0');
      else if (c >= 'A' && c <='F')
        result = (result << 4) + (c - 'A' + 10);
      else
        break;
      c = toupper(*(++s));
    }
  }
  *endptr = s;
  return(result);
}

/* *************************************************************************
  DESCRIPTION:  Converts string pointed to by s to a float
  RETURN: result of the conversion
  ALGORITHM:  none
  NOTES:  the next position in the string is returned in endptr
 *************************************************************************** */
float my_atof(char * s, char *endptr)
{
  float pow10 = 1.0;
  float result = 0.0;
  int sign = 0;
  char c;

  c = *s;

  if(c == '-')
  {
    sign = 1;
    c = *(++s);
  }
  else if(c == '+')
    c = *(++s);


  while((c >= '0' && c <= '9'))
  {
    result = 10*result + c - '0';
    c = *(++s);
  }

  if (c == '.')
  {
    c = *(++s);
    while((c >= '0' && c <= '9'))
    {
      pow10 = pow10*10;
      result += (c - '0')/pow10;
      c = *(++s);
    }
  }

   if (sign == 1)
     result = -1*result;

  *endptr = s;
  return(result);
}


/* *************************************************************************
  DESCRIPTION:  Implementation of scanf() using CCS C compiler
  RETURN: total number of arguments read
  ALGORITHM:  none
  NOTES:  none
 *************************************************************************** */
int8 sscanf(
  char  *buf,    /* pointer to the buffer that we are scanning */
  char  *fmt,    /* pointer to the format string */
  char  *pArgs)  /* pointer to array of arguments */
{

  int8        count = 0;
  char        *p;
  int1        size_long;
  int1        sign;
  char        *endptr;

  while (1)
  {
   /* Look to see if we are out of arguments */
   if ( !pArgs )
     return( count );

   /* Gobble up the fmt string */
    while (*buf == *fmt)
    {
      if ((*buf == 0) || (*fmt == 0))
        return (count);
      buf++;
      fmt++;
    }

    /* Check for the % */
    if (*fmt != '%')
      break;

    /* fmt should be '%' go to the next character */
    fmt++;

    /* get the size modifier */
    switch (*fmt)
    {
      case 'l':
      case 'L':
        fmt++;
        size_long = TRUE;
        break;
      default:
        size_long = FALSE;
        break;
    }

    /* fmt should point to our first conversion letter at this point */
    switch (*fmt)
    {
#ifndef NO_FLOAT
      case 'f':
      case 'F':
        /* Get a pointer to this argument */
        p = (float *)(*pArgs);

        /* convert to a number */
        *(float *)p = (float)my_atof(buf, &endptr);

        /* Make sure that we succeeded */
        if ( buf == endptr )
          return ( count );
        buf = endptr;

        /* count this one */
        count++;
        break;
#endif
#ifndef NO_SIGNED_INT
      case 'd':
      case 'D':
        /* Get a pointer to this argument */
        p = (signed int8 *)(*pArgs);
        if (*buf == '-')
        {
          buf++;
          sign = TRUE;
        }
        else
          sign = FALSE;

        /* convert to a number */
        if ( size_long )
        {
          *(signed int16 *)p = (signed int16)my_atoul(buf, &endptr, 10);
          if (sign)
            *(signed int16 *)p = -(*(signed int16 *)p);
        }
        else
        {
          *(signed int8 *)p = (signed int8)my_atoul(buf, &endptr, 10);
          if (sign)
            *(signed int8 *)p = -(*(signed int8 *)p);
        }
        /* Make sure that we succeeded */
        if ( buf == endptr )
          return ( count );
        buf = endptr;

        /* count this one */
        count++;
        break;
#endif
#ifndef NO_INT
      case 'u':
      case 'U':
        /* Get a pointer to this argument */
        p = (int8 *)(*pArgs);

        /* convert to a number */
        if ( size_long )
          *(int16 *)p = (int16) my_atoul(buf, &endptr, 10);
        else
          *(int8 *)p = (int8) my_atoul(buf, &endptr, 10);

        /* Make sure that we succeeded */
        if ( buf == endptr )
          return ( count );
        buf = endptr;

        /* count this one */
        count++;
        break;
#endif
#ifndef NO_STRING
      case 's':
        /* Get a pointer to this argument */
        p = (char *)(*pArgs);

        /* copy the chars */
        while (1)
        {
          if ((isspace(*buf)) || (!*buf))
          {
            *p = 0;
            break;
          }
          else
          {
            *p = *buf;
            p++;
            buf++;
          }
        }

        /* count this one */
        count++;
        break;
#endif
#ifndef NO_HEX
      case 'x':
      case 'X':
        /* Get a pointer to this argument */
        p = (int8 *)(*pArgs);

        /* convert to a number */
        if ( size_long )
          *(int16 *)p = (int16) my_atoul(buf, &endptr, 16);
        else
          *(int8 *)p = (int8) my_atoul(buf, &endptr, 16);

        /* Make sure that we succeeded */
        if ( buf == endptr )
          return ( count );
        buf = endptr;

        /* count this one */
        count++;
        break;
#endif
      /* unhandled format specifier */
      default:
        return (count);
    }
    /* Technically this is incorrect but since the size of all pointers
       are the same, who cares ;)

       point to the next argument
    */
    pArgs += sizeof(char *);
   
    /* Move to the next format char */
    fmt++;
  }

  return (count);
}



void main() {
    char x;
    char sbuffer[64];
    char cmd=0,param=0;
    long l;

    set_tris_a(0x80);
    port_b_pullups(0xFF);
    set_tris_b(0xFF);
    set_tris_d(0);
    set_tris_e(0x01);
    setup_oscillator(OSC_8MHZ);
    setup_adc_ports(sAN5|VSS_VDD);
    setup_adc(ADC_CLOCK_INTERNAL);
    set_adc_channel(5);
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
    setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
    setup_timer_2(T2_DIV_BY_16, 155, 1);
    setup_ccp1(CCP_PWM);
    set_pwm1_duty(75);
    setup_comparator(NC_NC_NC_NC);

sprintf(sbuffer,"/S30\n\");
x = sscanf(sbuffer,"/%C%d", &cmd, &param);
printf("\n\rsscanf sez: %u found, cmd %X param %X\n\r",x,cmd,param);

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 23, 2008 6:18 pm     Reply with quote

Quote:
sprintf(sbuffer,"/S30\n\");

The compiler doesn't like having the start of an escape sequence,
but without an identifier. i.e., you have a backslash at the end
without anything after it. (Probably it's supposed to be "\r").



Quote:
x = sscanf(sbuffer,"/%C%d", &cmd, &param);

Mark's function takes 3 arguments, as shown below. You've got 4 of them
in the code above.
Quote:
int8 sscanf(
char *buf, /* pointer to the buffer that we are scanning */
char *fmt, /* pointer to the format string */
char *pArgs) /* pointer to array of arguments */
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Oct 23, 2008 10:52 pm     Reply with quote

PCM programmer wrote:

Quote:
x = sscanf(sbuffer,"/%C%d", &cmd, &param);

Mark's function takes 3 arguments, as shown below. You've got 4 of them
in the code above.
Quote:
int8 sscanf(
char *buf, /* pointer to the buffer that we are scanning */
char *fmt, /* pointer to the format string */
char *pArgs) /* pointer to array of arguments */


OK... I did some more digging and I think I figured out how to do that. I now have:

Code:

char arglist[2];
arglist[0] = &cmd;
arglist[1] = &param;

...

strcpy(sbuffer,"/S30");
x = sscanf(sbuffer,"/%C%d",arglist);
printf("\n\rsscanf sez: %u found, cmd %X param %X\n\r",x,cmd,param);


Voila! It compiles. Thanks for the tip; I'd never done an array of args before, it took me a while to figure out how to do that. My apparent inability to grasp the finer points of indirection and such is no doubt the reason I'd never be able to make an honest living writing code.

And the output is... (drum roll)...

Code:
sscanf sez: 0 found, cmd 00 param 00


I've played around with it for a while now, always with the same result.
robinaspey



Joined: 01 Oct 2008
Posts: 4
Location: England (for time being)

View user's profile Send private message

PostPosted: Fri Oct 24, 2008 2:40 am     Reply with quote

I got it to work in the end but there are probably some elements of ansi sscanf syntax that dont work correctly . Otherwise in the end it worked fine and I am very grateful for the code.

You just need to stick with it and test any code you write with an ANSI compatible compiler for windows such as DEV-C++
_________________
Thanks in advance ...
RUFINOGG



Joined: 15 Jan 2010
Posts: 8

View user's profile Send private message Send e-mail

scanf()
PostPosted: Tue Dec 14, 2010 3:34 am     Reply with quote

PCM programmer wrote:
For everyone:
If you say it doesn't compile, you need to post your compiler version.

Also say if you're trying to compile the code in Mark's original post
or the shorter version that he posted later.

Tell if you're using Mark's test program or your own test program.
If it's your own, then post it.


When compiling sscanf () gives me this error:
Attempt to create a pointer to a constant
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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