Part 5 - Input
--------------
We have already discussed the different output methods available to us,
as well as what streams are.  So now let's look at the input functions.
We will begin with the gets() function.  The gets() function reads
in data from the standard input (STDIN), which in our case will be the
keyboard.  Here's the synopsis from the ANSI public draft (Jan 18, 1999
version -- n869):
                       char *gets(char *s);
       The  gets  function  reads  characters  from the input
       stream pointed to by stdin, into the array pointed to by  s,
       until  end-of-file is encountered or a new-line character is
       read.  Any new-line  character  is  discarded,  and  a  null
       character  is  written  immediately after the last character
       read into the array.
Translated, it means this:
       The gets function reads characters from stdin (Which in our case
       is the keyboard) into an array.
Fairly straightforward.  We know that in order to use gets, we need to
define an array to hold the stuff we type.  Let's do that:
       char stuff[13];  /* Make an array to hold input */
Why did I choose the number 13?  Just because I can.  :)  Actually we
are not allowed to use all 13 elements of our array for input.  If you
recall our synopsis a few paragraphs up, it says:
       ... a null character is written immediately after the last
       character read into the array.
This means that we need to reserve the last element of our array for the
null character.  So we are really only allowed to enter 12 characters
the the keyboard.  If we enter any more, we risk overwriting some other,
possibly important part of memory.  Overwriting memory can lead to many
evil things, from crashes to file corruption etc.
Let's write a program that uses the gets function:
/*------------------------------------------------------------------
 Program:       GETEXAMP.C
 Author:        CORVUS
 Date:          Aug. 30, 2001
 Description:   This is a program that gets input using gets().
------------------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  char stuff[12+1];   /* Allocate an array to hold 12 chars + 1 null */
                      /* I could put "char stuff[13]".  Preference. */
  printf("Enter your name, then press ENTER: ");
  gets(stuff);
  printf("You entered: %s\n", stuff);
  return 0;
}
This program works as long as the user doesn't type more than 12
characters.  I typed 20 characters and my computer crashed.  Very
disturbing.
Because gets() will be happy to read & store characters past the end of
the buffer, it's use is strongly discouraged.  I would never use it.
There are better alternatives.
The next function I'm going to show you is called "scanf".  This
function has gained alot of popularity.  Some people believe that this
is the only input function available to them.  I'm not exactly sure why
everyone seems to think that.  It's not at all very good.  Because it
is so widely used, I will show you an example of it's use.
/*------------------------------------------------------------------
 Program:       SCANEX.C
 Author:        CORVUS
 Date:          Aug. 31, 2001
 Description:   This is a program that gets input using scanf().
------------------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  int num;
  double fnum;
  printf("Enter a number then press ENTER: ");
  scanf("%d", &num);   
  printf("You entered: %d\n", num);
  printf("Enter a float then press ENTER: ");
  scanf("%lf", &fnum);
  printf("You entered: %lf\n", fnum);
  return 0;
}
Let's look a little more closely at those two scanf() statements we
have in there.
  scanf("%d", &num);  /* Assign the integer from the keyboard
                         to the variable num. */
  The "%d" is the conversion specifier.  It means that the scanf() is
  waiting for an integer value.  On the right side of the comma, we run
  into a strange looking "&num".  What is it?  It is called the
  "Address Of" operator.  I'll talk about that later on, when I finish
  writing the chapter on pointers.  Just remember one thing:  If you
  are inputing NUMBERS using scanf, you must place an ampersand "&",
  in front of the recieving variable.
  We'll now talk about what to do if you want to input strings.  First,
  you need to declare an array big enough to hold your string.  Let's
  rewrite the above program for strings:
/*------------------------------------------------------------------
 Program:       STREX.C
 Author:        CORVUS
 Date:          Aug. 31, 2001
 Description:   This is a program that gets input using scanf().
 -----------------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  char Fname[21];
  char Lname[21];
  printf("Enter your first and last names, then press ENTER: ");
  scanf("%21s%21s", Fname, Lname);  /* Accept no more than 21 chars */
  printf("You entered: %s %s\n", Fname, Lname);
  return 0;
}
Notice that a space can be used as a seperator for input.  Actually any
whitespace may be used.  For example; tab, space, enter.  You also may
notice that you do not use the ampersand on string input.  This example
is a little different from my last ones.  Notice the numbers inside the
input field.  When you place a number after the "%" sign but before the
specifier type, you are asking scanf to read only that number of chars.
We can/should also check the return value of scanf to make sure that
the number items you input, is the number of items actually read and to
check to see if we encountered the EOF marker.  Since scanf returns 0
if nothing was read or a number if something was read, we can do a test
inside an "if" statement.  If you recall, all loops and decision making
constructs evaluate to either a TRUE or FALSE value.  If we get a number
other than 0, that means it's true.  If we get 0, it's false.  Here is
an example program to demonstrate this:
  #include<stdio.h>
  int main(void)
  {
    int i;
    printf("Enter an integer: ");
    if (scanf("%d", &i))    /* Check return value of scanf. */
      printf("You entered: %d\n", i);  /* If !0 */
    else
      printf("Error occured during input.\n");
  
    return 0;
  }
If you like, you can also define and integer variable to hold the
return value of scanf if you prefer.
There are many more little details available with the scanf function.
I suggest that you read your compiler help files, or get a good book
on C programming.  Remember this tutor is not the only thing available
to you.  It's a quick and dirty introduction.
Be wary.  It is possible to overwrite an array by entering more
characters than expected.  The scanf function is losing popularity
quickly.
The next function on our discussion is fgets().  Despite the similiar
name to the gets() function, fgets() is one of the best functions for
input.  The difference is that fgets() allows you to select a stream as
well as the maximum number of characters to input.  This is much safer
than the gets() function.  Allow me to give you an example:
/*------------------------------------------------------------------
 Program:       FGET.C
 Author:        CORVUS
 Date:          Aug. 31, 2001
 Description:   This is a program that gets input using fgets().
 -----------------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  char in[11];  /* Allow 10 visible chars plus
                   one null char at last element. */
  char *ret_ptr;  /* Used to check return of fgets() */
  puts("Enter some text:");
  /* Store input in the "in" array.
     Stop accepting input after 10 chars.
     Use the stdin stream. */
  ret_ptr = fgets(in, sizeof(in), stdin);
  if (ret_ptr != NULL)
    printf("You entered: %s", ret_ptr);
  else
    printf("Error processing fgets()\n");
  return 0;
}
I suggest that you use the fgets() function for most of your input
needs.  Take note of the sizeof operator.  As the name suggests, this
operator will get the size of some item or data type.  In our case, it
will return the size of our array, which is 11.  In the example above,
I also checked to see if fgets() returned NULL.  If NULL is returned,
that would indicate some kind of error occured.
The next functions to discuss are fgetc() and getchar().  These two
functions a very similiar.  They both get a character from a stream.
In the case of fgetc(), you can choose the stream, whereas getchar()
is always getting a character from stdin.
Here's an example of their use:
/*------------------------------------------------------------------
 Program:       FGETC.C
 Author:        CORVUS
 Date:          Aug. 31, 2001
 Description:   This is a program that gets a character
                using fgetc().
 -----------------------------------------------------------------*/
#include<stdio.h>
int main(void)
{
  int ch;
  ch = fgetc(stdin);
  putchar(ch);
  return 0;
}
Though this is not the best example in the world it does demonstrate
the fgetc function.  The fgetc() and getchar() functions are usually
used inside loops.  You'll know if you need it.  If you need more help
with any of these functions, check with your compiler documentation or
a good book.  Try going to http://www.accu.org/ for book reviews and
other items of interest.
That will do for now.  Let's continue onto Part 6.