Why is there no dscanf function for reading from file descriptors?
We have fprintf, sprintf and dprintf for printing but for scanning there is only fscanf and sscanf.
It is not possible to write dscanf.
The scanf family requires that the stream is buffered, or else that it is capable of putting back a character that was read. POSIX file descriptors are neither.
Consider this stream
1234xyz
How would you scan a number off it? You cannot read it byte by byte and stop just before x. That would require clairvoyance. You also cannot read x and decide you don't need it, because you cannot put it back.
Because the printf and scanf family of functions is part of the C language, the functions handling file descriptors are not. Instead they are part of the operating system API (on POSIX platforms like Linux or OSX, other platforms emulate these system calls).
And the dprintf function is not a standard C function, it's an extension. From this printf (and family) manual page:
The dprintf() and vdprintf() functions were originally GNU extensions that were later standardized in POSIX.1-2008.
That there's no dscanf function is probably just an oversight from those who made the original dprintf extension.
Related
I'm programming with gcc in CentOS 5.5 and the most of time I use printf() and fprintf() to print on terminal, but in some websites I've seen that some people use write(). I want to know if there's other ways to print on terminal.
Thanks.
There are some major differences between these functions.
The standard library provides some functions to output to stdout: printf, puts, putchar etc.
And some functions to output to a stream, you can specify the stream to stdout: fprintf, fputs, fwrite, etc.
But write is different, it's a low-level I/O function. The
standard library doesn't provide any low-level I/O functions. For
example, POSIX provides write that can output to a file
descriptor.
Google for how to use each one of them.
You could use puts() or putchar().
puts("Hello, world!\n");
There's a also fputs(), putc(), and fputc() if you want/need to specify a FILE* to write to.
All the output functions in the C standard I/O library could be used:
fprintf()
fputc()
fputs()
fputwc()
fputws()
fwprintf()
fwrite()
printf()
putc()
putchar()
puts()
putwc()
putwchar()
vfprintf()
vfwprintf()
vprintf()
vwprintf()
wprintf()
Most of the other write-like functions in POSIX could be used (but a few are reserved for sockets and those probably can't be used).
aio_write()
dprintf()
putc_unlocked()
putchar_unlocked()
pwrite()
vdprintf()
write()
writev()
There are many functions in the curses library that could be used.
I'm using a system function which writes the output information into a stream of file pointer.
func(FILE *__fp)
I need to use this information in my program rather than printing this out to a file. For that I thought of creating a tmpfile() and writing to it then reading back from it. But is there a better way to get this information?
There are OS-specific solutions to writing to a memory buffer instead of a file, like for example the POSIX fmemopen or open_memstream (both which should be very useful considering your linux tag).
You can also change the internal buffer to your own with setvbuf.
On an unrelated note: Symbols starting with a leading underscore and followed by another underscore (like for example your __fp argument) are reserved. Such symbols may only be used by "the implementation", i.e. the compiler and library.
Experts I've doubts in gets(),puts() and getch().
Why do we use gets() and puts() when we have scanf() and printf()?
What is the use of getch().
Please explain this in simple language because I'm a beginner.
THank you in advance. :)
gets doesn't exist anymore (except in outdated environnments such as the infamous TurboC), use fgets instead.
fgets reads one line of text from a file including from the terminal (standard output)
puts writes one line of text to the terminal (standard output)
fputs writes one line of text to a file, including the terminal (standard output)
getch reads on character from the standard input (terminal)
printf and friends allow you to print formatted output
scanf and friends allow you to read formatted input.
Why do we use gets() and puts() when we have scanf() and printf()?
We don't use gets(), the function was so poorly designed that it was flagged obsolete 18 years ago and finally completely removed from the C language 6 years ago. If someone taught you to use gets(), you need to find a more updated source of learning. See What are the C functions from the standard library that must / should be avoided?.
puts(str) is only used as a micro-optimization of printf("%s", str). puts() is traditionally ever so slightly faster than printf(), since it doesn't need to parse a format string. Today, this performance benefit is a non-issue.
However, puts() is much safer than printf(). You can write bad code like printf("%s", pointer_to_int) and it might compile without warnings. But puts(pointer_to_int) will never compile without warnings/errors.
Generally, most of stdio.h is dangerous and unsafe because of the poor type safety. It is avoided in professional, production-quality code. For student/hobbyist purposes, printf/scanf are however fine.
What is the use of getch()
getch() was a non-standard extension to C, which allowed programs to read a character from stdin without echoing the typed character to stdout (the screen).
This function was popular back in the days of MS DOS when Borland Turbo C was the dominant compiler. Because Turbo C had it, some other compilers also started supporting it together with the non-standard conio.h library. We're talking early 1990s.
You shouldn't use this function in modern C programming.
(Though it is possible to implement it yourself with various API calls, as in this example for Windows.)
Actually other than the core C language, there is a C library. And if my understanding is right, functions like printf are part of C library. Now I have programmed in C in Turbo C in Windows as well as using gcc in Linux.
My question is: Are the code implementations of functions like printf the same in both Windows and Linux? Ultimately the printf function has to call a function in core OS (in both cases) that would display ASCII characters onto the screen? So since both the OS are different, will the implementation of code for printf be also different in both the cases?
Of course the implementation (of printf and all functions in <stdio.h>) is different (on Linux and on Windows), but the behavior should be conforming to the specification in the C11 or C99 standard.
Notice that printf does not show characters on the screen, but send them to the standard output (see printf(3)). Something else -e.g. the kernel tty layer and your terminal emulator on Linux- is displaying the characters on your screen (or elsewhere!).
On Linux and POSIX systems, <stdio.h> is ultimately using system calls to write data to a file descriptor. It would be write(2) (for printf) and the list of system calls is available in syscalls(2). Be aware that stdout is usually buffered (notably for performance reasons; making a write syscall for every written byte would be too costly). See fflush(3) & setvbuf(3). Try using strace(1) on your Linux program to understand the actually used syscalls.
On Windows, there is some equivalent thing (except that the list of syscalls on Windows is less documented and is very different).
BTW, GNU/Linux is mostly free software. So read Advanced Linux Programming then study the source code: the libc is often glibc (but could be musl-libc, etc... so you can have several implementations of printf on Linux, but usually you have one libc.so, even if you could have several ones), the kernel source is available on kernel.org.
When using system-level IO in Linux, I noticed that the compiler recognized the O_RDONLY and O_RDWR flags, but it had no clue whatsoever as to the meaning of the O_BINARY and O_TEXT flags.
Is this a Linux thing?
Linux, and just about every flavor of Unix for that matter, doesn't differentiate between binary and text files. Thus, there are no standard constants with that name. You can manually define the constants to be zero in Linux if you want to include them in your code for portability purposes.
http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2007-03/msg00147.html
It's a *nix thing. *nix operating systems don't do automatic linefeed conversion for I/O on "text" files so O_TEXT and O_BINARY flags wouldn't make sense.
At the level of C language and its standard library, there's no such thing as O_BINARY and O_TEXT flags. The binary or text mode is selected by adding the b specifier of the mode parameter of fopen function. The specifier itself is, of course, supported by all C implementations, but on POSIX platforms this specifier has no effect: per POSIX specification the text mode is the same as the binary mode.
Not suprisingly, if you dig deeper into the level of non-standard platform-specific Unix I/O functions, you'll discover that they have no knowledge of that text/binary distinction whatsoever.
Windows uses \r\n for line endings, Linux (and other Unix-alikes) use just \n. In Windows, reading O_BINARY gives you the raw data, possibly odd line endings and all, while O_TEXT normalises the line endings, so your C code only sees a single character.
Under Linux et al, there's no point distinguishing between text and binary, because the data only has a single character anyway, so the flags are unnecessary.
There isn't a difference at the OS level between binary and text file under Unix. Text file have just a restricted content. That's also true for Windows, but the conventions used by C for the end of lines are the same as the one used by Unix, while Windows use CR/LF pair (and an explicit end of file marker in some contexts, but the handling of that was not consistent even in the system programs last time I checked), so a mapping is needed to respect the conventions mandated by C.