arbitrary floating precision number to string - c

I am new to c programming language.
What I am trying to do is to get store pi in arbitary precision and turn that to string.
int calculatePIConst (int preciznost)
{
//init var
mpfr_t x;
mpfr_init2 (x, preciznost);
//populate pi
mpfr_const_pi (x, MPFR_RNDN);
//turn to string
char abc[preciznost];
int i;
//error RUN FINISHED; Segmentation fault; core dumped; real time: 90ms; user: 0ms; system: 0ms
// mpfr_get_str (abc, i, 50, 50, x, MPFR_RNDN);
//write pi
mpfr_printf ("PI = %1.1024RNf\n", x);
mpfr_clear (x);
return *abc;
}
Here is mpfr lib documentation documentation http://www.mpfr.org/mpfr-current/mpfr.html#Miscellaneous-Functions

The simplest way would be to let the MPFR to allocate the string:
char* abc = NULL;
abc = mpfr_get_str (NULL, i, 10, 50, x, MPFR_RNDN);
printf ("PI = %s\n", abc);
mpfr_clear(x);
mpfr_free_str(abc);
Also check this member function from C++ wrapper for the MPFR for example:
inline std::string mpreal::toString(const std::string& format) const
{
char *s = NULL;
std::string out;
if( !format.empty() )
{
if(!(mpfr_asprintf(&s, format.c_str(), mpfr_srcptr()) < 0))
{
out = std::string(s);
mpfr_free_str(s);
}
}
return out;
}
The thing is to use mpfr_asprintf, it allocates and returns the string automatically (same as mpfr_get_str) but also lets you use the format specification.

From the documentation you linked to:
If str is not a null pointer, it should point to a block of storage large enough for the significand, i.e., at least max(n + 2, 7). The extra two bytes are for a possible minus sign, and for the terminating null character, and the value 7 accounts for -#Inf# plus the terminating null character.
Also, I assume you want your result in base 10, not base 50.
Try this:
char abc[preciznost + 2]; /* assuming preciznost >= 5 */
:
mpfr_get_str (abc, i, 10, 50, x, MPFR_RNDN);

What value are you passing for preciznost? I see that the calls can handle very large bit precision, and there is a danger that you have broken the stack with the declaration
char abc[preciznost];
I suggest you allocate memory on the heap instead, remembering to free() it later.
char *abc = malloc(preciznost);
Although it is unclear what you will be using this array for. If it is a char array of '0' or '1' bit values you will need an extra byte for the nul termintor, so
char *abc = malloc(preciznost+1);

The prototype is:
char *mpfr_get_str (char *str, mpfr_exp_t *expptr, int b, size_t n, mpfr_t op, mpfr_rnd_t rnd)
There are two wrong things in your code:
The array is not large enough. See the answer by squeamish ossifrage. But if you choose to use n equal to 0, it is better to let MPFR allocate the string (also suggested by Pavel Holoborodko in all cases).
The second argument must be a pointer to mpfr_exp_t. For instance:
mpfr_exp_t e;
mpfr_get_str (abc, &e, 10, 50, x, MPFR_RNDN);

Based on Pavel's answer, I created this function to output the string.
string Autozoom::mpfrToString(const mpfr_t& in) {
int decimalLocation;
char* outChar = NULL;
mpfr_exp_t mpfrDecimalLocation;
outChar = mpfr_get_str(NULL, &mpfrDecimalLocation, 10, 0, in, MPFR_RNDN);
decimalLocation = mpfrDecimalLocation;
string out(outChar);
if (out[0] == '-') {
out.insert(decimalLocation + 1, ".");
}
else {
out.insert(decimalLocation, ".");
}
return out;
}
This will actually take the number for the decimal point, insert it into a string and return that.

Related

how to pass a char variable to FS_write() function -- EmFile?

I`m trying to use EmFile library for embedded programing based on C.
this is the structure of FS_write in API documentation :
U32 FS_Write (FS_FILE * pFile,
const void * pData,
U32 NumBytes);
I want to write my own function for my later use like:
void SD_write_to_file(char buff)
{
if(pFile)
{
if(0 != FS_Write(pFile, buff, strlen(buff)))
{
}
else
{
FontWrite_Position(100,148);//Text written to the position
PutStringLCD("Failed to write data to file");
}
}
}
the problem is that when I call this function and pass my char value, it can`t use it for FS_write.
for example:
sprintf(tempwordshow, "%f", realSamples[realsamplescounter]);
SD_write_to_file(tempwordshow);
realSample[ ] is float and tempwordshow is char.
Note that if use the function like :
if(0 != FS_Write(pFile, "0123456789", 10u))
it is working.
I think the problem is from the way of passing my data to this function .
any ideas?
Thanks
In general, make sure functions which take a pointer as argument do indeed receiver pointers. And conversely if you intend to use a pointer, you should make sure the function's signature takes a pointer as argument.
In this particular case your intention seems to be to write a buffer of characters (which can be passed to a function by passing a pointer to the memory location corresponding to the buffer), which would in all likelyhoods be more than a single char. Correspondingly, the signature of the SD_write_to_file should be changed to:
void SD_write_to_file(const char* buff)
You may have a similar problem with sprintf's first argument is expected to be of type char* whereas you mention that tempwordshow is of type char (note also that there should be memory allocated wherever tempwordshow points to). If it wasn't a trivial typo in your question, then you would have to convert tempwordshow's declaration to something such as:
char tempwordshow[40]; // a 40-char buffer should be large enough for %f
As a final note, strlen is designed to handle null-terminated character sequences (or strings). So, if you intend to use this function strictly for null-terminated strings, then this is fine. Otherwise, you may find it more appropriate to pass along the length of the buffer that you wish to write (something like SD_write_to_file(const char* buff, int bufferLength)).
SleuthEye was right. but after those modification I still couln`t write the correct float number in the file. some crap were written in the text file.
So I wrote my own function for converting float to string and the problem solved.
you need to do all the modification that SleuthEye mentioned above. additionally, use this function for changing type:
/** Number on countu**/
int n_tu(int number, int count)
{
int result=1;
while(count-- > 0)
result *=number;
return result;
}
/Convert float to string/
void float_to_string(float f, char r[])
{
long long int length, length2, i, number, position, sign;
float number2;
sign=-1; // -1 == positive number
if (f <0)
{
sign='-';
f *= -1;
}
number2=f;
number=f;
length=0; // size of decimal part
length2=0; // size of tenth
/* calculate length2 tenth part*/
while( (number2 - (float)number) != 0.0 && !((number2 - (float)number) < 0.0) )
{
number2= f * (n_tu(10.0,length2+1));
number=number2;
length2++;
}
/* calculate length decimal part*/
for(length=(f> 1) ? 0 : 1; f > 1; length++)
f /= 10;
position=length;
length=length+1+length2;
number=number2;
if(sign=='-')
{
length++;
position++;
}
for(i=length; i >= 0 ; i--)
{
if(i== (length))
r[i]='\0';
else if(i==(position))
r[i]='.';
else if(sign=='-' && i==0)
r[i]='-';
else
{
r[i]= (number % 10)+'0';
number /=10;
}
}
}
Thanks again . hope that it helps the others in future. :)

conversion in c

I'm new to C and I need to write a function in c which converts an integer to a string in the specified base and print it.
If I were given an input value of 1234 (base 10) it should return 2322 (base 8).
Here is the code structure I'm currently working on:
void int2ascii(int value, int base){
int a=0;
if (value > base) {
a = a + int2char(value); //recursive case
int2ascii(value/base, base); //base case
}
printf("%s\n",a);
}
The program won't run, can someone enlighten me?
Thanks
Analysis of your program
I noted first off that a is declared int, but it was being passed to printf with %s as the format specifier. %s designates the associated argument will be a string, which a is not. The result will be undefined behavior, and is a possible cause for your crash.
You do not specify what int2char() does, but let's assume that it converts a numeric "digit" into a corresponding char value. With that in mind, let us suppose its implementation is similar to:
int int2char(int d) {
return "0123456789abcdefghijklmnopqrstuvwxyz"[d];
}
In your code, you pass value to int2char(). In my hypothetical implementation, this would cause out-of-bounds access of the array, and thus undefined behavior. This is indicates a logic error, and another possible cause for your crash.
I note that if value is less than base, a remains 0. Probably, you really mean to compute a value for a even when value is less than base. This indicates another logic error.
Base conversion
The number dKdK-1 .. d0, where each di is in (0 .. 9), is a short form for &Sum;di×10i. To discover the base 10 digits of a number N, the process is:
di = ⌊N / 10i⌋ mod 10
But, as it turns out, you can replace 10 with some other base number to compute the digits for a number in that base:
di = ⌊N / Bi⌋ mod B
In your code, the recursive call that divides by the base represents the first part of the calculation. However, in your calculation of a, you were missing the "mod" part of the calculation.
Solution 1
Assuming base is from 2 to 36, and that your int2char(d) does something more or less as illustrated earlier:
void int2ascii(int value, int base){
int a=0;
a = a + int2char(value%base);
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",a);
}
Because you are not passing a into your recursive call, you can only use it to store the current digit to be printed. So, move the code to store the value in a out of the if check, since you always want a sensible value to print at the end. The digit in a is in the radix base, so you need the modulus result to get the right digit value. Since a represents a character, change the format string to match, and remove the \n so that all the digits end up on the same line.
Solution 2
The first solution is an attempt to leave most of your original code intact. Since a is initialized to 0, the extra addition does not make it incorrect. But, since the print doesn't happen until the very end, the value doesn't really need to be stored at all, and can be calculated at the point you actually want to print it. With that in mind, the program can be simplified to:
void int2ascii(int value, int base){
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",int2char(value%base));
}
#include <stdio.h>
#include <limits.h>
char *int2ascii_aux(int n, int base, char *s){
//base {x| 2 <= x <= 36 }
static const char *table = "0123456789abcdefghijklmnopqrstuvwxyz";
if(n){
*--s = table[n % base];
return int2ascii_aux(n/base, base, s);
} else {
return s;
}
}
char *int2ascii(int n, int base){
//base {x| 2<= x <= 36 }
static char s[sizeof(int)*CHAR_BIT+1];
if(n <= 0){
*s = '0';
return s;
}
if(base < 2 || base > 36){
*s = '\0';
return s;
}
return int2ascii_aux(n, base, s + sizeof(s) -1);
}
int main(){
printf("%s\n", int2ascii(1234, 8));
return 0;
}

What to pass to printf() [duplicate]

The following outputs 0.23. How do I get it to simply output .23?
printf( "%8.2f" , .23 );
The C standard says that for the f and F floating point format specifiers:
If a decimal-point character appears, at least one digit appears before it.
I think that if you don't want a zero to appear before the decimal point, you'll probably have to do something like use snprintf() to format the number into a string, and remove the 0 if the formatted string starts with "0." (and similarly for "-0."). Then pass that formatted string to our real output. Or something like that.
It is not possible to do it only using printf. The documention for printf says:
f - "double" argument is output in conventional form, i.e.
[-]mmmm.nnnnnn
The default number of digits after the decimal point is six,
but this can be changed with a precision field. If a decimal point
appears, at least one digit appears before it. The "double" value is
rounded to the correct number of decimal places.
Note the If a decimal point appears, at least one digit appears before it.
Therefore it seems you have to handcode your own formatter.
Just convert it to an integer with the required accuracy
double value = .12345678901; // input
int accuracy = 1000; // 3 digit after dot
printf(".%03d\n", (int)(value * accuracy) );
Output:
.123
example source on pastebin
double f = 0.23;
assert(f < 0.995 && f >= 0);
printf(".%02u\n" , (unsigned)((f + 0.005) * 100));
#include <stdio.h>
static void printNoLeadingZeros(double theValue)
{
char buffer[255] = { '\0' };
sprintf(buffer, "%.2f", theValue);
printf("%s\n", buffer + (buffer[0] == '0'));
}
int main()
{
double values[] = { 0.23, .23, 1.23, 01.23, 001.23, 101.23 };
int n = sizeof(values) / sizeof(values[0]);
int i = 0;
while(i < n)
printNoLeadingZeros(values[i++]);
return(0);
}
The Standard C library doesn't provide this, so you have to write it yourself. This isn't a rare, one-off requirement. You'll need to write similar functions sooner or later to trim trailing zeros and to add in thousands-separators. So, it pays to not just get the bytes of output you're looking for but to illustrate more generally how to write a strong library. When doing so keep in mind:
figure out how you want to call it. Something like this you write once but call
a million times, so make the calling as easy as possible.
then make the test suite
exercising all alternatives you can think of
while you're at it,
just solve the problem forevermore so you never have to come back to
it again (eg, don't hardcode width, precision, go ahead and make
versions for leading-plus, e-format, and so on)
make it
thread-safe even if you're not using threads (a specific case of
point 3, actually)
So working backwards: Thread safety requires allocating storage on the stack, which must be done from the caller. This isn't pretty or fun but just get used to it. It's the C way. Formats can have width, precision, some flags, and a conversion type (f, e, g). So lets make width and precision parameters. Rather than parameterizing the public API fully, I'll just have multiple entry points that say in the function name which flags and conversion type they use.
A pet peeve is that when passing in buffers to functions, the function will need to know the size. But if you make that a separate parameter, it's a pain in the but as 1) the caller has to write it and 2) the caller can get it wrong. So my personal style is to make a masking macro that assumes the buffer is a character array, not a pointer, and that uses sizeof() to pass the size into a more verbose version of the function taking the size.
Here's the mock-up of the simplest way I can think of to call it, with test cases.
(Note COUNT() is a macro I've used weekly for decades to get the number of elements in an array. Standard C, should have had something like this.)
(Note I use a dialect of "Hungarian Notation" here. "d" is a double. "a" is "array of." "sz" is a NUL-terminated string buffer, while "psz" is a pointer to one. The difference between these two is that "sz" can be used with COUNT() or sizeof() to get the array size, while "psz" cannot. "i" is an integer and the specific variable "i" is used for looping.
double ad[] = { 0.0, 1.0, 2.2, 0.3, 0.45, 0.666, 888.99,
-1.0, -2.2, -0.3, -0.45, -0.666, -888.99 };
char szBuf[20];
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroF( 4, 2, ad[i], szBuf ) );
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroPlusF( 4, 2, ad[i], szBuf ) );
Now, the "f" and "+f" versions seem very similar, so lets have them both call an internal function. Here are the functions, which take the buffer size, and macros that figure it out themselves. (Parallel functions are also written for e and g formats.)
char* NoLeadingZeroFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
char* NoLeadingZeroPlusFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%+*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
#define NoLeadingZeroF( width, precision, number, buf ) \
NoLeadingZeroFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
#define NoLeadingZeroPlusF( width, precision, number, buf ) \
NoLeadingZeroPlusFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
Finally the (internal) function that does the work. Note that snprintf() needs a prepended underscore on Windows, but not on Unix.
char* NoLeadingZeroFmtN( char* szFmt, int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
#ifdef WIN32
_snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#else
snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#endif
// Some snprintf()'s do not promise to NUL-terminate the string, so do it ourselves.
szBuf[ iBufLen - 1 ] = '\0';
// _snprintf() returns the length actually produced, IF the buffer is big enough.
// But we don't know it was, so measure what we actually got.
char* pcTerminator = strchr( szBuf, '\0' );
for ( char* pcBuf = szBuf; *pcBuf && *pcBuf != '.'; pcBuf++ )
if ( *pcBuf == '0' ) {
memmove( pcBuf, pcBuf + 1, pcTerminator - pcBuf );
break;
}
return szBuf;
}
The output is:
.00
1.00
2.20
.30
.45
.67
888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
+.00
+1.00
+2.20
+.30
+.45
+.67
+888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
Additional testing should verify that the functions work with buffers that are too small.
It looks there is no easy solution. I would probably use something like code below. It is not the fastest method, however it should work with many different formats. It preserves number of char and position of dot too.
#include <stdio.h>
void fixprint(char *s)
{
size_t i;
i = 1;
while (s[i]=='0' || s[i]==' ' || s[i]=='+' || s[i]=='-') {
if (s[i]=='0') s[i]=' ';
i++;
}
}
int main()
{
float x = .23;
char s[14];
sprintf(s,"% 8.2f",x);
fixprint(s);
printf("%s\n",s);
}
You can not do this using printf() So how can you achieve this perfectly?
Here is my solution.
sprintf() => to convert float to string.
#include <stdio.h>
#include <string.h>
int main()
{
char result[50];
float num = 0.23;
sprintf(result, "%.2f", num);
char *str = result;
int n = strspn(str, "0" );
printf("Trimmed string is %s ", &str[n]);
return 0;
}
Output
Trimmed string is .23

How to manually convert decimal value to hexadecimal string in C?

n.b. I know that this question has been asked on StackOverflow before in a variety of different ways and circumstances, but the search for the answer I seek doesn't quite help my specific case. So while this initially looks like a duplicate of a question such as How can I convert an integer to a hexadecimal string in C? the answers given, are accurate, but not useful to me.
My question is how to convert a decimal integer, into a hexadecimal string, manually. I know there are some beat tricks with stdlib.h and printf, but this is a college task, and I need to do it manually (professor's orders). We are however, permitted to seek help.
Using the good old "divide by 16 and converting the remainder to hex and reverse the values" method of obtaining the hex string, but there must be a big bug in my code as it is not giving me back, for example "BC" for the decimal value "188".
It is assumed that the algorithm will NEVER need to find hex values for decimals larger than 256 (or FF). While the passing of parameters may not be optimal or desirable, it's what we've been told to use (although I am allowed to modify the getHexValue function, since I wrote that one myself).
This is what I have so far:
/* Function to get the hex character for a decimal (value) between
* 0 and 16. Invalid values are returned as -1.
*/
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
/* Function asciiToHexadecimal() converts a given character (inputChar) to
* its hexadecimal (base 16) equivalent, stored as a string of
* hexadecimal digits in hexString. This function will be used in menu
* option 1.
*/
void asciiToHexadecimal(char inputChar, char *hexString)
{
int i = 0;
int remainders[2];
int result = (int)inputChar;
while (result) {
remainders[i++] = result % 16;
result /= (int)16;
}
int j = 0;
for (i = 2; i >= 0; --i) {
char c = getHexValue(remainders[i]);
*(hexString + (j++)) = c;
}
}
The char *hexString is the pointer to the string of characters which I need to output to the screen (eventually). The char inputChar parameter that I need to convert to hex (which is why I never need to convert values over 256).
If there is a better way to do this, which still uses the void asciiToHexadecimal(char inputChar, char *hexString) function, I am all ears, other than that, my debugging seems to indicate the values are ok, but the output comes out like \377 instead of the expected hexadecimal alphanumeric representation.
Sorry if there are any terminology or other problems with the question itself (or with the code), I am still very new to the world of C.
Update:
It just occurred to me that it might be relevant to post the way I am displaying the value in case its the printing, and not the conversion which is faulty. Here it is:
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
(Everything in this code snip-pit works except for hexString)
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
You might wish to print out the characters you get from calling this routine for every value you're interested in. :) (printf(3) format %c.)
When you call getHexValue() with a number between 0 and 9, you return a number between 0 and 9, in the ASCII control-character range. When you call getHexValue() with a number between 10 and 15, you return a number between 65 and 75, in the ASCII letter range.
The sermon? Unit testing can save you hours of time if you write the tests about the same time you write the code.
Some people love writing the tests first. While I've never had the discipline to stick to this approach for long, knowing that you have to write tests will force you to write code that is easier to test. And code that is easier to test is less coupled (or 'more decoupled'), which usually leads to fewer bugs!
Write tests early and often. :)
Update: After you included your output code, I had to comment on this too :)
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
hexString has been allocated one byte too small to be a C-string -- you forgot to leave room for the ASCII NUL '\0' character. If you were printing hexString by the %c format specifier, or building a larger string by using memcpy(3), it might be fine, but your printf() call is treating hexString as a string.
In general, when you see a
char *foo = malloc(N);
call, be afraid -- the C idiom is
char *foo = malloc(N+1);
That +1 is your signal to others (and yourself, in two months) that you've left space for the NUL. If you hide that +1 in another calculation, you're missing an opportunity to memorize a pattern that can catch these bugs every time you read code. (Honestly, I found one of these through this exact pattern on SO just two days ago. :)
Is the target purely hexadecimal, or shall the function be parametizable. If it's constrained to hex, why not exploit the fact, that a single hex digit encodes exactly four bits?
This is how I'd do it:
#include <stdlib.h>
#include <limits.h> /* implementation's CHAR_BIT */
#define INT_HEXSTRING_LENGTH (sizeof(int)*CHAR_BIT/4)
/* We define this helper array in case we run on an architecture
with some crude, discontinous charset -- THEY EXIST! */
static char const HEXDIGITS[0x10] =
{'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
void int_to_hexstring(int value, char result[INT_HEXSTRING_LENGTH+1])
{
int i;
result[INT_HEXSTRING_LENGTH] = '\0';
for(i=INT_HEXSTRING_LENGTH-1; value; i--, value >>= 4) {
int d = value & 0xf;
result[i] = HEXDIGITS[d];
}
for(;i>=0;i--){ result[i] = '0'; }
}
int main(int argc, char *argv[])
{
char buf[INT_HEXSTRING_LENGTH+1];
if(argc < 2)
return -1;
int_to_hexstring(atoi(argv[1]), buf);
puts(buf);
putchar('\n');
return 0;
}
I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h. Very simple to use :
char* dechex (int dec);
This will use calloc() to to return a pointer to an hexadecimal string, this way the quantity of memory used is optimized, so don't forget to use free()
Here the link on github : https://github.com/kevmuret/libhex/
You're very close - make the following two small changes and it will be working well enough for you to finish it off:
(1) change:
if (value <= 9) return (char)value;
to:
if (value <= 9) return '0' + value;
(you need to convert the 0..9 value to a char, not just cast it).
(2) change:
void asciiToHexadecimal(char inputChar, char *hexString)
to:
void asciiToHexadecimal(unsigned char inputChar, char *hexString)
(inputChar was being treated as signed, which gave undesirable results with %).
A couple of tips:
have getHexValue return '?' rather than -1 for invalid input (make debugging easier)
write a test harness for debugging, e.g.
int main(void)
{
char hexString[256];
asciiToHexadecimal(166, hexString);
printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
return 0;
}
#include<stdio.h>
char* inttohex(int);
main()
{
int i;
char *c;
printf("Enter the no.\n");
scanf("%d",&i);
c=inttohex(i);
printf("c=%s",c);
}
char* inttohex(int i)
{
int l1,l2,j=0,n;
static char a[100],t;
while(i!=0)
{
l1=i%16;
if(l1>10)
{
a[j]=l1-10+'A';
}
else
sprintf(a+j,"%d",l1);
i=i/16;
j++;
}
n=strlen(a);
for(i=0;i<n/2;i++)
{
t=a[i];
a[i]=a[n-i-1];
a[n-i-1]=t;
}
//printf("string:%s",a);
return a;
//
}
In complement of the other good answers....
If the numbers represented by these hexadecimal or decimal character strings are huge (e.g. hundreds of digits), they won't fit in a long long (or whatever largest integral type your C implementation is providing). Then you'll need bignums. I would suggest not coding your own implementation (it is tricky to make an efficient one), but use an existing one like GMPlib

How to hide leading zero in printf

The following outputs 0.23. How do I get it to simply output .23?
printf( "%8.2f" , .23 );
The C standard says that for the f and F floating point format specifiers:
If a decimal-point character appears, at least one digit appears before it.
I think that if you don't want a zero to appear before the decimal point, you'll probably have to do something like use snprintf() to format the number into a string, and remove the 0 if the formatted string starts with "0." (and similarly for "-0."). Then pass that formatted string to our real output. Or something like that.
It is not possible to do it only using printf. The documention for printf says:
f - "double" argument is output in conventional form, i.e.
[-]mmmm.nnnnnn
The default number of digits after the decimal point is six,
but this can be changed with a precision field. If a decimal point
appears, at least one digit appears before it. The "double" value is
rounded to the correct number of decimal places.
Note the If a decimal point appears, at least one digit appears before it.
Therefore it seems you have to handcode your own formatter.
Just convert it to an integer with the required accuracy
double value = .12345678901; // input
int accuracy = 1000; // 3 digit after dot
printf(".%03d\n", (int)(value * accuracy) );
Output:
.123
example source on pastebin
double f = 0.23;
assert(f < 0.995 && f >= 0);
printf(".%02u\n" , (unsigned)((f + 0.005) * 100));
#include <stdio.h>
static void printNoLeadingZeros(double theValue)
{
char buffer[255] = { '\0' };
sprintf(buffer, "%.2f", theValue);
printf("%s\n", buffer + (buffer[0] == '0'));
}
int main()
{
double values[] = { 0.23, .23, 1.23, 01.23, 001.23, 101.23 };
int n = sizeof(values) / sizeof(values[0]);
int i = 0;
while(i < n)
printNoLeadingZeros(values[i++]);
return(0);
}
The Standard C library doesn't provide this, so you have to write it yourself. This isn't a rare, one-off requirement. You'll need to write similar functions sooner or later to trim trailing zeros and to add in thousands-separators. So, it pays to not just get the bytes of output you're looking for but to illustrate more generally how to write a strong library. When doing so keep in mind:
figure out how you want to call it. Something like this you write once but call
a million times, so make the calling as easy as possible.
then make the test suite
exercising all alternatives you can think of
while you're at it,
just solve the problem forevermore so you never have to come back to
it again (eg, don't hardcode width, precision, go ahead and make
versions for leading-plus, e-format, and so on)
make it
thread-safe even if you're not using threads (a specific case of
point 3, actually)
So working backwards: Thread safety requires allocating storage on the stack, which must be done from the caller. This isn't pretty or fun but just get used to it. It's the C way. Formats can have width, precision, some flags, and a conversion type (f, e, g). So lets make width and precision parameters. Rather than parameterizing the public API fully, I'll just have multiple entry points that say in the function name which flags and conversion type they use.
A pet peeve is that when passing in buffers to functions, the function will need to know the size. But if you make that a separate parameter, it's a pain in the but as 1) the caller has to write it and 2) the caller can get it wrong. So my personal style is to make a masking macro that assumes the buffer is a character array, not a pointer, and that uses sizeof() to pass the size into a more verbose version of the function taking the size.
Here's the mock-up of the simplest way I can think of to call it, with test cases.
(Note COUNT() is a macro I've used weekly for decades to get the number of elements in an array. Standard C, should have had something like this.)
(Note I use a dialect of "Hungarian Notation" here. "d" is a double. "a" is "array of." "sz" is a NUL-terminated string buffer, while "psz" is a pointer to one. The difference between these two is that "sz" can be used with COUNT() or sizeof() to get the array size, while "psz" cannot. "i" is an integer and the specific variable "i" is used for looping.
double ad[] = { 0.0, 1.0, 2.2, 0.3, 0.45, 0.666, 888.99,
-1.0, -2.2, -0.3, -0.45, -0.666, -888.99 };
char szBuf[20];
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroF( 4, 2, ad[i], szBuf ) );
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroPlusF( 4, 2, ad[i], szBuf ) );
Now, the "f" and "+f" versions seem very similar, so lets have them both call an internal function. Here are the functions, which take the buffer size, and macros that figure it out themselves. (Parallel functions are also written for e and g formats.)
char* NoLeadingZeroFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
char* NoLeadingZeroPlusFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%+*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
#define NoLeadingZeroF( width, precision, number, buf ) \
NoLeadingZeroFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
#define NoLeadingZeroPlusF( width, precision, number, buf ) \
NoLeadingZeroPlusFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
Finally the (internal) function that does the work. Note that snprintf() needs a prepended underscore on Windows, but not on Unix.
char* NoLeadingZeroFmtN( char* szFmt, int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
#ifdef WIN32
_snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#else
snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#endif
// Some snprintf()'s do not promise to NUL-terminate the string, so do it ourselves.
szBuf[ iBufLen - 1 ] = '\0';
// _snprintf() returns the length actually produced, IF the buffer is big enough.
// But we don't know it was, so measure what we actually got.
char* pcTerminator = strchr( szBuf, '\0' );
for ( char* pcBuf = szBuf; *pcBuf && *pcBuf != '.'; pcBuf++ )
if ( *pcBuf == '0' ) {
memmove( pcBuf, pcBuf + 1, pcTerminator - pcBuf );
break;
}
return szBuf;
}
The output is:
.00
1.00
2.20
.30
.45
.67
888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
+.00
+1.00
+2.20
+.30
+.45
+.67
+888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
Additional testing should verify that the functions work with buffers that are too small.
It looks there is no easy solution. I would probably use something like code below. It is not the fastest method, however it should work with many different formats. It preserves number of char and position of dot too.
#include <stdio.h>
void fixprint(char *s)
{
size_t i;
i = 1;
while (s[i]=='0' || s[i]==' ' || s[i]=='+' || s[i]=='-') {
if (s[i]=='0') s[i]=' ';
i++;
}
}
int main()
{
float x = .23;
char s[14];
sprintf(s,"% 8.2f",x);
fixprint(s);
printf("%s\n",s);
}
You can not do this using printf() So how can you achieve this perfectly?
Here is my solution.
sprintf() => to convert float to string.
#include <stdio.h>
#include <string.h>
int main()
{
char result[50];
float num = 0.23;
sprintf(result, "%.2f", num);
char *str = result;
int n = strspn(str, "0" );
printf("Trimmed string is %s ", &str[n]);
return 0;
}
Output
Trimmed string is .23

Resources