Friday, 24 February 2017

COMMAND LINE ARGUMENTS

COMMAND LINE ARGUMENTS

It is possible to pass some values from the command line to your C programs
when they are executed. These values are called command line
arguments and many times they are important for your program especially
when you want to control your program from outside instead of hard coding
those values inside the code.

The command line arguments are handled using main() function arguments
where argc refers to the number of arguments passed, and argv[] is a pointer
array which points to each argument passed to the program. Following is a
simple example which checks if there is any argument supplied from the
command line and take action accordingly:

#include <stdio.h>
int main( int argc, char *argv[] )
{
if( argc == 2 )
{
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 )
{
printf("Too many arguments supplied.\n");
}
else
{
printf("One argument expected.\n");
}
}

When the above code is compiled and executed with a single argument, it
produces the following result.

$./a.out testing
The argument supplied is testing

30. COMMAND LINE ARGUMENTS

When the above code is compiled and executed with two arguments, it produces
the following result.

$./a.out testing1 testing2
Too many arguments supplied.

When the above code is compiled and executed without passing any argument,
it produces the following result.

$./a.out
One argument expected

It should be noted that argv[0] holds the name of the program itself
and argv[1] is a pointer to the first command line argument supplied, and
*argv[n] is the last argument. If no arguments are supplied, argc will be one,
and if you pass one argument, then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument
itself has a space then you can pass such arguments by putting them inside
double quotes "" or single quotes ''. Let us re-write above example once again
where we will print program name and we also pass a command line argument
by putting inside double quotes:

#include <stdio.h>
int main( int argc, char *argv[] )
{
printf("Program name %s\n", argv[0]);
if( argc == 2 )
{
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 )
{
printf("Too many arguments supplied.\n");
}
else
{
printf("One argument expected.\n");
}
}

When the above code is compiled and executed with a single argument
separated by space but inside double quotes, it produces the following result.

$./a.out "testing1 testing2"
Progranm name ./a.out
The argument supplied is testing1 testing2


MEMORY MANAGEMENT

MEMORY MANAGEMENT

This chapter explains dynamic memory management in C. The C programming
language provides several functions for memory allocation and management.
These functions can be found in the <stdlib.h> header file.


Function and Description

1 void *calloc(int num, int size);
This function allocates an array of num elements each of which size in
bytes will be size.

2 void free(void *address);
This function releases a block of memory block specified by address.

3 void *malloc(int num);
This function allocates an array of num bytes and leave them initialized.

4 void *realloc(void *address, int newsize);
This function re-allocates memory extending it upto newsize.

Allocating Memory Dynamically

While programming, if you are aware of the size of an array, then it is easy and
you can define it as an array. For example, to store a name of any person, it can
go up to a maximum of 100 characters, so you can define something as follows:

char name[100];

But now let us consider a situation where you have no idea about the length of
the text you need to store, for example, you want to store a detailed description
about a topic. Here we need to define a pointer to character without defining
how much memory is required and later, based on requirement, we can allocate
memory as shown in the below example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Zara Ali");
/* allocate memory dynamically */
description = malloc( 200 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcpy( description, "Zara ali a DPS student in class 10th");
}
printf("Name = %s\n", name );
printf("Description: %s\n", description );
}

When the above code is compiled and executed, it produces the following result.

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

Same program can be written using calloc(); only thing is you need to replace
malloc with calloc as follows:

calloc(200, sizeof(char));

So you have complete control and you can pass any size value while allocating
memory, unlike arrays where once the size is defined, you cannot change it.

Resizing and Releasing Memory

When your program comes out, operating system automatically release all the
memory allocated by your program but as a good practice when you are not in
need of memory anymore then you should release that memory by calling the
function free().

Alternatively, you can increase or decrease the size of an allocated memory
block by calling the function realloc(). Let us check the above program once
again and make use of realloc() and free() functions:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Zara Ali");
/* allocate memory dynamically */
description = malloc( 30 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcpy( description, "Zara ali a DPS student.");
}
/* suppose you want to store bigger description */
description = realloc( description, 100 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcat( description, "She is in class 10th");
}
printf("Name = %s\n", name );
printf("Description: %s\n", description );
/* release memory using free() function */
free(description);
}

When the above code is compiled and executed, it produces the following result.

Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th


You can try the above example without re-allocating extra memory, and strcat()
function will give an error due to lack of available memory in description.

VARIABLE ARGUMENTS

VARIABLE ARGUMENTS

Sometimes, you may come across a situation, when you want to have a
function, which can take variable number of arguments, i.e., parameters,
instead of predefined number of parameters. The C programming language
provides a solution for this situation and you are allowed to define a function
which can accept variable number of parameters based on your requirement.
The following example shows the definition of such a function.

int func(int, ... )
{
.
.
.
}
int main()
{
func(1, 2, 3);
func(1, 2, 3, 4);
}


It should be noted that the function func() has its last argument as ellipses,
i.e., three dotes (...) and the one just before the ellipses is always an int which
will represent the total number variable arguments passed. To use such
functionality, you need to make use of stdarg.h header file which provides the
functions and macros to implement the functionality of variable arguments and
follow the given steps:

1. Define a function with its last parameter as ellipses and the one just
before the ellipses is always an int which will represent the number of
arguments.

2. Create a va_list type variable in the function definition. This type is
defined in stdarg.h header file.

3. Use int parameter and va_start macro to initialize the va_list variable to
an argument list. The macro va_start is defined in stdarg.h header file.

4. Use va_arg macro and va_list variable to access each item in argument
list.

5. Use a macro va_end to clean up the memory assigned
to va_list variable.

Now let us follow the above steps and write down a simple function which can
take the variable number of parameters and return their average:

#include <stdio.h>
#include <stdarg.h>
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* initialize valist for num number of arguments */
va_start(valist, num);
/* access all the arguments assigned to valist */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* clean memory reserved for valist */
va_end(valist);
return sum/num;
}
int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}


When the above code is compiled and executed, it produces the following result.
It should be noted that the function average() has been called twice and each
time the first argument represents the total number of variable arguments being
passed. Only ellipses will be used to pass variable number of arguments.

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000


RECURSION


RECURSION

Recursion is the process of repeating items in a self-similar way. In
programming languages, if a program allows you to call a function inside the
same function, then it is called a recursive call of the function.


void recursion()
{
recursion(); /* function calls itself */
}
int main()
{
recursion();
}

The C programming language supports recursion, i.e., a function to call itself.
But while using recursion, programmers need to be careful to define an exit
condition from the function, otherwise it will go into an infinite loop.


Recursive functions are very useful to solve many mathematical problems, such
as calculating the factorial of a number, generating Fibonacci series, etc.


Number Factorial

The following example calculates the factorial of a given number using a
recursive function:

#include <stdio.h>
int factorial(unsigned int i)
{
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1);
}
int main()
{
int i = 15;
printf("Factorial of %d is %d\n", i, factorial(i));
return 0;
}

When the above code is compiled and executed, it produces the following result:

Factorial of 15 is 2004310016


Fibonacci Series


The following example generates the Fibonacci series for a given number using a
recursive function:

#include <stdio.h>
int fibonaci(int i)
{
if(i == 0)
{
return 0;
}
if(i == 1)
{
return 1;
}
return fibonaci(i-1) + fibonaci(i-2);
}
int main()
{
int i;
for (i = 0; i < 10; i++)
{
C Programming
166
printf("%d\t%n", fibonaci(i));
}
return 0;
}

When the above code is compiled and executed, it produces the following result:

0 1 1 2 3 5 8 13 21 34


ERROR HANDLING

ERROR HANDLING

As such, C programming does not provide direct support for error handling but
being a sytem programming language, it provides you access at lower level in
the form of return values. Most of the C or even Unix function calls return -1 or
NULL in case of any error and set an error code errno. It is set as a global
variable and indicates an error occurred during any function call. You can find
various error codes defined in <error.h> header file.

So a C programmer can check the returned values and can take appropriate
action depending on the return value. It is a good practice to set errno to 0 at
the time of initializing a program. A value of 0 indicates that there is no error in
the program.

errno, perror(), and strerror()

The C programming language provides perror() and strerror() functions which
can be used to display the text message associated with errno.

· The perror() function displays the string you pass to it, followed by a
colon, a space, and then the textual representation of the current errno
value.

· The strerror() function, which returns a pointer to the textual
representation of the current errno value.

Let's try to simulate an error condition and try to open a file which does not
exist. Here I'm using both the functions to show the usage, but you can use one
or more ways of printing your errors. Second important point to note is that you
should use stderr file stream to output all the errors.

#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;
int main ()
{
FILE * pf;
int errnum;
pf = fopen ("unexist.txt", "rb");
if (pf == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
}
else
{
fclose (pf);
}
return 0;
}


When the above code is compiled and executed, it produces the following result:

Value of errno: 2
Error printed by perror: No such file or directory
Error opening file: No such file or directory

Divide byZero Errors


It is a common problem that at the time of dividing any number, programmers
do not check if a divisor is zero and finally it creates a runtime error.
The code below fixes this by checking if the divisor is zero before dividing:

#include <stdio.h>
#include <stdlib.h>
main()
{
int dividend = 20;
int divisor = 0;
int quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(-1);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient );
exit(0);
}

When the above code is compiled and executed, it produces the following result:

Division by zero! Exiting...

Program Exit Status


It is a common practice to exit with a value of EXIT_SUCCESS in case of
program coming out after a successful operation. Here, EXIT_SUCCESS is a
macro and it is defined as 0.
If you have an error condition in your program and you are coming out then you
should exit with a status EXIT_FAILURE which is defined as -1. So let's write
above program as follows:


#include <stdio.h>
#include <stdlib.h>
main()
{
int dividend = 20;
int divisor = 5;
int quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(EXIT_FAILURE);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient );
exit(EXIT_SUCCESS);
}


When the above code is compiled and executed, it produces the following result:

Value of quotient : 4



TYPE CASTING

TYPE CASTING

Type casting is a way to convert a variable from one data type to another data
type. For example, if you want to store a ‘long’ value into a simple integer, then
you can type cast ‘long’ to ‘int’. You can convert the values from one type to
another explicitly using the cast operator as follows:

(type_name) expression

Consider the following example where the cast operator causes the division of
one integer variable by another to be performed as a floating-point operation:

#include <stdio.h>
main()
{
int sum = 17, count = 5;
double mean;
mean = (double) sum / count;
printf("Value of mean : %f\n", mean );
}

When the above code is compiled and executed, it produces the following result:

Value of mean : 3.400000

It should be noted here that the cast operator has precedence over division, so
the value of sum is first converted to type double and finally it gets divided by
count yielding a double value.

Type conversions can be implicit which is performed by the compiler
automatically, or it can be specified explicitly through the use of the cast
operator. It is considered good programming practice to use the cast operator
whenever type conversions are necessary.


Integer Promotion

Integer promotion is the process by which values of integer type "smaller"
than int or unsigned int are converted either to int or unsigned int. Consider
an example of adding a character with an integer:


#include <stdio.h>
main()
{
int i = 17;
char c = 'c'; /* ascii value is 99 */
int sum;
sum = i + c;
printf("Value of sum : %d\n", sum );
}

When the above code is compiled and executed, it produces the following result:

Value of sum : 116

Here, the value of sum is 116 because the compiler is doing integer promotion
and converting the value of 'c' to ASCII before performing the actual addition
operation.

Usual Arithmetic Conversion


The usual arithmetic conversions are implicitly performed to cast their values
to a common type. The compiler first performs integer promotion; if the
operands still have different types, then they are converted to the type that
appears highest in the following hierarchy:

The usual arithmetic conversions are not performed for the assignment
operators, nor for the logical operators && and ||. Let us take the following
example to understand the concept:
#
include <stdio.h>
main()
{
int i = 17;
char c = 'c'; /* ascii value is 99 */
float sum;
sum = i + c;
printf("Value of sum : %f\n", sum );
}

When the above code is compiled and executed, it produces the following result:

Value of sum : 116.000000

Here, it is simple to understand that first c gets converted to integer, but as the
final value is double, usual arithmetic conversion applies and the compiler
converts i and c into ‘float’ and adds them yielding a ‘float’ result.

HEADER FILES

HEADER FILES

A header file is a file with extension .h which contains C function declarations
and macro definitions to be shared between several source files. There are two
types of header files: the files that the programmer writes and the files that
comes with your compiler.

You request to use a header file in your program by including it with the C
preprocessing directive #include, like you have seen inclusion of stdio.h header
file, which comes along with your compiler.

Including a header file is equal to copying the content of the header file but we
do not do it because it will be error-prone and it is not a good idea to copy the
content of a header file in the source files, especially if we have multiple source
files in a program.
A simple practice in C or C++ programs is that we keep all the constants,
macros, system wide global variables, and function prototypes in the header files
and include that header file wherever it is required.


Include Syntax


Both the user and the system header files are included using the preprocessing
directive #include. It has the following two forms:

#include <file>

This form is used for system header files. It searches for a file named ‘file’ in a
standard list of system directories. You can prepend directories to this list with
the -I option while compiling your source code.

#include "file"
This form is used for header files of your own program. It searches for a file
named ‘file’ in the directory containing the current file. You can prepend
directories to this list with the -I option while compiling your source code.

Include Operation

The #include directive works by directing the C preprocessor to scan the
specified file as input before continuing with the rest of the current source file.
The output from the preprocessor contains the output already generated,
followed by the output resulting from the included file, followed by the output
that comes from the text after the #include directive. For example, if you have
a header file header.h as follows:
24. HEADER FILES
char *test (void);

and a main program called program.c that uses the header file, like this:

int x;
#include "header.h"
int main (void)
{
puts (test ());
}
the compiler will see the same token stream as it would if program.c read.
int x;
char *test (void);
int main (void)
{
puts (test ());
}

Once-Only Headers


If a header file happens to be included twice, the compiler will process its
contents twice and it will result in an error. The standard way to prevent this is
to enclose the entire real contents of the file in a conditional, like this:

#ifndef HEADER_FILE
#define HEADER_FILE
the entire header file file
#endif

This construct is commonly known as a wrapper #ifndef. When the header is
included again, the conditional will be false, because HEADER_FILE is defined.
The preprocessor will skip over the entire contents of the file, and the compiler
will not see it twice.

Computed Includes

Sometimes it is necessary to select one of the several different header files to be
included into your program. For instance, they might specify configuration
parameters to be used on different sorts of operating systems. You could do this
with a series of conditionals as follows:

#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#elif SYSTEM_3
...
#endif

But as it grows, it becomes tedious, instead the preprocessor offers the ability to
use a macro for the header name. This is called a computed include. Instead
of writing a header name as the direct argument of #include, you simply put a
macro name there:

#define SYSTEM_H "system_1.h"
...
#include SYSTEM_H

SYSTEM_H will be expanded, and the preprocessor will look for system_1.h as if
the #include had been written that way originally. SYSTEM_H could be defined
by your Makefile with a -D option.

PREPROCESSORS

PREPROCESSORS

The C Preprocessor is not a part of the compiler, but is a separate step in the
compilation process. In simple terms, a C Preprocessor is just a text substitution
tool and it instructs the compiler to do required preprocessing before the actual
compilation. We'll refer to the C Preprocessor as CPP.
All preprocessor commands begin with a hash symbol (#). It must be the first
nonblank character, and for readability, a preprocessor directive should begin in
the first column. The following section lists down all the important preprocessor
directives:

Directive                                                                             Description
#define Substitutes a preprocessor macro.
#include Inserts a particular header from another file.
#undef Undefines a preprocessor macro.
#ifdef Returns true if this macro is defined.
#ifndef Returns true if this macro is not defined.
#if Tests if a compile time condition is true.
#else The alternative for #if.
#elif #else and #if in one statement.
#endif Ends preprocessor conditional.
#error Prints error message on stderr.
#pragma Issues special commands to the compiler, using a standardized
PREPROCESSORS
method.

Preprocessors Examples

Analyze the following examples to understand various directives.


#define MAX_ARRAY_LENGTH 20

This directive tells the CPP to replace instances of MAX_ARRAY_LENGTH with 20.
Use #define for constants to increase readability.

#include <stdio.h>
#include "myheader.h"

These directives tell the CPP to get stdio.h from System Libraries and add the
text to the current source file. The next line tells CPP to get myheader.h from
the local directory and add the content to the current source file.

#undef FILE_SIZE
#define FILE_SIZE 42

It tells the CPP to undefine existing FILE_SIZE and define it as 42.

#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif

It tells the CPP to define MESSAGE only if MESSAGE isn't already defined.

#ifdef DEBUG
/* Your debugging statements here */
#endif

It tells the CPP to process the statements enclosed if DEBUG is defined. This is
useful if you pass the -DDEBUG flag to the gcc compiler at the time of
compilation. This will define DEBUG, so you can turn debugging on and off onthe-fly during compilation.

Predefined Macros

ANSI C defines a number of macros. Although each one is available for use in
programming, the predefined macros should not be directly modified.

Macro                                                                       Description
__DATE__ The current date as a character literal in "MMM DD YYYY"
format.
__TIME__ The current time as a character literal in "HH:MM:SS" format.
__FILE__ This contains the current filename as a string literal.
__LINE__ This contains the current line number as a decimal constant.
__STDC__ Defined as 1 when the compiler complies with the ANSI
standard.
Let's try the following example:


#include <stdio.h>
main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}

When the above code in a file test.c is compiled and executed, it produces the
following result:

File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1

Preprocessor Operators

The C preprocessor offers the following operators to help create macros:
TheMacro Continuation (\)Operator
A macro is normally confined to a single line. The macro continuation operator
(\) is used to continue a macro that is too long for a single line. For example:


#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")

TheStringize(#)Operator
The stringize or number-sign operator (#), when used within a macro definition,
converts a macro parameter into a string constant. This operator may be used
only in a macro having a specified argument or parameter list. For example:

#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}

When the above code is compiled and executed, it produces the following result:

Carole and Debra: We love you!

TheToken Pasting(##)Operator

The token-pasting operator (##) within a macro definition combines two
arguments. It permits two separate tokens in the macro definition to be joined
into a single token. For example:


#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}

When the above code is compiled and executed, it produces the following result:

token34 = 40

It happened so because this example results in the following actual output from
the preprocessor:

printf ("token34 = %d", token34);
This example shows the concatenation of token##n into token34 and here we
have used both stringize and token-pasting.

TheDefined() Operator

The preprocessor defined operator is used in constant expressions to determine
if an identifier is defined using #define. If the specified identifier is defined, the
value is true (non-zero). If the symbol is not defined, the value is false (zero).
The defined operator is specified as follows:


#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}

When the above code is compiled and executed, it produces the following result:

Here is the message: You wish!

Parameterized Macros

One of the powerful functions of the CPP is the ability to simulate functions using
parameterized macros. For example, we might have some code to square a
number as follows:


int square(int x) {
return x * x;
}

We can rewrite the above code using a macro as follows:

#define square(x) ((x) * (x))

Macros with arguments must be defined using the #define directive before they
can be used. The argument list is enclosed in parentheses and must immediately
follow the macro name. Spaces are not allowed between the macro name and
open parenthesis. For example:

#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}

When the above code is compiled and executed, it produces the following result:

Max between 20 and 10 is 20


FILE I/O

FILE I/O

The last chapter explained the standard input and output devices handled by C
programming language. This chapter covers how C programmers can create,
open, close text or binary files for their data storage.
A file represents a sequence of bytes, regardless of it being a text file or a binary
file. C programming language provides access on high-level functions as well as
low-level (OS level) calls to handle file on your storage devices. This chapter will
take you through the important calls for file management.

Opening Files

You can use the fopen( ) function to create a new file or to open an existing file.
This call will initialize an object of the type FILE, which contains all the
information necessary to control the stream. The prototype of this function call is
as follows:
FILE *fopen( const char * filename, const char * mode );
Here, filename is a string literal, which you will use to name your file, and
access mode can have one of the following values:


Mode Description

r Opens an existing text file for reading purpose.
w Opens a text file for writing. If it does not exist, then a new file is
created. Here your program will start writing content from the
beginning of the file.
a Opens a text file for writing in appending mode. If it does not exist,
then a new file is created. Here your program will start appending
content in the existing file content.
r+ Opens a text file for both reading and writing.
w+ Opens a text file for both reading and writing. It first truncates the file
to zero length if it exists, otherwise creates a file if it does not exist.
22. FILE I/O
a+ Opens a text file for both reading and writing. It creates the file if it
does not exist. The reading will start from the beginning but writing
can only be appended.
If you are going to handle binary files, then you will use the following access
modes instead of the above-mentioned ones:

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

Closing a File

To close a file, use the fclose( ) function. The prototype of this function is:
int fclose( FILE *fp );
The fclose() function returns zero on success, or EOF if there is an error in
closing the file. This function actually flushes any data still pending in the buffer
to the file, closes the file, and releases any memory used for the file. The EOF is
a constant defined in the header file stdio.h.
There are various functions provided by C standard library to read and write a
file, character by character, or in the form of a fixed length string.


Writing a File

Following is the simplest function to write individual characters to a stream:


int fputc( int c, FILE *fp );

The function fputc() writes the character value of the argument c to the output
stream referenced by fp. It returns the written character written on success
otherwise EOF if there is an error. You can use the following functions to write a
null-terminated string to a stream:

int fputs( const char *s, FILE *fp );

The function fputs() writes the string s to the output stream referenced by fp. It
returns a non-negative value on success, otherwise EOF is returned in case of
any error. You can use int fprintf(FILE *fp,const char *format, ...) function
as well to write a string into a file. Try the following example.

Make sure you have /tmp directory available. If it is not, then before
proceeding, you must create this directory on your machine.

#include <stdio.h>
main()
{
FILE *fp;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}

When the above code is compiled and executed, it creates a new file test.txt in
/tmp directory and writes two lines using two different functions. Let us read this
file in the next section.

Reading a File

Given below is the simplest function to read a single character from a file:


int fgetc( FILE * fp );

The fgetc() function reads a character from the input file referenced by fp. The
return value is the character read, or in case of any error, it returns EOF. The
following function allows to read a string from a stream:

char *fgets( char *buf, int n, FILE *fp );

The functions fgets() reads up to n - 1 characters from the input stream
referenced by fp. It copies the read string into the buffer buf, appending
a null character to terminate the string.

If this function encounters a newline character '\n' or the end of the file EOF
before they have read the maximum number of characters, then it returns only
the characters read up to that point including the new line character. You can
also use int fscanf(FILE *fp, const char *format, ...) function to read strings
from a file, but it stops reading after encountering the first space character.

#include <stdio.h>
main()
{
FILE *fp;
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1 : %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("2: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("3: %s\n", buff );
fclose(fp);
}

When the above code is compiled and executed, it reads the file created in the
previous section and produces the following result:

1 : This
2: is testing for fprintf...
3: This is testing for fputs...

Let's see a little more in detail about what happened here. First, fscanf() reads
just This because after that, it encountered a space, second call is
for fgets() which reads the remaining line till it encountered end of line. Finally,
the last call fgets() reads the second line completely.
Binary I/O Functions
There are two functions that can be used for binary input and output:

size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);


Both of these functions should be used to read or write blocks of memories -
usually arrays or structures.