Divide integer by 10 then display one decimal place?

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Divide integer by 10 then display one decimal place?

#1 Post by nigelmercier » 26 Sep 2016 14:22

I have a number stored in a variable of type int, for example 10132

This actually represents an air pressure of 1013.2hPa, how can I convert this so it will display one decimal place?

Rtk
Posts: 30
Joined: 13 Nov 2013 18:20

Re: Divide integer by 10 then display one decimal place?

#2 Post by Rtk » 26 Sep 2016 15:57

Hello!

Code: Select all

unsigned char text[7];
int value;  
      
text[0] = (value/10000)%10 + 48;
text[1] = (value/1000)%10 + 48;
text[2] = (value/100)%10 + 48;
text[3] = (value/10)%10 + 48;
text[4] = '.';
text[5] = value%10 + 48;
text[6] = 0;
nigelmercier wrote:I have a number stored in a variable of type int, for example 10132

This actually represents an air pressure of 1013.2hPa, how can I convert this so it will display one decimal place?

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: Divide integer by 10 then display one decimal place?

#3 Post by nigelmercier » 27 Sep 2016 09:59

I've decided to create a function to do this, at the moment it just returns a pre-defined string:

Code: Select all

char * intDiv10ToStr(int num)
{ // divide integer num by 10, return string (with sign) and 1 DP (12345 -> "s1234.5")
char txt8[] = "01234.5" ;
// empty function for testing ...
return txt8 ;
}
Except that it isn't returning anything.

[EDIT] Fixed, space needed after * unlike the examples in mikroC Help files :(

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: Divide integer by 10 then display one decimal place?

#4 Post by nigelmercier » 27 Sep 2016 10:46

And here is the working version:

Code: Select all

char * intDiv10ToStr(int num)
{ // divide integer num by 10, return string (with sign) and 1 DP (12345 -> "1234.5")
  char txt9[9] = "-0000.0 " ;
  IntToStr(num , txt7 ) ;         // txt7 now "s12345"
  memcpy(txt9, txt7, 5) ;         // txt9 now "s1234.0 "
  memcpy(txt9 +6, txt7 +5, 1) ;   // txt9 now "s1234.5 "
  Ltrim(txt9) ;                   // remove leading spaces
  Rtrim(txt9) ;                   //   ... & 1 trailing space
  return txt9 ;
}
No idea why the destination string txt9 needs to have extra space at end, but it does.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

Re: Divide integer by 10 then display one decimal place?

#5 Post by oliverb » 29 Sep 2016 08:46

Because of the way strings (and arrays generally) work in C if you want a function to return a string (or array) it is far better to pass the string (really its pointer) to the function as a parameter and not try to return a string as a return value. By passing the string in to the function you ensure it has correct scope.

Otherwise what actually happens is the string declared inside the function goes out of scope when you leave the function, and what you returned is just a pointer to an unallocated memory location that may be overwritten at any time. Because of the way MC allocates memory the string will persist for a reasonable time, probably until the function is called again, but you shouldn't count on it.

Alternatives are using "static local" for the return string, which means it persists until the next time the function is called and can do dire things if you ever move to a threaded environment, or allocating heap memory which requires the system to have a heap and means you must remember to deallocate the returned string or you have a memory leak.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: Divide integer by 10 then display one decimal place?

#6 Post by nigelmercier » 02 Oct 2016 22:42

oliverb wrote:Because of the way strings (and arrays generally) work in C if you want a function to return a string (or array) it is far better to pass the string (really its pointer) to the function as a parameter and not try to return a string as a return value. By passing the string in to the function you ensure it has correct scope...
Tried to do this, got in a muddle. Any chance you could give an example?

oliverb
Posts: 570
Joined: 24 May 2007 15:09

Re: Divide integer by 10 then display one decimal place?

#7 Post by oliverb » 03 Oct 2016 16:17

Sorry in advance for any typos as I'm not actually compiling this to confirm it.

Actually thinking about it the "strcpy" function IS an example, it has parameters for the source and the destination strings.

adapting your example:

Code: Select all

void intDiv10ToStr(char* txtbuf, int num)
{ // divide integer num by 10, return string (with sign) and 1 DP (12345 -> "s1234.5")
char txt8[] = "01234.5" ;
// empty function for testing ...
strcpy(txtbuf, txt8) ; // or even strcpy(txtbuf, "01234.5") ;
}
strcpy takes the destination first.

In the main program you might declare:

Code: Select all

unsigned char text[9]; 
also adapting the other version to have a result buffer:

Code: Select all

char * intDiv10ToStr(char * txt9, int num)
{ // divide integer num by 10, return string (with sign) and 1 DP (12345 -> "1234.5")
  char txt7[7];  //declare txt7 local as it can be discarded after
  strcpy(txt9,"-0000.0 ") ;  //not quite sure about that, but we can't just "assign" a string.
  IntToStr(num , txt7 ) ;         // txt7 now "s12345"
  memcpy(txt9, txt7, 5) ;         // txt9 now "s1234.0 "
  memcpy(txt9 +6, txt7 +5, 1) ;   // txt9 now "s1234.5 "
  Ltrim(txt9) ;                   // remove leading spaces
  Rtrim(txt9) ;                   //   ... & 1 trailing space
  return txt9 ;                   // many c string functions return the destination pointer see strcpy
}
then when calling you pass "text" as an argument:

Code: Select all

intDiv10ToStr(text,12345);
This works because "text" is a pointer to some memory and we are telling the function "here is a buffer, put your output there".

IstvanK
Posts: 166
Joined: 22 Feb 2013 12:28

Re: Divide integer by 10 then display one decimal place?

#8 Post by IstvanK » 03 Oct 2016 18:10

Other, maybe smaller and quicker solution (tried):

Code: Select all

unsigned char text[8]; // to accomodate "s1234.5" (7 chars + zero)

char *IntDiv10ToStr(char *txt8, int num) {
  // divide integer num by 10, return string (with sign) and 1 DP (12345 -> "1234.5")
  char fract;
  IntToStr(num , txt8); // txt8 is now "s12345", 6 chars + zero, right justified
  fract = txt8[5];      // save last digit
  txt8[5] = '.';        // new DP
  txt8[6] = fract;      // put (append) the saved fract part
  txt8[7] = 0;          // new end sign
  Ltrim(txt8);		    // remove leading spaces if any
  // many C string functions return the destination pointer:
  return txt8;
}

void main() {
  IntDiv10ToStr(text, 12345);
}

Post Reply

Return to “mikroC PRO for PIC General”