Search This Blog

Simplicity is the ultimate sophistication.” — Leonardo da Vinci
Contact me: sreramk360@gmail.com

Friday, 13 February 2015

Learn files in C: tutorial 1

Learn files programming in C: practical tutorial 1(Brief introduction to files in C)

Keywords- Learn files programming in C, C files programming, file random access in C, C Files, fopen, fclose, fopen C formats, C files programming, fread, fwrite, Programming in C tutorials.
"To follow this tutorial, you should be familiar with the following topics in C language:
  1.  variable declaration, static memory allocation, value assignment
  2. basic arithmetic and logical expressions in C
  3.  basic C pointers, its meaning, assigning the address location of memory locations to pointer variables  (i.e., assigning the reference of one variable to another variable).
  4. functions in C (all four combinations; i.e. functions with return with arguments, .. etc)
  5. passing memory address as arguments in C functions"
Now, assuming you  are familiar with the above topics, let me proceed with the tutorial. To gain the maximum benefit learning files, it is advisable to try out all the example programs in a computer. Until now, you have been storing values in variables and manipulate them in your program. But once your program terminates, you will find it impossible to retrieve the values that were stored in your program's memory. This is always not desirable; let's assume that you are playing your favorite video game, and suddenly you get interrupted by some work. Then you will be left with two possibilities; one: you will have to play the entire game from the very beginning; two: you could save the game to a particular location and time such that the next time you switch on your game, you would resume it without any problems. It's obvious that the second option is more desirable; so how is this done? Your game stores the data that describe your level, your place in that game, or any other associated parameters in the computer's hard-disk as a file, giving it a suitable name. So this file is read when the application is reopened and resumes your place in the game.

So how is all this done? When we run our program on top of a modern operating system, like windows 8.1, the computer won't give you direct access to the basic hardware like the hard-disk, the random access memory, the video memory (the memory associated with the screen display) etc.; so your program requests the operating system to communicate with these hardware. This ensures the overall stability of the system and minimizes the risk of malware and virus (imagine if a malware or virus has low level access to the system, enabling it to directly communicate with the hardware; then, it wouldn't take any time for it to wipe-out the entire data on the hard-disk!). The request to handle hardware are sent to the operating system using its run-time library functions; these functions help in performing the requested task. So when you run the same program in a different version of windows, the run-time library functions used may vary, but that's not going to affect your program's performance. 

 Streams:

Streams are logical interfaces to hardware device in a computer. This hardware device could be the output screen, hard drive, keyboard or the computer mouse or any other device. In C language, when referring to a file, we refer to a hardware device. Streams like stdin and stdout are input and output streams respectively; they handle the keyboard inputs and the program output screen's display. They get initialized by default when the header stdio.h is included. In C we represent a pointer to a stream as
                                     FILE *varName; // the stream

Files programming:

So certain standard file handling functions are available in C. They are (note, at this point its not necessary to know about the following functions; Ill be explaining them soon),

Opening and closing files:  
fopen()  - for opening the file stream
fclose()  - for closing the file stream
 fclose() - for closing a stream
fcloseall() - for closing all the open streams other than the default ones such as stdin, stdout, sterr etc.

For text based operations:
fgets()    - for getting a string from file
fputs()   -  for writing a string to file
fscanf() - for reading a formatted data from a stream
fprintf() - for writing a formatted data to a stream
fputc()  - for writing a character to the destined file
fgetc()  - for reading a character from the destined file

For binary based operations:
fread() - reads raw data from the stream
fwrite() - writes raw data to file

For file navigation:
fseek()
ftell()

For stream buffer flushing:
fflush()

 Just for a brief introduction, let me write down an example program:

#include <stdio.h> // has the external symbols fscanf, fprintf, fopen declared in it
#include <conio.h> // not required: tell me why should we avoid including library files that aren't                                       //    used
#include <strings.h>
int main()
{
    FILE *f = fopen("a.txt", "w"); // opens the file a.txt in write mode
    char text[100];

    if(f == NULL) // checks if the opening operation was a success
    {
        printf("error opening the file in read mode");
        return -1; // return an error signal to the operating system
    }
    while(!(strcmp(text, "exit")==0)) // checks if the text typed in is "exit" or not
    {
        gets(text); // reads text from the user
        fprintf(f, "%s\n", text); // writes the text to the file
    }
    fclose(f); // closes the file and clears all the memory in the location pointed by f.
    return 0;
}

Now, this above program gets data from the user and writes to the file named a.txt. The function fopen takes two arguments, one the file directory, and the other the opening mode. Let me list down the kind of file open modes avilable:
  1.   r - read mode
  2.  w- write mode
  3.  a - append mode
  4.  r+ - read/write mode. Return's error when the file does not exist. 
  5. w+ - write/read mode. Creates a new file if the file does not exist
  6. a+ - opens the file for read/append mode. But when data is written to the file right after the file opens, the written data gets appended. instead, if data is read from the file, the pointer jumps to the end of the file
  7. rb - read in binary mode
  8. wb - write in binary mode
  9. ab -append in binary mode
  10. r+b - read/write in binary mode (does not create the file if it does not exist)
  11. w+b -write/read in binary mode (here, it creates a file)
  12. a+b - opens a file in append mode for read/write (here it creates a file if it does not originally exist. But if the file does exist, and if the "fread" operation is used, the pointer heads to the file's beginning )
Now we got to check if the file was actually opened by the fopen operation. If  it was opened successfully, then 'f' would hold a non zero memory address value. If for some reason the file didn't open, then the error message is displayed and the program gets terminated. Next, the function fprintf writes the data in 'text' C string variable to the file a.txt. Finally, the file gets closed using the fclose(). Calling fclose(f) clears all the memory locations associated with the stream 'f'.

If you run the above program in a machine, you will find that a new text file gets created and once you type something and press enter, the text gets saved to the file a.txt. After terminating the process by typing 'exit', check out the file a.txt. The text you typed along with the word exit would be saved to the file a.txt.   

 Now, lets see a program that reads from a file. We used fprintf for writing data to file, now we may use fscanf to read formatted data from the file. Like scanf, fscanf also formats the data obtained from the file. fscanf ignores all space characters and terminates reading either when it encounters, '\n', ' ' or '\r'. So when we read the data from the file using fscanf, then as the characters '\n', '\r' and ' ' are ignored, the information about the location of the space character in the text file (along with the next-line character) is lost and it become impossible to extract them back unless we read the buffer data present in the location f. So you use fscanf only if your program needed these texts to be ignored. Lets say you write a huge program like the C interpreter in C. In this case, it is necessary that these characters are ignored.

Now lets see the example for reading the text contents from the file.       
#include <stdio.h>
#include <conio.h>
#include <strings.h>
int main()
{
    FILE *f = fopen("a.txt", "r");
    char text[100];

    if(f == NULL)
    {
        printf("error opening the file in read mode");
        return -1;
    }
    while(!(strcmp(text, "exit")==0) && !(feof(f)))
    {
       fscanf(f, "%s", text);// reads text from the file pointed to by the stream f
        printf("%s\n", text); // displays the text that's been read
    }
    getch();
    fclose(f);
    return 0;
}

Unlike the former program, this program reads contents from the file a.txt displaying the words one after other and terminates once it reads the word 'exit' or reaches the file's end.The function feof(), as its name suggests, checks for the end of the file being read. feof(f) becomes true if the file's end is reached. Note that the file has been opened in read mode (i.e., "r"). So if the file does not exist, then the pointer variable will be assigned the value NULL or 0x0.
                                                                                                           tutorial 2 >>>>
 copyright (c) 2015 K Sreram. You may not distribute this article without the concerned permission from K Sreram.  

about my blog

1 comment:

  1. There's no use of including conio.h right? So what are the drawbacks of including a library file unnecessarily?

    ReplyDelete

Featured post

Why complicating matters is not good

“ Simplicity is the ultimate sophistication.” — Leonardo da Vinci Why is complicating things wrong ? - K Sr...