Having trouble C language debug step into process decimal point operator in a floating point sting of numbers. Example: 1234.5678, itoa() output stops at 4 and terminates out array string with '\0' Null char* pointer also an array. So we only get 1234\0 in the out array even after adding test for '.' seems to just skip over it like it's not really there. Thanks for any ideas to get these counts and floating-point decimal point for serial UART data without using printf().
Also strnlen() has same issue, counts only to the decimal point and C sizeof returns the count of 2 (1234.5678) characters are put in the array1={0.0} yet sizeof operator is in violation of clang definition below since it only returns count of 2 for the string. This may be vendor related string.h
#if defined(_INLINE) || defined(_STRLEN)
_OPT_IDEFN size_t strlen(const char *string)
{
size_t n = (size_t)-1;
const char *s = string;
do n++; while (*s++);
return n;
}
#endif /* _INLINE || _STRLEN */
size_t len = sizeof *varin;
sizeof object and sizeof(type name): yield an integer equal to the size of the specified object or type in bytes. (Strictly, sizeof produces an unsigned integer value whose type, size_ t, is defined in the header <stddef. h>.) An object can be a variable or array or structure. A type name can be the name of a basic type like int or double, or a derived type like a structure or a pointer.
```
/*****************************************************
*
*! Implementation of itoa()
*
* b\return converted character string
*
***************************************************/
char*
itoa(int16_t num, char* str, int base)//intmax_t
{
uintptr_t i = 0; //int
bool isNegative = false;
/* Handle decimal point explicitely with ASCII (".") */
if(num == '.')
{
//str[i++] = '.';
str[i] = 0x2E;
//
return str;
}
/* Handle unterminated end of string by adding NULL */
else if(num == ' ')
{
str[i] = '\0';
//
return str;
}
/* Handle 0 explicitely, otherwise Null string is printed for 0 */
if(num == '0') //0
{
str[i++] = '0';
//str[i] = '\0';
return str;
}
// In standard itoa(), negative numbers are handled only with
// base 10. Otherwise numbers are considered unsigned.
if (num < 0 && base == 10)
{
isNegative = true;
num = -num;
}
// Process individual digits
while (num != 0)
{
int16_t rem = num % base; //intmax_t
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0'; //
num = num/base;
}
// If number is negative, append '-'
if (isNegative)
{
str[i++] = '-';
}
// Append string terminator
str[i] = '\0';
// Reverse the string
reverse(str, i);
return str;
}
```
/* Decls */
static float32_t varin[1] = {0.0};
*varin = dbytes;
static char varout[8];
/* Convert hexadecimal to ASCII codes
* terminate end NULL */
itoa(*varin, varout, 10);
I think there are three separate problems here. Let's cover them in turn.
sizeof
is for computing the size of an object as declared. It's not generally any good for determining the length of a string. I suspect you got 2 because you (a) tried to take the size of a pointer and (b) are using a 16-bit microcontroller. You can demonstrate that issue like this:sizeof
computes the size of the pointer itself, whilestrlen
computes the length of the pointed-to string.The second problem is that you seem to be imagining that a number — an
int
orfloat
value — contains human-readable characters like'.'
or' '
or'0'
. It does not. A number is a number you can do math on; it is not a string of characters you can see. In youritoa
implementation, you're doing things likeand
and
But these are all wrong. If an integer has the value 0, it does not contain the character
'0'
. A floating-point variable likefloat f = 123.456
looks to you and me like it contains a decimal point, but in the computer's memory, it does not, so it makes no sense to test whethernum
is equal to'.'
. (It makes especially no sense sincenum
in that code is an integer variable, not a floating-point variable.)The third problem is that you're trying to use your
itoa
function to directly convert a floating-point value, and it's failing, and you're surprised at the way it's failing. But really, there's no surprise. If you have a functionthat accepts an integer parameter
num
, and you pass a floating-point value like 123.456, the first thing the compiler is going to do is convert the floating-point number to an integer, by throwing away the fractional part. That's why everything after the decimal point seems to be missing.So with those misconceptions out of the way, let's look at how to properly convert a floating-point number to its string representation. It turns out this is a very hard problem! In fact, a proper algorithm for performing this task, in all cases, without error, was not published until 1990. So the right way to convert a floating-point number to a string is generally to use
printf
orsprintf
, because those functions have a pretty good chance of using a proper algorithm.But you said you didn't want to use printf. It's possible to convert a floating-point number to a string "by hand" — it can actually be rather straightforward — but you should realize that any code you can write will probably not do a perfect job of it.
You can find some code and commentary about this problem at this former SO question and also this one.
Here is a simple, straightforward, basically simpleminded
ftoa
function for converting floating-point numbers to strings. It's written on top of your existingitoa
function, as I think you were trying to do. It follows the approach suggested in this comment: it takes a floating-point number like123.456
and breaks it up into an integer part123
and a fractional part.456
. It converts the integer part usingitoa
. Then it converts and appends the fractional part by repeatedly multiplying it by 10. It accepts amaxprec
argument telling it how many digits after the decimal to print, just like the number you can use in%.6f
inprintf
.Here is an example call:
But please note that this is not a very good function! It will work decently well for "simple" floating-point numbers, but it has plenty of problems. The example call
ftoa(123.456, buf, sizeof(buf), 6)
shows one of them: it converts to123.456001
on my machine. (Although, that's not actually as wrong as it looks.)As mentioned, properly converting floating-point numbers to strings is a very hard problem, and this simpleminded code does not attempt to address any of the hard parts of the problem. See chux's answer for a somewhat more complete approach.
Also, for this to work at all you're going to have to fix at least some of the problems in the underlying
itoa
function. At the very least, changeif(num == '0')
toif(num == 0)
and uncomment thestr[i] = '\0'
line in that case. You should also get rid of thenum == ' '
andnum == '.'
cases, which you don't need and which will cause unnecessary problems trying to convert the numbers 32 and 46.