简体   繁体   中英

Read a double number from stdin, with C read()

According to the Linux manual ,

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.

I am writing a C program that uses "read" (instead of scanf) to read a double from stdin. Below is what I get. I typed inputs such as 42.0, 47.9, etc from the console. It turns out that the program produces random outputs. Can anyone help?

#include <stdio.h>
#include <unistd.h>

int main(){
    double x;
    read(0, &x, sizeof(x));
    printf ("Results = %g\n", x);
}

Input on standard input (please use STDIN_FILENO instead of the "magic number" 0 ) is usually text .

You attempt to read the input as a raw binary representation of the value.

Unless you know that the input will be in raw binary form (for example from redirection of a binary file or from a pipe where the other end is writing raw binary data) I suggest you read into a character buffer, make sure the buffer is null-terminated (you have to do it yourself, the position is what read return if successful), and use eg sscanf or strtod to convert the string.

As the manual says, attempts to read up to count bytes from file descriptor fd and that means for a double for example to read sizeof (double) bytes with the internal format representation of a double value. As it says it reads bytes, those bytes can be generated by a corresponding write(2) of a double value, but are only understandable by the machine, so entering 24.2 is not valid, as that is a string representation of a number in ascii decimal form.

There's a standard binary representation for internal use on extended use, described in the IEEE-752 standard. It describes internal binary format representations for float , double and extended long doubles (128bit representation of a floating point number, normally not used in current architectures, but only a small set) If you know it, probably you can produce the exact representation needed to be able to input correctly a specific number. You should read that document in order to understand why the sequence of chars 2 , 4 , . , 2 , that form the string 24.2 is not the same as the internal binary representation of that number, which is what is written by write(2) .

Try to write(2) that first, with:

double number = 3.1415926535897932;
write(1, &number, sizeof number);

and see what happens in your output. Next try to filter up with a hex reader, as in

$ new_program | hd

and you'll see the exact values of the bytes that pi produces. Then, try to feed that to your original program, as in

$ new_program | your_original_program

and print them again with

read(0, &my_double, sizeof my_double);
printf("%g", my_double);

you'll see that what was read is what you wrote, but the binary representation of a double value is, in general, misunderstandable for humans (well, there's people so used to binary that understand hex dumps up to this level, but I'm not one of them)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM