hakunami
hakunami

Reputation: 2441

How to tell "1.0" is a float but an integer in C language?

I have a program that accept orders by reading commands from a file. In this file some commands are "float string", like "1.0","2.0", but they are invalid, what the program need is integer, like "1","2". So, how can I make the program understand the commands like "1.0" is invalid? Is there any neat way to do this?

    char buf[CMDSIZE];
    if(fgets(buf, CMDSIZE, stdin))      //buf likes this: "1.0 \n"
    {
        *prio = 1; *command = -1; *ratio =1.0;
        // I need to make sure that command is not "1.0" or something like this              
        sscanf(buf, "%d", command);
        switch(*command){....blahblah......}
    }

Thank you.

Upvotes: 0

Views: 1971

Answers (4)

Ananthakrishna
Ananthakrishna

Reputation: 3

You can use scanf with %f to store it as a floating point value example or scan with %d to store it as an integer but it will not count the decimal

#include<stdio.h>
main()
{
float i;
int a;
printf("Enter a number which is a floating point value");
scanf("%f,%d",&i,&a);
}

here using scanf and %f we are storing it in a float variable i so 1.5,1.0 or any number with a decimal will be stored or if we only use the %d it will only store 1,2,3,4 any number without the decimal i.e if we give 2.5 it will only take 2

Upvotes: 0

RolandXu
RolandXu

Reputation: 3678

in your special case, just to check difference between 1 and 1.0 use the code:

int ret = scanf("%d.%d",&i,&j);

if inputs is 1, the scanf only assign one value, the ret is 1 if inputs is 1.0, the scanf assign two value, the ret is 2. if inputs is abcd, the scanf can't assign any value, the ret is 0

and regarding the return value of scanf, fscanf etc.

In C99 standard 7.19.6.4 The scanf function

The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure

Upvotes: 0

Dietrich Epp
Dietrich Epp

Reputation: 213318

It's easier to use strtol.

This will parse a base-10 integer. The pointer e will point to the first character after the integer. You can check to make sure it's a NUL byte and signal an error otherwise. (You also have to check that the input isn't empty.)

If you want to allow spaces / newlines after the number, you can do that too. Note that strtol eats leading whitespace -- but not trailing whitespace.

long v;
char *e;
v = strtol(buf, &e, 10);
if (!buf[0] || *e) {
    error();
}
// v has number

Footnote: Checking for overflow and underflow with strtol is a little weird. You have to set errno to 0 first, call strtol, then check if the result is LONG_MIN or LONG_MAX and if errno is set to ERANGE.

Upvotes: 3

Thomas Padron-McCarthy
Thomas Padron-McCarthy

Reputation: 27632

Both scanf("%d"....) and scanf("%f"....) will succeed and return 1 when reading the input 1.0. (sscanf works the same way.) It's just that with "%d", it will stop reading before the decimal point.

You can use the format specifier %n with sscanf to see how many characters were read, and then look if the buffer contains more stuff afterwards.

Or, which might be easier, just look at the contents in the buffer with your own code, instead of sscanf, to see if there are only digits there.

Upvotes: 3

Related Questions