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?
Divide integer by 10 then display one decimal place?
-
- Posts: 316
- Joined: 23 Oct 2008 09:36
Re: Divide integer by 10 then display one decimal place?
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?
-
- Posts: 316
- Joined: 23 Oct 2008 09:36
Re: Divide integer by 10 then display one decimal place?
I've decided to create a function to do this, at the moment it just returns a pre-defined string:
Except that it isn't returning anything.
[EDIT] Fixed, space needed after * unlike the examples in mikroC Help files
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 ;
}
[EDIT] Fixed, space needed after * unlike the examples in mikroC Help files
-
- Posts: 316
- Joined: 23 Oct 2008 09:36
Re: Divide integer by 10 then display one decimal place?
And here is the working version:
No idea why the destination string txt9 needs to have extra space at end, but it does.
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 ;
}
Re: Divide integer by 10 then display one decimal place?
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.
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.
-
- Posts: 316
- Joined: 23 Oct 2008 09:36
Re: Divide integer by 10 then display one decimal place?
Tried to do this, got in a muddle. Any chance you could give an example?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...
Re: Divide integer by 10 then display one decimal place?
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:
strcpy takes the destination first.
In the main program you might declare:
also adapting the other version to have a result buffer:
then when calling you pass "text" as an argument:
This works because "text" is a pointer to some memory and we are telling the function "here is a buffer, put your output there".
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") ;
}
In the main program you might declare:
Code: Select all
unsigned char text[9];
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
}
Code: Select all
intDiv10ToStr(text,12345);
Re: Divide integer by 10 then display one decimal place?
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);
}