-1

C program takes float value as command line argument, so need to format from string to float and then to integer. Using round() from math.h, and then want to cast to int.

Casting by declaring (int) before value, but value type does not change.

Code below:

double *f = (double *) malloc(sizeof(double));
*f = (int)roundf(atof(argv[1]));
printf("Testing f: %d", *f);

make gives this error message:

format specifies type 'int' but the argument has type 'double'
      [-Werror,-Wformat]
    printf("Testing f: %d", *f);
dbush
  • 205,898
  • 23
  • 218
  • 273
azochz
  • 1,006
  • 4
  • 12
  • 20
  • What type should be changing? Also why are you casting at all? – UnholySheep Apr 28 '17 at 19:15
  • trying to change *f from type float to type int – azochz Apr 28 '17 at 19:16
  • 2
    You can't change a type at runtime - C is a statically typed language – UnholySheep Apr 28 '17 at 19:16
  • You can specify rounding direction (up/down) with `fenv`. The typical round `.5` up to the next integer value can be expressed (when rounding `fv` as the float value to integer `v`) as `v = (int)(fv > 0 ? fv + .5 : fv - .5);` to handle both positive and negative cases. – David C. Rankin Apr 28 '17 at 20:45
  • @DavidC.Rankin `v = (int)(fv > 0 ? fv + .5 : fv - .5);` is a problem (wrong answer) for a number of values of `fv` when the `fv + .5` incurs a rounding before the cast `(int)`. C has functions that do the conversion better: `round(), rint(), lround(), nearby()`. – chux - Reinstate Monica Apr 28 '17 at 21:15
  • Yes, I should qualify that by saying the purpose of the math library functions are to provide protections against a number of cases that do not work with a simple ternary, namely `INF`, `NAN`, etc. Good catch. I guess `typical` was not apparent enough to explain the comment was by way of an example. – David C. Rankin Apr 28 '17 at 21:19

3 Answers3

3

You're putting int into double. The f variable should be of type int.

int f;
f = (int)roundf(atof(argv[1]));
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
martin49
  • 182
  • 2
  • 8
1

C has a direct way to round and convert a float to an integer type

long int lround(double x);

The lround and llround functions round their argument to the nearest integer value, rounding halfway cases away from zero, regardless of the current rounding direction. ... C11 7.12.9.7 2


#include <math.h>
#include <stdlib.h>

long i = lround(atof(argv[1]));
// or 
float f = atof(argv[1]);
long i = lroundf(f);

// Use %.0f to print a FP with no factional digits.
printf("%.0f\n", f);

// Use %ld to print a `long`
printf("%ld\n", i);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

The error is in the %d format specifier in the printf function:

printf("Testing f: %d", *f); /* %d expects an integer but *f is a double */

It doesn't matter that *f contains a rounded number, it is still a double as far as printf is concerned.

Try this:

printf("testing f: %d", (int)*f);

N.B. why you are going to the trouble of using malloc to allocate a single double? If you need to pass just one double to some other program, you could just have:

double f;
... stuff ...
foo(&f);