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
Related
In c language,
for example:
if value double x = 3.4900
I want output be 3.4900, not 3.490000
The problem is the input value x is changeable, I don't how many decimal point will be.
any idea?
to make an answer:
double x = 3.4900;
printf("the value of x is %.4f",x);
.4 means, you print the value with for digits after the dot. If you want to print exact and changeable number of digits you read in, you had to work with a string.
double x = 3.4900; is exactly the same as double x = 3.49;
When you ask about "input", you might mean "reading a value as a string from a file or stdin"... You could count the digits to the right of the decimal point and store that count in another variable.
Once that string is converted to double, there is no record of how much 'precision' was supplied by the source.
And, because floats and doubles use base-2 numbers (not base-10), it is extremely rare that the internal representation matches the base-10 version (without some rounding involved.)
Note in the following the 'extra effort' to determine the precision from the pseudo-input string...
int main() {
char *s1 = "3.4900";
char *s2 = "3.49";
double d1 = strtod( s1, NULL );
double d2 = strtod( s2, NULL );
printf( "%s\n", d1 == d2 ? "Same" : "Diff!!" );
char *cp = strchr( s1, '.' ) + 1;
int prec = strlen( s1 ) - (cp - s1);
printf( "s1 restores as %.*lf\n", prec, d1 );
return 0;
}
any idea?
C programming language does not have reflection - it's not possible to inspect itself. If you want to have the ability to inspect the source code of a C program from that C program itself, you have to implement such functionality yourself.
how to print double exactly as input in C
You have to include verbatim the stringifed form of the input inside your source code and print that.
double x = 3.4900;
const char *xstr = "3.4900";
printf("source code %s was translated into %f\n", xstr, x);
With the help of # preprocessor operator, we could make it a bit nicer and don't repeat ourselves:
struct double_and_string {
double x;
const char *str;
};
#define VAL_AND_STR(x) { x, #x }
struct double_and_string a = VAL_AND_STR(3.4900);
printf("source code %s was translated into %f\n", a.str, a.x);
double x = 3.4900;
printf("the value of x is %lf",x);
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.
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;
}
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
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;
}