converting float to sprintf - c

I'm trying to convert a float to char string I used sprintf, as the following
float temperature = getTemperature();
char array[15];
sprintf(array, "temperature %f", temperature);
int length = strlen(array);
protocol_WriteMessage(length,(unsigned char*)&array);
but protocol_WriteMessage accepts unsigned char *, so I casted it, but the program crashes.
void protocol_WriteMessage( UINT16 wLen, UINT8 *pbData )
{
UINT16 crc_calc;
// Calculate transmitt CRC16
crc_calc = calc_crc16(&pbData[COMM_POS_COMMAND1], wLen-COMM_POS_COMMAND1);
comm_states.TxActive = true; // signal that the Tx_UART is working
// write data without further checks
hal_uart_WriteBuffer( wLen, pbData );
}

First of all use a safer alternative like snprintf(), and then remove the & address of operator from the call.
To use snprintf() you need to do something like this
int result;
char array[32]; // This should be big enough
result = snprintf(array, sizeof(array), "temperature %f", temperature);
if ((result == -1) || (result >= sizeof(array))) {
// It means that array is too small, or some other error
// occurred such that `snprintf' has returned -1
}
protocol_WriteMessage(length, (unsigned char *) array);
since array is already a pointer to the first element of itself, which is of type char then it's type is char * when passed like that as a pointer, using the & operator is clearly wrong and casting only hides the fact that you made a mistake.

Related

Sprintf function converting int to a single char instead of a string

I'm trying to convert the unsigned long integer converted_binary, which contains 10000000000 to a string, but sprintf converts it to a single character 1 instead.
I am able to know this through the vscode debugger.
I expect sprintf to convert the details of converted_binary to a string, but it doesn't. I initially thought the problem was with the malloc, but that doesn't seem to be the case as the problem persists even if manually create a character array large enough.
I've also tried to replace the sprintf with printf to see if something is wrong with the converted_binary variable, but it prints out 10000000000 to stdout normally.
This is the code snippet:
int get_bit(unsigned long int n, unsigned int index)
{
unsigned long int converted_binary, arg_int_len, int_len = 0;
char *converted_string;
int bit;
/*convert n to binary*/
converted_binary = convert(n);
/*convert binary to string*/
arg_int_len = converted_binary;
do
{
arg_int_len = arg_int_len / 10;
++int_len;
}
while (arg_int_len != 0);
converted_string = malloc(sizeof(char *) * int_len);
if (converted_string == NULL)
return (-1);
sprintf(converted_string, "%lu", converted_binary);
/*Loop through string to binary at index*/
bit = (int)converted_string[index];
/*pass that into a variable*/
/*Return the variable*/
return bit;
}

How to pass an unknown data type through to printf in C

I'm porting some C code which contains function calls like this:
...
char string[] = "Hello";
int data = 3;
char fmt[] = "%d";
printit(string, &data, fmt);
...
/* Elsewhere */
char string[] = "Hello";
float fdata = 3.1416;
char ffmt[] = "%f";
printit(string, &fdata, ffmt);
The function prototype for printit is:
void printit( char *s, void *data, char *format);
I don't have the code for printit (that's part of what I have to do in porting), but from context it is supposed to print the first string then pass the data and format to printf. At various points in the code, printit is called with data of various types. Since the number of arguments to printit is always the same, it doesn't seem like the whole machinery of varargs should be necessary to accomplish this but I haven't cracked a simpler way. What am I missing?
Here is a skeleton of the code I think you're going to need:
void printit(char *s, void *data, char *format)
{
char fmt[4];
fmt[0] = format[strlen(format)-1]; /* last char of format */
fmt[1] = '\0';
fputs(s, stdout);
if(strcmp(fmt, "d") == 0) {
int i = *(int *)data;
printf(format, i);
} else if(strcmp(fmt, "f") == 0) {
double d = *(double *)data;
printf(format, d);
} ...
}
The key to this is that, once we know what type we're operating on, we take the "generic" data pointer and cast it to a "real" pointer type (int *, double *, etc.), and indirect on it with * to fetch the pointed-to value.
You'll have to do a trickier extraction of fmt if you want to handle types long int (%ld), long double (%Lf), or long long int (%lld).

Issues calling a function that accepts certain pointer types

I've finished some C Programming book and felt confident enough to try the cryptopals exercises. I wanted to call a libsodium function which excepts pointers to char arrays I can't figure out.
Could you tell me what is (obviously) wrong with my code and guide me a to a topic I can review to understand my problem?
int main() {
unsigned char hex[] = "49276d206b696c6c696e6720796f757220627261696e206c696b652061207069736f6e6f7573206d757368726f6f6d";
const char *phex = hex;
const size_t phex_length = sizeof(hex);
unsigned char end[phex_length];
const char ** const hex_end = &phex;
printf("Using this hex string with size %ld bytes: \n %s \n",phex_length, **phex);
unsigned char bin[phex_length*10];
unsigned char * const pbin;
size_t binsize = sizeof(bin);
printf("sizeof result for bin: %d \n", binsize);
int status = sodium_hex2bin(pbin, binsize, phex, phex_length, NULL, NULL, hex_end);
if(status < 0) {
printf("Error %d target: bin seems not large enoughi \n", status);
return 1;
}
printf("Converted Binary is: %d \n",bin);
return 0;
}
The functions signature of libsodium I try to call (https://libsodium.gitbook.io/doc/helpers)
int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
const char * const hex, const size_t hex_len,
const char * const ignore, size_t * const bin_len,
const char ** const hex_end);
Normally you should tell us what your problem is with your code. Also what compiler warnings yout get that you were not able to fix.
All this is missing in your question, but a few issues can already be seen:
int main() {
unsigned char hex[] = "49276d206b696c6c696e6720796f757220627261696e206c696b652061207069736f6e6f7573206d757368726f6f6d";
const char *phex = hex;
const size_t phex_length = sizeof(hex);
The spec you linked tells us:
hex does not have to be nul terminated, as the number of characters to parse is supplied via the hex_len parameter.
This means you should not include the terminating 0 byte.
Also why do you make hex an array of unsigned char? It is just a string and the functions expects const char * const hex. Nothing is telling you to make it unsigned.
unsigned char end[phex_length];
const char ** const hex_end = &phex;
That is not a proper variable for the purpose it is used.
The function you call, will return the position where conversion stopped, to the caller via the end pointer. There is no point in passing the address of a char[].
printf("Using this hex string with size %ld bytes: \n %s \n",phex_length, **phex);
unsigned char bin[phex_length*10];
Where did you get the idea to allocate 10 bytes per hex digit?
Every 2 hex digits will end up in 1 binary byte.
unsigned char * const pbin;
Why make it const? That means you cannot even assign any value afterwards.
size_t binsize = sizeof(bin);
printf("sizeof result for bin: %d \n", binsize);
int status = sodium_hex2bin(pbin, binsize, phex, phex_length, NULL, NULL, hex_end);
if(status < 0) {
printf("Error %d target: bin seems not large enoughi \n", status);
return 1;
}
printf("Converted Binary is: %d \n",bin);
As mentioned in comment, bin is of wrong type for %d. And the value you are converting is way too large for any integer variable anyway.
return 0;
}
You seem to have completely misunderstood how function parameters work.
Check your textbook for passing by value and passing by reference (or passing by address)
With fixing the issues above your code should look more like that (untested):
int main(void) {
char hex[] = "49276d206b696c6c696e6720796f757220627261696e206c696b652061207069736f6e6f7573206d757368726f6f6d";
const size_t hex_length = strlen(hex);
unsigned char *end;
printf("Using this hex string with size %zu bytes: \n %s \n", hex_length, hex);
unsigned char bin[hex_length/2];
size_t maxsize = sizeof(bin);
size_t binsize;
printf("sizeof result for bin: %zu \n", binsize);
int status = sodium_hex2bin(bin, maxbinsize, hex, phex_length, NULL, &binsize, &end);
if(status < 0) {
printf("Error %d target: bin seems not large enough\n", status);
return 1;
}
printf("Converted Binary is: \n");
for (int i = 0; i < binsize; i++)
{
printf("%02hhx ", bin[i]);
}
putc('\n');
return 0;
}

void pointer and different size of memory

I have a function which converts a string of an unsigned int to its unsigned int counterpart.
I want to to be able to pass an unsigned type of ANY size to it as the container and specify a limit on how big of a value it is to hold. function prototype is this:
str_to_uint(void *tar, const char *str, const uint64_t lim)
uint64_t *tar is where the unsigned integer will be stored, *str is the string of the number and uint64_t lim is the limit of the size the *tar will be able to hold.
since sizeof(tar) is variable is it safe to cast *tar to an uint64_t * and then contain the converted variable in that? I know that it will always be smaller than the actual type anyway since I check for it with the lim variable.
is such a thing allowed?
basically it would boil down to this
I have a variable of an unsigned type where sizeof(variable) is 1, 2, 3 or 4.
I pass the variable to the function via (void *)&variable.
in the function I cast it to uint64_t * and write the detected variable into it. I make sure the detected variable is able to be written into the variable by checking if it is smaller or equal than lim
is this allowed?
code:
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
static int str_to_uint(uint64_t *tar, const char *str, const uint64_t lim) {
char *eptr = NULL;
unsigned long long int temp = 0;
if (str == NULL) {
printf("str is a NULL pointer\n");
return -1;
}
temp = strtoull(str, &eptr, 10);
if (temp == 0 && eptr == str) {
printf("strtoull() conv err, %s\n", str);
return -1;
} else if (temp > lim) {
printf("strtoull() value to big to contain specified limit, %s\n", str);
return -1;
} else {
*tar = temp;
}
return 0;
}
int main() {
int ret;
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
ret = str_to_uint((void *)&a, "22", UINT8_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&b, "22", UINT16_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&c, "22", UINT32_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&d, "22", UINT64_MAX);
if (ret != 0) {
exit(1);
}
printf("a = %"PRIu8"\nb = %"PRIu16"\nc = %"PRIu32"\nd = %"PRIu64"\n", a, b, c, d);
exit(0);
}
No, of course you can't do that.
If I call your function like this:
uint8_t my_little_value;
str_to_uint(&my_little_value, "4711", sizeof my_little_value);
Then you do
uint64_t *user_value = tar;
*user_value = ...;
Boom, you've overwritten a bunch of bytes you're not allowed to touch. Of course you knew this since I passed you the size of my variable, and you say you "make sure", but I don't see how you intend to do that if your approach is going to be treating tar as a uint64_t *.
I don't see why you can't just return the converted number, like strtoul() already does. That puts the responsibility for dealing with mismatch between storage location and potential precision to represent the converted number on the user (or even on the compiler!) where it belongs. Your proposed API is very error-prone and hard to understand.
At this line of code:
*tar = temp;
You are writing 8 bytes of data to a variable that may be less than 8 bytes in size. You need to handle each size separately, like this for 1 byte:
*(uint8_t *) tar = temp;

Converting int to string in C

I am using the itoa() function to convert an int into string, but it is giving an error:
undefined reference to `itoa'
collect2: ld returned 1 exit status
What is the reason? Is there some other way to perform this conversion?
Use snprintf, it is more portable than itoa.
itoa is not part of standard C, nor is it part of standard C++; but, a lot of compilers and associated libraries support it.
Example of sprintf
char* buffer = ... allocate a buffer ...
int value = 4564;
sprintf(buffer, "%d", value);
Example of snprintf
char buffer[10];
int value = 234452;
snprintf(buffer, 10, "%d", value);
Both functions are similar to fprintf, but output is written into an array rather than to a stream. The difference between sprintf and snprintf is that snprintf guarantees no buffer overrun by writing up to a maximum number of characters that can be stored in the buffer.
Use snprintf - it is standard an available in every compilator. Query it for the size needed by calling it with NULL, 0 parameters. Allocate one character more for null at the end.
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
Before I continue, I must warn you that itoa is NOT an ANSI function — it's not a standard C function. You should use sprintf to convert an int into a string.
itoa takes three arguments.
The first one is the integer to be converted.
The second is a pointer to an array of characters - this is where the string is going to be stored. The program may crash if you pass in a char * variable, so you should pass in a normal sized char array and it will work fine.
The last one is NOT the size of the array, but it's the BASE of your number - base 10 is the one you're most likely to use.
The function returns a pointer to its second argument — where it has stored the converted string.
itoa is a very useful function, which is supported by some compilers - it's a shame it isn't support by all, unlike atoi.
If you still want to use itoa, here is how should you use it. Otherwise, you have another option using sprintf (as long as you want base 8, 10 or 16 output):
char str[5];
printf("15 in binary is %s\n", itoa(15, str, 2));
Better use sprintf(),
char stringNum[20];
int num=100;
sprintf(stringNum,"%d",num);
Usually snprintf() is the way to go:
char str[16]; // could be less but i'm too lazy to look for the actual the max length of an integer
snprintf(str, sizeof(str), "%d", your_integer);
You can make your own itoa, with this function:
void my_utoa(int dataIn, char* bffr, int radix){
int temp_dataIn;
temp_dataIn = dataIn;
int stringLen=1;
while ((int)temp_dataIn/radix != 0){
temp_dataIn = (int)temp_dataIn/radix;
stringLen++;
}
//printf("stringLen = %d\n", stringLen);
temp_dataIn = dataIn;
do{
*(bffr+stringLen-1) = (temp_dataIn%radix)+'0';
temp_dataIn = (int) temp_dataIn / radix;
}while(stringLen--);}
and this is example:
char buffer[33];
int main(){
my_utoa(54321, buffer, 10);
printf(buffer);
printf("\n");
my_utoa(13579, buffer, 10);
printf(buffer);
printf("\n");
}
void itos(int value, char* str, size_t size) {
snprintf(str, size, "%d", value);
}
..works with call by reference. Use it like this e.g.:
int someIntToParse;
char resultingString[length(someIntToParse)];
itos(someIntToParse, resultingString, length(someIntToParse));
now resultingString will hold your C-'string'.
char string[something];
sprintf(string, "%d", 42);
Similar implementation to Ahmad Sirojuddin but slightly different semantics. From a security perspective, any time a function writes into a string buffer, the function should really "know" the size of the buffer and refuse to write past the end of it. I would guess its a part of the reason you can't find itoa anymore.
Also, the following implementation avoids performing the module/devide operation twice.
char *u32todec( uint32_t value,
char *buf,
int size)
{
if(size > 1){
int i=size-1, offset, bytes;
buf[i--]='\0';
do{
buf[i--]=(value % 10)+'0';
value = value/10;
}while((value > 0) && (i>=0));
offset=i+1;
if(offset > 0){
bytes=size-i-1;
for(i=0;i<bytes;i++)
buf[i]=buf[i+offset];
}
return buf;
}else
return NULL;
}
The following code both tests the above code and demonstrates its correctness:
int main(void)
{
uint64_t acc;
uint32_t inc;
char buf[16];
size_t bufsize;
for(acc=0, inc=7; acc<0x100000000; acc+=inc){
printf("%u: ", (uint32_t)acc);
for(bufsize=17; bufsize>0; bufsize/=2){
if(NULL != u32todec((uint32_t)acc, buf, bufsize))
printf("%s ", buf);
}
printf("\n");
if(acc/inc > 9)
inc*=7;
}
return 0;
}
Like Edwin suggested, use snprintf:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int n = 1234;
char buf[10];
snprintf(buf, 10, "%d", n);
printf("%s\n", buf);
return 0;
}
If you really want to use itoa, you need to include the standard library header.
#include <stdlib.h>
I also believe that if you're on Windows (using MSVC), then itoa is actually _itoa.
See http://msdn.microsoft.com/en-us/library/yakksftt(v=VS.100).aspx
Then again, since you're getting a message from collect2, you're likely running GCC on *nix.
see this example
#include <stdlib.h> // for itoa() call
#include <stdio.h>
int main() {
int num = 145;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}
see this link having other examples.
itoa() function is not defined in ANSI-C, so not implemented by default for some platforms (Reference Link).
s(n)printf() functions are easiest replacement of itoa(). However itoa (integer to ascii) function can be used as a better overall solution of integer to ascii conversion problem.
itoa() is also better than s(n)printf() as performance depending on the implementation. A reduced itoa (support only 10 radix) implementation as an example: Reference Link
Another complete itoa() implementation is below (Reference Link):
#include <stdbool.h>
#include <string.h>
// A utility function to reverse a string
char *reverse(char *str)
{
char *p1, *p2;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
// Implementation of itoa()
char* itoa(int num, char* str, int base)
{
int i = 0;
bool isNegative = false;
/* Handle 0 explicitely, otherwise empty string is printed for 0 */
if (num == 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)
{
int rem = num % base;
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num = num/base;
}
// If number is negative, append '-'
if (isNegative)
str[i++] = '-';
str[i] = '\0'; // Append string terminator
// Reverse the string
reverse(str);
return str;
}
Another complete itoa() implementatiton: Reference Link
An itoa() usage example below (Reference Link):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int a=54325;
char buffer[20];
itoa(a,buffer,2); // here 2 means binary
printf("Binary value = %s\n", buffer);
itoa(a,buffer,10); // here 10 means decimal
printf("Decimal value = %s\n", buffer);
itoa(a,buffer,16); // here 16 means Hexadecimal
printf("Hexadecimal value = %s\n", buffer);
return 0;
}
if(InNumber == 0)
{
return TEXT("0");
}
const int32 CharsBufferSize = 64; // enought for int128 type
TCHAR ResultChars[CharsBufferSize];
int32 Number = InNumber;
// Defines Decreasing/Ascending ten-Digits to determine each digit in negative and positive numbers.
const TCHAR* DigitalChars = TEXT("9876543210123456789");
constexpr int32 ZeroCharIndex = 9; // Position of the ZERO character from the DigitalChars.
constexpr int32 Base = 10; // base system of the number.
// Convert each digit of the number to a digital char from the top down.
int32 CharIndex = CharsBufferSize - 1;
for(; Number != 0 && CharIndex > INDEX_NONE; --CharIndex)
{
const int32 CharToInsert = ZeroCharIndex + (Number % Base);
ResultChars[CharIndex] = DigitalChars[CharToInsert];
Number /= Base;
}
// Insert sign if is negative number to left of the digital chars.
if(InNumber < 0 && CharIndex > INDEX_NONE)
{
ResultChars[CharIndex] = L'-';
}
else
{
// return to the first digital char if is unsigned number.
++CharIndex;
}
// Get number of the converted chars and construct string to return.
const int32 ResultSize = CharsBufferSize - CharIndex;
return TString{&ResultChars[CharIndex], ResultSize};

Resources