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 CCS Technical Support

sprintf questions

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



Joined: 17 Aug 2007
Posts: 19

View user's profile Send private message

sprintf questions
PostPosted: Mon Aug 20, 2007 4:23 am     Reply with quote

My question is how many locations of tempmsg the code below occupies worst case, my assumption has always been 15, but now I have gotten indications on things being different. I assume the first sprintf to use 3 bytes, and the second to use 5/6 bytes, am I right or wrong?

/Daniel


Code:

#define MAX_SELECT_LENGTH 16


Code:

void send_CommandToFU( unsigned int16 code, signed int32 value )
{
  char tempmsg[MAX_SELECT_LENGTH];
  char BCC = 0;
  int pos = 0;
  int i; 

  tempmsg[pos++] = EOT;
  tempmsg[pos++] = FU_ADDRESS;
  tempmsg[pos++] = STX;
  sprintf(&tempmsg[pos], "%03Lu", code); pos +=3;
  tempmsg[pos++] = '=';
  if (value >= 0) {
    sprintf(&tempmsg[pos], "%05Ld", value); pos+= 5;
  } else {
    sprintf(&tempmsg[pos], "%06Ld", value); pos+= 6;
  }
  tempmsg[pos++] = ETX;
  for (i = 3; i < pos; i++)
    BCC ^= tempmsg[i];
  tempmsg[pos++] = BCC;

  FUCode = 0xFFFF;
  rs485_AddQueue(tempmsg, pos);

  return;
}
zilog



Joined: 17 Aug 2007
Posts: 19

View user's profile Send private message

PostPosted: Mon Aug 20, 2007 4:44 am     Reply with quote

Running this modified code on a Linux/64-bit/gcc PC gives the execution trace below:

Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_SELECT_LENGTH 16
#define EOT 1
#define FU_ADDRESS 32
#define STX 2
#define ETX 3

int FUCode;

void send_CommandToFU(long long int code, long long int value )
{
  char tempmsg[MAX_SELECT_LENGTH];
  char BCC = 0;
  int pos = 0;
  int i;

  tempmsg[pos++] = EOT;
  tempmsg[pos++] = FU_ADDRESS;
  tempmsg[pos++] = STX;
  sprintf(&tempmsg[pos], "%03Lu", code); pos +=3;
  tempmsg[pos++] = '=';
  if (value >= 0) {
    sprintf(&tempmsg[pos], "%05Ld", value); pos+= 5;
  } else {
    sprintf(&tempmsg[pos], "%06Ld", value); pos+= 6;
  }
  tempmsg[pos++] = ETX;
  for (i = 3; i < pos; i++)
    BCC ^= tempmsg[i];
  tempmsg[pos++] = BCC;

  FUCode = 0xFFFF;
  //  rs485_AddQueue(tempmsg, pos);
  printf("msg: %s, len: %d\n", tempmsg, pos);
  //printf("code: %Ld, value: %Ld", code, value);

  return;
}


int main(void)
{
  while (1) {
    send_CommandToFU(999, 123456);
  }
  return;
}


Code:

msg:  999=1234566, len: 14


While modifying for send_CommandToFU(999, 123456); gives

Code:

msg:  999=-12345en: 15


And yes, I do know that I dont check for the end of the string here, this is just for testing ;)
zilog



Joined: 17 Aug 2007
Posts: 19

View user's profile Send private message

PostPosted: Mon Aug 20, 2007 5:28 am     Reply with quote

I now see that I made an erroneous assumption, sprintf CAN fill more than 5/6 spaces here. The solution is to limit "value" to only fill 5 digit places.
Ttelmah
Guest







PostPosted: Mon Aug 20, 2007 7:19 am     Reply with quote

Remember that a 'string', always has a terminating '0'. The sprintf, adding three characters, adds three characters, and then a terminating '0'. This shouldn't matter (since you then start again 'over' this zero in each case). However, then remember that 'pos', is incremented after adding the last checksum byte, so could reach 16. If the RS485 function, uses this as a length indicator, it'll be one larger than the length of the actual data stored. I'd suspect this is your problem.

Best Wishes
zilog



Joined: 17 Aug 2007
Posts: 19

View user's profile Send private message

PostPosted: Mon Aug 20, 2007 7:25 am     Reply with quote

Ttelmah wrote:
Remember that a 'string', always has a terminating '0'. The sprintf, adding three characters, adds three characters, and then a terminating '0'. This shouldn't matter (since you then start again 'over' this zero in each case). However, then remember that 'pos', is incremented after adding the last checksum byte, so could reach 16. If the RS485 function, uses this as a length indicator, it'll be one larger than the length of the actual data stored. I'd suspect this is your problem.

Best Wishes


I only count pos increasing to the value of 14 at the end of the function, it is used as a"number of characters"-indicator for the add-function. You can find all of the abovementioned functions in http://wintermute.csbnet.se/~zilog/kod/styrkort_riktiga/DriveLPI.c
Ttelmah
Guest







PostPosted: Mon Aug 20, 2007 8:00 am     Reply with quote

Er. Pos will always be larger than you expect then...
Remember '++', means 'increment after using the value', so 'pos' will always be one _more_ than the number of characters.

Best Wishes
zilog



Joined: 17 Aug 2007
Posts: 19

View user's profile Send private message

PostPosted: Mon Aug 20, 2007 8:18 am     Reply with quote

Ttelmah wrote:
Er. Pos will always be larger than you expect then...
Remember '++', means 'increment after using the value', so 'pos' will always be one _more_ than the number of characters.

Best Wishes


pos begins at zero and is incremented after each use -> should contain the number of characters at the end. During a run with a negative number not exceeding 5 digits in magnitude, I place the following in the buffer:

[EOT, ADDRESS, STX, 3 digits code, '=', 6 digits value where the first is '-', ETX, BCC] which adds up to 15 characters in the buffer, and leaves pos == 15, being the number of elements in the buffer.
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