[Courses] Fwd: Re: C Programming For Absolute Beginners, Lesson 2: Fun With Printf, Scanf, Puts, and Variables
Carla Schroder
carla at bratgrrl.com
Wed Feb 22 00:10:14 UTC 2012
Here is some interesting stuff from Jim on stdin, stdout, stderr, fgets, and
fputs. Have fun!
Carla
Here are some links about std in, out, err:
General
http://en.wikipedia.org/wiki/Standard_streams
Mainly shell use
http://people.ischool.berkeley.edu/~kevin/unix-tutorial/section10.html
http://www.codecoffee.com/tipsforlinux/articles2/042.html
Shell and C
http://www.cs.bu.edu/teaching/c/file-io/intro/
C-specific
http://en.wikipedia.org/wiki/C_file_input/output
http://icecube.wisc.edu/~dglo/c_class/stdio.html
http://www.cprogramming.com/tutorial/cfileio.html
http://www.mrx.net/c/program.html
------------------------
I want to give it a try. The following augments the last four
links above.
// readtxt.c 20120221 jim at well.com james stockford
// demonstrates how to read text from a file
#include <stdio.h>
int main()
{
FILE *myfile;
char mybuffer[81];
myfile = fopen("/home/jim/.bashrc","r");
fgets(mybuffer, 81, myfile);
puts(mybuffer);
fputs(mybuffer, stdout);
fputs(mybuffer, stderr);
fclose(myfile);
}
I recall the saying "everything in unix is a file". Not very
helpful, I tho't when I first heard it.
A file is defined as a stream of bytes.
There are two categories:
* files with bytes that are only ASCII (values from 0 to 127), meant
to be interpreted as text, and
* files with bytes that are fully binary (values from 0 to 255), used
for everything but text, for example, a pixel might be described as
three or four bytes, and a file might contain information about a lot
of pixels.
Beginning examples stick to ASCII text files, and C has functions
designed to work with just text files as well as functions designed
to work with fully binary files.
#include <stdio.h> // the stdio.h file for basic file handling
To open a file is to ask the kernel to do the work and return
a number that represents the file.
FILE *myfile; // FILE * says myfile can store a number for a file
// the * means myfile stores an address, ignore for now
I have to have a place in memory where my program can store a
line of text from the file. The following tells the gcc to create
an array of 81 bytes in memory with the name mybuffer.
char mybuffer[81];
myfile = fopen("/home/jim/.bashrc", "r"); // fopen asks the kernel
// to open the .bashrc file in my home directory in read-
// only mode
// myfile stores the number that the kernel returns
I use the fgets function to read a line of text from the file.
fgets(mybuffer, 81, myfile); // the fgets function is designed to
// interpret its three arguments as
// the address of a storage area in memory
// the maximum number of characters to read
// the number of an open text file
The fgets function asks the kernel to give it bytes from the file
until one of the bytes is a newline character or the total number of
bytes is 81.
The name fgets has three distinctive parts:
"f" means "file"
"get" means read some bytes
"s" means this function is designed to work with text strings
I want to prove to myself that my program really did read a line
of text from the /home/jim/.bashrc file. Here are three ways to do
that; all three print a line of text to the terminal.
puts(mybuffer);
fputs(mybuffer, stdout);
fputs(mybuffer, stderr);
The name puts has two parts, the name fputs has three parts.
The difference in the names is the "f" and the difference in the
arguments is stdout or stderr.
The puts (put string) function has got the stdout information
built in. It can only write to the standard output.
The fputs function does not have any file information built in
and requires the number of some open text file; I chose to use
stdout in one call and stderr in the subsequent call. The stdio.h
file declares stdout and stderr to be FILE type, and the magic is
that there's no need to ask the kernel for a number (no fopen call).
There are three names for standard output "files".
stdin (standard input) has a value of 0
stdout (standard output) has a value of 1
stderr (standard error) has a value of 2
Here's where "everything is a file" comes in handy.
* The keyboard is a file, a stream of bytes (the stuff I type)
with a guaranteed file number of 0. It's a read-only file.
* The display (the terminal window) is a file with a guaranteed
file number of 1 that is write-only; programs send streams of
bytes to the terminal window.
* The display (the terminal window) also has a guaranteed file
number of 2. It's a write-only file to which programs send
streams of bytes.
Using stderr instead of stdout seems to work the same, both
send the line of text to the display. But stdout and stderr are
different files. I use redirection in the shell to verify.
Using normal redirection, the output of my program stores
the puts and stdout output to ofile and displays only the stderr
output.
$ a.out > ofile
# ~/.bashrc: executed by bash(1) for non-login shells.
$ ls
ofile
Redirecting standard error, the output of my program stores
the stderr output to efile and displays the puts and stdout
output.
$ a.out 2> efile
# ~/.bashrc: executed by bash(1) for non-login shells.
# ~/.bashrc: executed by bash(1) for non-login shells.
$ ls
efile ofile
I've asked the kernel to open the /home/jim/.bashrc file and
the kernel keeps that file open until I ask it to close it.
fclose(myfile);
These standard input, output, and error techniquest don't work
with GUI programs.
-----------------------
About the * character. It's sometimes called "splat" and can
either represent the multiplication operator or the dereference
(aka "indirection") operator.
int x = 5 * 6; // multiplication, spat is between to operands
FILE *myfile // dereference, splat is to the left of one operand
Here splat means that myfile stores the address of a value that
is the address of a FILE type.
char *mystring
Here splat means that mystring stores the address of a value
that is the address of a single character.
Above, myfile is a pointer to a FILE type and mystring is a
pointer to a character. Note that the term "pointer" means an
identifier that stores an address.
On Tue, 2012-02-21 at 11:26 -0800, Carla Schroder wrote:
> On Tuesday, February 21, 2012 12:29:35 PM Kathryn Hogg wrote:
> > On 2012-02-21 12:26, Christopher Howard wrote:
> > > Some discussion should probably be made of buffering issues that can
> > > occur while mixing reading and writing on the command-line. I.e., the
> > > program might start waiting for the user input before it actually
> > > prints
> > > out the line telling the user what to enter. It's been a long time
> > > since
> > > I have had to deal with this (normally user input is provided through
> > > the program arguments). However, I think it involves flushing
> > > stdin/stdout buffers with fflush().
> >
> > Reading from stdin (which is what scanf is doing) will cause stdout to
> > be flushed.
>
> Excellent, this is exactly the sort of clear, pertinent explanation that I
> like, and try to write myself. (This was rather a half-baked lesson so it
> needs help.)
>
> Anyone who does not have a good understanding of stdin and stdout should
look
> them up because they are fundamental to all computing.
>
> And remember, there are no stupid questions-- don't be shy!
>
> Carla
>
-----------------------------------------
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Carla Schroder
ace Linux nerd
author of Linux Cookbook,
Linux Networking Cookbook,
Book of Audacity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More information about the Courses
mailing list