Converting a number from a given base to base 10 - c

I am trying to convert from any base to base 10. For an input of 010111 base 2 it gives me 1, and for 35 base 9 it gives me 18 which should be 38. Any suggestions?
#include<stdio.h>
#include<math.h>
#include<string.h>
#define LENGTH 6
double pow( double x, double power );
int main()
{
char input[LENGTH+1] ;
int base;
unsigned decValue ;
char values[] = "0123456789ABCDEFG";
int i;
puts( "Enter a value, and its base: " );
scanf( "%s", &input );
scanf( "%i", &base );
for( i = LENGTH-1 ; i >= 0; i-- )
{
int index = strchr(values, input[ i ] ) - values;
decValue += index * pow( base , i - LENGTH + 1 );
}
printf( "%s (base-%u) equals %u \n", input, base, decValue );
return 0;
}

The thing that troubles me here the most is your mixture of floating point arithmetic into an integer problem. Not only is it less efficient, but when the result is converted back to an int, there's the possibility it might get rounded down or something silly. Hypothetical example:
double n = pow(2,3); //becomes 7.99999999999999999999999 for some silly reason
int in = n; //rounds down to 7
Although this might not even be happening in your case, be wary of integer <-> floating point conversions, and avoid them when they are unnecessary.
A better solution is to build up the power incrementally. If I were you, I'd iterate from beginning to end of the number. Pseudocode:
let s be the input string's digits;
let r be the radix;
let n be the resulting number;
n=0;
for (i=0; i<s.size(); i++) {
n *= radix;
n += s[i];
}
The concept is that you are picking up digits and shifting them into the number. E.g. 123 in decimal:
1
(shift 1 left, then add 2)
12
(shift 12 left, then add 3)
123
Shifting left, in the context of integers in a given base, is simply multiplying by the radix.

Since i < LENGTH, i - LENGTH + 1 is negative and the pow is therefore 0.
So, you should use pow( base , LENGTH - i - 1 ) -- that one's the biggie. Other big bugs: you should use strlen(input) wherever you're using LENGTH; and you should initialize decValue to 0. There may be others, I stopped looking after the first three (this IS after all California, land of the "Three Strikes, You're Out" law;-).

My suggestion: Dont reinvent the wheel.
See strtoul function:
#include <stdlib.h>
#include <stdio.h>
int main(){
/* first arg: number in base n to convert to base 10
* third arg: base n
*/
long int b10= strtoul("111",NULL,2);
printf("%ld\n",b10);
return 0;
}

You're adding to decValue before you ever assign anything to it. I didn't look too closely at your logic but that stood out immediately. Depending on platform that may cause you issues.

A few comments:
As written, your code doesn't support "any base", only bases up to 17 (an odd place to stop).
strchr() can return NULL. You should never assume that it won't, especially when you're feeding it direct user input.
Lowercase letters are nice, and you should support them. Simply convert the relevant character to uppercase with toupper(), and then you can recognize both a and A as hexidecimal 10.
In the interest of coding practices, I would suggest creating a function to perform the relevant conversion, rather than doing all the dirty work in main().
If you're doing this as a learning exercise, ignore this paragraph, but you appear to essentially be rewriting the standard library function strtol(), which converts a string to a long for arbitrary bases. It's pretty nice, actually, and has some functionality that you could incorporate into your code if you wanted.

Couple things: don't take the address of input (input, an array, already degrades to the pointer you want; taking a pointer of it will result in a pointer to an array, not what you want); and you need to make sure not to overflow the input buffer when reading into it.
If this is not homework, you should just use strtol():
#include <stdlib.h>
#include <stdio.h>
#define Str(x) #x
#define Xstr(x) Str(x)
int main()
{
char input[LENGTH+1] ;
int base;
long decValue;
char *endptr;
puts( "Enter a value, and its base: " );
scanf( "%" Xstr(LENGTH) "s", input ); /* reads at most LENGTH characters */
scanf( "%i", &base );
decValue = strtol( input, &endptr, base );
assert( *endptr == '\0' ); /* if there are any characters left, then string contained invalid characters */
printf( "%s (base-%u) equals %ld\n", input, base, decValue );
return 0;
}

Related

bits and arrays in C - New to programming

I have a given code from school, I need this as my output:
Digital Binair
0 is 000,
1 is 001,
2 is 010,
3 is 011,
4 is 100,
5 is 101,
6 is 110,
7 is 111
(3 bits)
I need to work with for loops, this is the given code:
#include <stdio.h>
#include <string.h>
#define ZERO '0'
#define ONE '1'
int main(void)
{
char rij[8][4];
int n, m;
strcpy( rij[0], "000" );
printf( "%s\n", rij[0] );
for ( n=1; n<8; n++ )
{
strcpy( rij[n], rij[n-1] );
printf( "%s\n", rij[n] );
// *ONLY ABLE TO TYPE IN HERE !!!! THE REST IS GIVEN !!!!*
}
for( n=0; n<8; n++ )
{
printf( "%i %s\n", n, rij[n] );
}
return 0;
}
I'm stuck at is how do I make a for loop that is working with bits. So lets say for(n = 0; n < 8; n++) how do I make the loop go form 000 to 001 to 010.
While there are many ways of generating a binary sequence, here the task appears to have been deliberately complicated (or made interesting) by the constraint that you modify code only at the location indicated and the initialisation of each successive string with the content of the previous one.
The arrays serve no purpose other than to make you think - it is a purely academic exercise, not a practical application. Each string is initialised with the content of the previous string (which the code you must add will have modified), the intent of the exercise is that you perform a binary "add 1" at each iteration.
To do that, starting from the LSB (rij[n][2]), if the digit is ZERO you set it to ONE, then move to the next n, else you set it to ZERO, and "carry" one, repeating the above process for the next most significant bit in the string n.
You can do that in a loop from the LSB (2) index to the MSB (0) index, and exiting the loop (break) when you set any bit to ONE.
Or for just three digits you can unroll-the loop thus:
if( rij[n][2] == ZERO )
{
rij[n][2] = ONE ;
}
else
{
rij[n][2] = ZERO ;
if( ... // test next bit [1] - enough of a hint I think.

fprintf that uses constant space

I have the problem with fprintf. What I want is to use as much of space as possible staying in the same column but that means changing amount of decimal floating numbers. I have a bit problem to describe it so maybe just example:
0.001234
0.123456
1.234567
12.34567
123.4567
I tried to play with g and f options but it didn't work for me (i.e. things like %8.6g or %8.6f).
This is a tricky to survive corner cases.
With different precision specifiers, the number of digits of the left side of the decimal point changes.
printf("%.3f", 9.996) --> "9.996";
printf("%.2f", 9.996) --> "10.00"; // Same print width with different precision.
Given the various rounding modes, +/- numbers, NaN, INF, and details of the typical binary representation of floating point numbers, attempting to predict the width a printf() for a given floating point number is, at best, an approximation. Rather than out-think printf(), simple sprintf() with a best guess precision. Use sprintf() return value and adjust the precision as needed.
Solution:
Estimate width.
Print to a buffer.
Adjust if needed.
.
#include <float.h>
int fprintf_Width(FILE *outf, double a, int width) {
// Subtract 2 for a potential leading "0."
int prec = width - 2;
if (prec < 0 || prec > 100 /* TBD upper bound */)
return 0; // `width` out of range
// By some means, determine the approximate precision needed.
char buf[1 + 1 + DBL_MAX_10_EXP + 1 + prec + 1];
int len = sprintf(buf, "%#.*f", prec, a);
prec -= len - width;
if (prec < 0)
return 0; // `a` too big
// Try it out
len = sprintf(buf, "%#.*f", prec, a);
// Adjust as needed
if (len > width) {
prec--;
if (prec < 0)
return 0; // `a` too big
sprintf(buf, "%#.*f", prec, a);
}
len = fprintf(outf, "%s", buf);
return len;
}
Acknowledgement: This approach fails with certain numbers with certain width-specifications, as pointed out in the comments.
One thing you could do is to calculate the amount of digits before the decimal point, and then use the printf Precision Specification to truncate the digits that would make the number too long.
You could create a custom function, taking the FILE pointer to use with fprintf, float nubmer that you want to print and the desired amount of characters you want to have; 3 arguments.
The next thing you should do is to determine the amount of digits there before the decimal point. Having a new int variable and putting the float you have into it, then dividing the new int by 10s until it is zero should do it. But beware, 0.001234 also has one digit before the decimal point, although its int evaluation would not show one.
Then all you'd have to do is to reduce the width received by the amount of digits before the decimal point, plus 1 for the decimal point itself (or rather minus in this case), and this shall be your Precision Specification for the fprintf you'll use.
So, in the end, your fprintf should look somewhat like this with this method:
fprintf( fp, "%.*f", Width - digitsbeforeDpoint - 1 );
Here is an example that I've done, working as far as I can test. It also has some further precautions, making sure that every input is reasonable and assuring that the float given is qualified to print out the amount of digits you'd desire:
#include <stdio.h>
void fixdLengthfprintf( FILE * _File, float a, int width ) {
if ( !_File ) return;
if ( width < 3 ) return;
int b = a;
do {
width--;
b /= 10;
} while ( b );
width--;
if ( width > 0 ) fprintf( _File, "%.*f\n", width, a );
}
int main( ) {
float numbers[7] = { // prints as:
1.123456, // 1.123456
12.1234567, // 12.12346 (apparently rounded)
123456.0123456, // 123456.0 (heavily rounded)
1234567.0123456, // doesn't get printed
12345678.0123456, // doesn't get printed
123456789.0123456, // doesn't get printed
0.123456789, // 0.123457
};
// I don't allow them to get printed because else they'd look like:
// 1.123456
// 12.12346
// 123456.0
// 1234567
// 12345678.000000
// 123456792.000000
// 0.123457
for ( int i = 0; i < 7; i++ ) fixdLengthfprintf( stdout, numbers[i], 8 );
fflush( stdin );
getchar( );
return 0;
}

odd numbers in language C? pb 'ram or algorithm'!

This program gives us the position of the odd numbers in a given integer, this program works well, but when I give him an integer in its numbers are greater than 10 -like 123456789123-, it doesn't work.
I do not know if is a problem of ram or algorithm ?
#include<stdio.h>
#include<stdlib.h>
main(){
int a,b;
int i = 0;
scanf("%d",&a);
while(a/10!=0){
b=a%10;
if(b%2!=0)
printf("\nodd number position: %d",i);
a=a/10;
i++;
}
if(a%2!=0)
printf("\nodd number position: %d",i);
system("pause");
}
The problem is one of processor (architecture) rather than RAM. On your platform the size of an int seems to be 32 bits which cannot hold a number as large as 123456789123. As Groo commented to Raon, you could use a string instead (if you don't plan to do any calculations on the number):
char a[1024] = {0}; /* should be plenty, but extend the array even more if needed */
fgets(a, sizeof a, stdin); /* fgets is recommended as it doesn't overflow */
int i, length = strlen(a);
for(i = 0; i < length; i++){
/* count your odd digits here
left as an exercise to the reader */
/* note that you must access the individual digits using a[i] */
}
Every data type is limited to specific range.for example char is limited to range -128 to 128. if you use the beyond this range. You might get unexpected results.
In your program if you give any number which is beyond the range of integer, then you will get unexpected results
if your int size is 4 byte/32-bit you can give input with in this range –2,147,483,648 to 2,147,483,647
if Your int size is 2 byte/16-bit you can give input with in this range –32,768 to 32,767
Check this Data Type Ranges.
And if you want to give large Numbers You can declare variable as long int/long long int
and don't forgot to change format specifier when using long int(%ld) and long long int(%lld)
You can also use string and check whether all characters are digits are not by using isdigit() function in ctype.h header and convert character digit into integer digit by substracting '0'(character zero). and check whether is that odd or not.
The problem is that 123456789123 exceed the storage limit for an integer data type,
try using a string to store the value and parse it, something like
#include<stdio.h>
int main(){
char a[] = "12345678912345678913246798";
int i = 0;
for (i=0; a[i] != '\0'; i++){
if ( a[i] % 2 != 0 ) printf("%c is odd\n", a[i]);
}
return 0;
}
#include<stdio.h>
void main() {
int i;
char s[256];
scanf("%s",s);
for( i=0; s[i]!=0; ++i ) {
/*int digit = s[i]-48;
if( digit%2==1 ) break;
- or even shorter: */
if( s[i]%2==1 ) break;
}
if( s[i]!=0 )
printf( "First odd digit position: %d", i );
else
printf( "All digits are even" );
}
Here is working sample: http://cfiddle.net/sempyi
I think this program will not give proper answer if you give more than 10 digits! please correct me if I am wrong.
The max Unsigned integer value is 4294967295 (in any 32 bit processor). if the given value is more than that then it will either limit to that max value or overflow will happen. So if you give a integer which is more than 4294967295 it will not work as it supposed to.
try printing the input. In that case you will know whether complete number is sent or Max number is sent to find the odd number's position.
One way to make it work is read the input number as array of characters and then try to figure out the odd number position.
Note: for signed integer maximum is 2147483647
123456789123 is 0x1CBE991A83
so if int is 32 bit, your number is truncated (to 3197704835 or 0xBE991A83).
Number you are giving input is greater than range of int. You need to change the data type Below link should help you.
http://www.tutorialspoint.com/ansi_c/c_basic_datatypes.htm
You need to choose a data type that matches the expected data range.
If you want your program to work for any number it is probably best to read the number one character at a time.
Code (not that in this code, position is counted with the most significant digit = 1, which is the other direction compared to your code):
int c;
unsigned long long pos = 0;
while (++pos) {
c = getc();
if (c < '0' || c > '9') break; // Not a digit
if ((c - '0')%2 != 0) {
printf("\nodd number position: %ulld", pos);
}
}
The code can handle numbers that have a ridiculus amount of digits. Eventually the pos variable will overflow, though.

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 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