This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

<stdlib.h> itoa

Guru 55013 points
Part Number: EK-TM4C1294XL

Tool/software: Code Composer Studio

Hello,

Not sure why C++ library include does not find (itoa()) in (18.12.2.LTS) but does find (atoi()) and both appear to be present in the stdlib.h file. Rebuild index has no effect to flush an other project linked source path to an added source file mock itoa() in the project tree. Older versions of compiler did not include (itoa()) thus programmers added a name like iota but function does not seem to correctly convert integers (0-9) into ASCII characters. Instead it was configured for a mock iota to find integer to character string lengths.

Seemingly it is important for standard library C++ language calls to work coincidentally with TI tool chains. How can my project without mock iota() be made to use C++ iota() via #include <stdlib.h>?  CCS9.1

  • The function itoa is not required by the standards for C or C++.  It is not supplied with any TI compiler.  There is a similar function named ltoa (long to ascii).  Note ltoa is not standard either.  So the only way to learn about it is by searching the RTS library source code for it.  

    The function atoi is required by the standards.

    BP101 said:
    both appear to be present in the stdlib.h file

    I only see atoi.

    If your program includes a function named itoa, then it must come from somewhere other than the standard RTS library.  It is handled the same as any other user defined function.

    I still do not understand your problem.  How is your implementation of itoa being handled in a manner that is different from other user defined functions?

    Thanks and regards,

    -George

  • Hi George

    George Mock said:
    It is not supplied with any TI compiler

    Oddly it was listed under includes {libcxx (stdlib.h)} 8.2.5 compiler and does not seem to even exist in 18.12.2.LTS.

    My C++ language documents state itoa is part of the C++ language but is missing in TI compiler tool chains seems all so wrong!

    Seemingly project CDT build GNU C++ preprocessors should forward (iota()) into GNU language code analysis but does not! Also inherited library Debug, Symbols etc..(ambiguous) are forever returning into the project after deleting them from the include path tabs in CCS 9.1.  

    George Mock said:
    There is a similar function named ltoa (long to ascii).

    The problem recalled being (long to char) conversion syntax errors. We need (int to char) conversion for array loads into UART 8bit transport. Will try ltoa() but the UART serial output is 8bit register and long to char seems to cause compiler integral error with array[i] (for loop i++) sequencing during conversion. 

    How to PUT 8bit UART characters from an long assigned integer into an array[] in the center of other serial data streams without (itoa())? 

    This alternate iota_code (TI provided) character conversions does not produce correct integer to ASCII stings and also causes random POR of MCU.

    // usprintf() conversion produces incorrect decimal values and random POR of MCU.
    
    usprintf(valout, "%d", valout);
    
    
    // Renamed mock iota to itod so code analysis would find GNU C++ iota().
    // What on earth has format word (base) anything to do with usprintf() or iota()?
    
    // ITOA added by Tiva C group. This C library function may not exist in our standard
    // development environment for every toolchain.
    #define itoad(number, string, base)                                            \
        do                                                                        \
        {                                                                         \
            usprintf(string, "%d", number);                                        \
        }                                                                         \
        while(0)
    

  • Hi George,

    Again tried ltoa() and causes compatibility issues, int32_t MyVariable into a long array[20] then ltoa() into char. Tivaware longs were to be renamed int32_t or uint32_t in the migration from Stellaris applications. I understood identifiers (short, long, char, int) were to be deprecated from newer written applications, post mortem CCS compiler C++ directives think not so fast Tivaware.

    Tivaware and CCS deprecated identifiers are not all on the same page. Either these identifiers were to one day be deprecated but not both! Most times the conversion uint32_t to long succeeds but then conversion into char seems to cause odd issues. So a 9 bit variable incorrectly produces 8 bit integers but the long to usprintf() conversion drops the 9th bit, what to doooooo?

    The ltoa() is not a useable integer to ASCII conversion that TI hardware can use to port longs to 8 bit UART serial characters!

    Serial UART data transport 8 bits 1 stop no parity!

  • Your posts lack specific details I can act on.  For instance, if some compiler RTS function is acting incorrectly, then show me enough detail to reproduce it.  I need to see how you call it, the results you expect, and the results you get instead.  All in very specific detail.

    I should not have suggested you use ltoa.  Because it is not a standard RTS function, future releases of the compiler may not supply it.  Such a change may occur with no notice.

    Consider using sprintf.

    Consider writing your own implementation of itoa.  Model it on the ltoa function.

    Thanks and regards,

    -George

  • BP101 said:
    Oddly it was listed under includes {libcxx (stdlib.h)} 8.2.5 compiler

    There is no TI ARM compiler with that version number.

    BP101 said:
    usprintf(valout, "%d", valout);

    The function usprintf is not supplied with the TI ARM compiler.  

    Thanks and regards,

    -George

  • George Mock said:
    Oddly it was listed under includes {libcxx (stdlib.h)} 8.2.5 compiler

    There is no TI ARM compiler with that version number.

    Wow reversed numbers, should have read 5.2.8 and printf() is producing NULL outputs. The itoa() is very specific and seemingly shifts uint32_t high order bits in the input string so bits >7 produce the correct ASCII digits for 8 bit UART register. The compiler must have a way to inline convert integers into ASCII for 8 bit peripheral can function with applications!

    Why would TI make it so difficult for programmers? There are insane ways to convert integers into 8 bit ASCII but C++ language has the answer TI decided to omit?

     

  • TI ARM compiler version 5.2.8 does not supply an itoa function.  I do not know how that itoa line in stdlib.h came to be there.  Therefore, I cannot explain the problems you have with itoa.

    BP101 said:
    printf() is producing NULL outputs

    I didn't know you use printf.  Do you mean sprintf?

    I continue recommend you either use sprintf, or your own implementation of itoa.

    Thanks and regards,

    -George

  • George Mock said:
    I continue recommend you either use sprintf, or your own implementation of itoa.

    TI needs to put itoa() back into all compiler versions otherwise TI serial UART peripheral can not affectively port variable born integers (decimals) as ASCII 0-9! There is no way prints(), printf(), sprintf() or any other C++ inline function can turn an integer into an ASCII character. usprintf() at least produces the same static ASCII number each time it is invoked.

    The function sprintf does the same conversions as printf does, but
    stores the output in a string:
    
    int sprintf (char *string, char *format, arg i , arg2, ... )
    
    sprintf formats the arguments in argb arg2, etc., according to format as
    before, but places the result in string instead of on the standard output;
    string must be big enough to receive the result.

    The 32bit integer has to be left shifted into the low order bits of an char array[] during conversion subtracting 0x30 according to C++ forums. None of the so called standard C++ (abs, labs, fabs) appear to properly shift high order bits 15:8 into the lower order byte 7:0. Adding Thumb instructions to do integer to ASCII conversion should not have to be coded by the customer when C++ handles that quite affectively!

    Function atoi() is the counter to itoa() and still exists in the compiler - how George explain that? My thought is itoa() was accidently deleted by disgruntled TI employee.

  • 3693 is the result for all variable (integers) passed to ltoa() when *char has to be inline converted to uint32_t.

    usprintf() does the very same 3693 conversion for values that are changing in bits 9:0.

    Due to odd method of index pointer into character array of (const *char) SRAM laden storage.  

    
    

  • This is the result of ltoa() when *char is converted to long(uint32_t) as the integer value was passed into the function above post via many while commands.

    Laying out the array in the for (I) loop above and a few short 2 digit variables are correctly converting to ASCII. All the longs (uin32_t) variables fail to produce correct  3-4 digit ASCII values seems to be shifted upward in the higher order bits. 

     ltoa((uint16_t)varin[i], varout);
    
    /* Transmit data for the component Object named */
    HWREG(UART2_BASE + UART_O_DR) = varout[0]; //ones
    HWREG(UART2_BASE + UART_O_DR) = varout[1]; //tens
    HWREG(UART2_BASE + UART_O_DR) = varout[2]; //hundreds
    HWREG(UART2_BASE + UART_O_DR) = varout[3]; //thousands

  • The thousands place is not producing but NULL cancels all index lookups. Two uint32_t variables had to be output to text boxes versus a number of float widget to produce the correct value. Some uint32_t variables produce an incorrect value in text, float and number widgets.

    The MCU keeps randomly BOR no matter how slow the input stream from inline command while loops via Systick and some uint32_t (long) values are not correct after conversion to ASCII. 

    Yet atoi() seems to produce the correct values oddly in the reverse array order from UART serial RX data. My take on all this is ltoa() is not working as well as it should in standard C++ library. The need for itoa() function may help to make this code piece actually work without random BOR. CCS debug offers no clue for BOR event in the SYSCTRL reset cause register. If the ltoa() conversion is REM'd the random BOR stops.

    	static int SpeedValue;
    
    	/* Convert ASCII numbers to integer values */
    	SpeedValue = atoi(g_ppcArgv[7]);// Ones
    	SpeedValue = atoi(g_ppcArgv[6]);// Tens
    	SpeedValue = atoi(g_ppcArgv[5]);// Hundreds
    	SpeedValue = atoi(g_ppcArgv[4]);// Thousands
    
    	g_sParameters.ulTargetSpeed  = ((uint32_t)(int)SpeedValue);

  • I do not see where you have demonstrated that an RTS function supplied with the compiler has done anything wrong.  If that has happened, please make it clear.  Provide precise details on what the inputs are, what result is expected, and what result is seen instead.

    Thanks and regards,

    -George

  • Hi George,

    I resolved the BOR issues in high speed functions loops but the ltoa() will produce only 16 bit output via two 8 bit chunks. If we try to force even 8 more bits from 3rd array context specified by strnlen() the high order bits (31:16) NULLs the other array values.

    The trim variable (1,2,3) removes high order bits (15:8) for (0-255) bit length gauge type widgets. So input integer length conforms to widget constraints on some calls to convert integer to ASCII as an 8 bit value. A 3rd or even 4th array can not be included or it NULLs all array outputs in the process, even without trim length. Where is the function ltoa() in compiler library?  ltoa() seems fine for 16 bit integers but not at all for 32 bit longs as there are always NULL in high order bits (31:16). It seems something has been missed when TI MCU's went from 16 bit up to 32 bit registers!

        static uint16_t len;
        /* variable value */
        static char varin[0]; // 3 for UART2 array[2]
        *varin = dbyte;
        static char varout[0]; // 3 for UART2 array[2]
    
    		/* Loop through input integers output as strings  */
    		for(i = 0; i <= len - trim; i++)
    		{
    			/* Check variable string length */
    			//len = strlen(varin);
                             len = (sizeof(varin[0]));
    
    			/* Convert integer to strings */
    			//ltoa((varin[0], varout);
                            usprintf(varin, "%d", varout[0]);
    			//varout[0] = *varout;
    
    			/* Blocking checks FIFO Transmitter Busy flag */
    			while(HWREG(UART2_BASE + UART_O_FR) &
    					(UART_FR_TXFF|UART_FR_BUSY))
    			{}
    			/* Transmit data for the component Object named */
    			HWREG(UART2_BASE + UART_O_DR) = varout[0]; //8-bits
    			HWREG(UART2_BASE + UART_O_DR) = varout[1]; //16-bits
    			//HWREG(UART2_BASE + UART_O_DR) = varout[2]; //NULL bits 
    
    			ByteCnt = i;
    
    			/* Next case on count match */
    			if(ByteCnt >= len - trim)
     			{		
    				ByteCnt = 0;
    				NextCmd = 2;
    				break;
    			}
    

  • See above code ltoa() produces NULL's bits (31:14) obviously shifted into bits (15:0). Thus it blanks out previous array stored data in the lower order bits if or when the high order bits (31:14) are include as array loads from calls made to ltoa(). Who would ever be the wiser unless they try to output high order bits (31:14) via a pointer into dedicated array[n].

    We call the function and pass the variable to ltoa():

    This long ltoa() fails to produce correct integer to string values:
    
    while(!(NexSendCmd("taco.val=", (uint16_t)g_ulMeasuredSpeed, 0, 0)));

  • The call to strenlen() insures while loop passes of 32bit integers are (0-255 bit) lengths. 

  • Issue of ltoa() high bits must be C++ Ping Pongs between the two array[0] and array[1]. The odd part is it must require 2 passes of the for loop to load two 8 bit (uint8_t) bytes into 16 bit (uint16_t) conversion of (uint32_t) variable. That was unexpected and opposite from itoa() which required 4 array storage to convert 4 decimals as integer values ported into application.  

    So without integer trim things get real gnarly on the other end of things.