C Programming/Input and Output

Objective

edit
  • Learn how to input and output data throught the console.
  • Learn how to input and output data using files.

Lesson

edit

Introduction

edit

By now you should have noticed the frequent use of the function printf(). This is the basic C function for printing text onto a command line terminal.

printf() has an unusual (but very powerful) way of displaying text. All information to be displayed is placed between quotation marks. The unusual part is that in order to print the value of a variable, a placeholder must be used within the quotes. To use a placeholder, you write %datatype replacing datatype with a value corresponding to the type of the variable to be displayed. Finally, the name of the variable to be displayed is added after the last quotation mark, but before the semi-colon.

The values for variable placeholders are as follows:

format string input type
%c character
%d digit (integer)
%f float
%lf double
%u unsigned
%s string

For example, to print the value of an integer variable named "integer_var":

printf("The value of my variable is %d",integer_var);

More than one variable can be included in a single printf() function. However, for each variable placeholder within the quotation marks, a variable name of matching type must added to the end of the line. For example, to use an integer variable, a float variable, and a single character variable within a printf() function, you could type:

printf("Here is an integer: %d, a float: %f, and a character: %c",int_var, float_var, char_var);

Further, printf() can also make use of escape characters to represent things that are kept in memory as text but cannot be written directly into your code. One commonly used escape code is \n, which is used to add a line feed to the output. Escape characters always start with a backslash "\".

For example:

int number = 6;
printf("the number\n is %d\n",number);

will output:
the number
is 6 (followed by a blank line).

Escape Sequences

edit

Here is a table of most of the escape sequences.

Escape Sequence Description
\' Single quote
\" Double quote
\\ Backslash
\nnn Octal number (nnn)
\0 Null character (really just the octal number zero)
\a Audible bell
\b Backspace
\f Formfeed
\n Newline
\r Carriage return
\t Horizontal tab
\v Vertical tab
\xnnn Hexadecimal number (nnn)

Add in use of stderr(), scanf() and fgets().

Simple input

edit

For simple input we can use the function scanf(). scanf reads formatted input which means it will need the format string to function. A very simple example:

cnt = scanf("%d",&x);

- %d is the format string here, it means a simple integer, a digit.

- x is the variable we will store the integer we've just read, therefore we must pass the memory address of x to scanf. We can do that with the "address" operator &.

- cnt will store number of values we've actually read, if this is less than we intended then obviously something went wrong. So this provides us with some error checking capabilities!

scanf essentially uses the very same format strings as printf, see them on the top of this page.

File I/O

edit

we can open a file in
- binary
- text
modes.

opening modes description
r opens an already existing file for reading
r+ opens an already existing file for reading and writing (update)
w creates a new file for writing or empties the already existing one.
w+ creates a new file for reading and writing or empties the already existing one.
a appends to an already existing file (writing only, starting from the end of the file). if it doesn't exist, a new file is created.
a+ appends to an already existing file (both reading/writing , starting from the end of the file). if it doesn't exist, a new file is created.


Dealing with text files:
Text files can be handled very similar to what we learned about the standard input/output, but now we will use fprintf/fscanf instead of printf/scanf! Their arguments are similar. The only difference is that fprintf/fscanf have 1 more argument. A file pointer!
Also we need to open/close the files. It simply means to ask the OS to give us control over that particular file, then after we are done we give it back.

FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );
int fprintf ( FILE * stream, const char * format, ... );
int fscanf  ( FILE * stream, const char * format, ... );

However first of all we need to open the file(s) we want to use.

Opening/using/closing a text file:

1.) First we need to declare a file pointer variable.

FILE *textfile = NULL;

2.) Then we need to open it, telling the operating system how we want to open it (text/binary/read/write/append/etc). If the operation is successful we get a file pointer that will tells us where to read from/write. Otherwise we will get a NULL. So it is easy to find out if it was successful or not.

textfile = fopen("filename","w");

3.) After that we can actually read/write. In this example we write. The return value of fprintf/fscanf is the successfully read/wrote items. So it is easy to find out about errors here too.

for(i = 9; i >= 0; i--)
      fprintf(fp,"%d\n",i);

4.) finally we need to close the file, it gives the control back to the OS.

fclose(textfile);


'Dealing with binary files:
Well binary files are really different than text files. In binary mode, you deal with bytes not characters, and it provides us with a method of storing data more efficiently. What is a matter of utmost importance when dealing with large amount of data (like databases), because it makes your program run faster. It's faster to read/write it from the disk, and takes less disk space! Let's see an example: The number 1985 in a text file, appears as 4 characters: '1','9','8','5'. This takes 4 bytes. However in a binary file it gets stored in the machine's internal format 0x07C1 (2 bytes if we are using short as the variable type). With this little trick we have already saved half the disk space. Opening and closing a file in binary mode is very similar to the method we learned about text mode files. We only have to add 1 more letter to the opening mode string in fopen. However to read and write such files we have brand new and totally different functions.

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );


Opening/using/closing a binary file:

1.) first we need to declare a file pointer variable again, and a buffer variable (this is what we will write to the file).

FILE *binaryfile = NULL;
int i = 0;

2.) Now we need to open the file in binary mode. This can be done with adding a 'b' to the opening mode string.

binaryfile = fopen("filename","wb");

3.) Now we can work with the file. We need to tell fwrite, what we want to write (need to pass a pointer to it, so we point on the data literally), how many times we want to write it, how big the data is we want to write, and where we want to write it. The fread function works almost exactly the same, just the other way around.

for(i = '9'; i >= '0'; i--)
      fwrite (&i , 1 , sizeof(int) , fp );

4.) Finally we need to close the file

fclose(binaryfile);

Additional Resources

edit

Assignments

edit