Pages

Saturday, December 4, 2010

Reading and writing at the same time.

All the above examples were either reading or writing a file. None of the examples were doing both the operations at the same time. Therefore to write a file and then to read it we will have to create two separate programs. Let's see if we can write and read a file in a single program The code given below will first create a file using the "w" mode. After the writing is complete, we will close the file and reopen it in "r" mode. A file can not be opened in two modes at the same time therefore we must close it before changing the mode.

Example 1 : To write and read a single string in a single program

#include
#include
void main()
{

FILE *fp; // Line 1
fp=fopen("example","w"); // Line 2
char text[50]; // Line 3
printf("\nEnter text to be stored in the file (max 50 chars) "); // Line 4
gets(text); // Line 5
fputs(text,fp); // Line 6
fclose(fp); // Line 7
fp=fopen("example","r"); // Line 8
fgets(text,50,fp); // Line 9
printf("\nThs is the content of the file "); // Line 10
printf("\n%s",text); // Line 11
fclose(fp); // Line 12
}

Description

Line 4 and 5
Asks the user to enter the data that has to be stored in the file.
Line 6
Stores the text entered by the user in the file using the "fputs()" function.
Line 7
Till now the file is open in "w" mode, reading in this mode is not possible, so we are closing this file from its current mode.
Line 8
To read the file we are opening the file in "read" mode.
Line 9
Now that the file is open, the function "fgets()" is reading the first 50 chars of the file.
Line 11
The read data is printed on the screen.
Line 12
The file is closed again, so that the memory is freed.


Example 2 : To write and read multiple strings the data in a single program.

#include
#include
void main()
{
FILE *fp; // Line 1
char ch; // Line 2
fp=fopen("example","w"); // Line 3
char ename[10]; // Line 4
do // Line 5
{
fflush(stdin); // Line 6
printf("\nEnter name of the employee "); // Line 7
gets(ename); // Line 8
fflush(stdin); // Line 9
fputs(ename,fp); // Line 10
printf("\nContinue (y/n) "); // Line 11
scanf("%c",&ch); // Line 12
}while(ch=='y' || ch=='Y'); // Line 13
fclose(fp); // Line 14
fp=fopen("example","r"); // Line 15
printf("\nThs is the content of the file "); // Line 16
while(fgets(ename,10,fp)!=NULL) // Line 17
printf("\n%s",ename); // Line 18
fclose(fp); // Line 19
}

Description
The above code works similar to the previous example. The difference is that this program is asking the user to enter multiple values inside the loop.
Line 7 and 8
Asks the user to enter the data that has to be stored in the file.
Line 10
Stores the text entered by the user in the file using the "fputs()" function.
Line 14
Closes the file so that it can be reopened.
Line 17
To read the file the function "fgets()" has been used with the while loop. The while loop has been used since we don't know how much data is there to be read. The loop will continue to read the file till it reachs the end of the file.
Line 18
The read data is printed on the screen.
Line 19
The file is closed again, so that the memory is freed.

Writing a file - String by String

Writing char by char to a file will take a lot of time. So it will be much better if we can write a whole string to a file in one go. To write a complete string to file we will use the function "fputs()". This function will take two arguments, first the string to be written and second the file pointer.

Syntax
fputs(char [],filepointer);

Example

1. fputs("MyName",fp);


2. char str[]="MyName";


fputs(str,fp);


3. char str[10];

printf("\nEnter any string ");
scanf("%s",&str);
fputs(str,fp);

In the first example, we are writing a fixed string "MyName" to the file pointed by the pointer fp. The second example is also doing the same the difference being that instead of writing the string directly, we have first saved the string "MyName" to a variable "str" and then have written the value of "str" to the file. In the third example, we are writing the string in the file, by asking it from the user.

Example 1 : Writing a string to a file using fputs()

#include
#include
void main()
{
FILE *fp; // Line 1
fp=fopen("names","w"); // Line 2
char name[15]; // Line 3
printf("\nEnter name "); // Line 4
scanf("%s",&name); // Line 5
fputs(name,fp); // Line 6
printf("\nName saved"); // Line 7
fclose(fp); // Line 8
}

Description

This is the simplest use of "fputs()" , after asking the name of the user in line no 4 and 5, we have written it in the file using the "fputs()" function in the line no. 6. The first argument is the string that we want to write and second is the file pointer. Line 7 displays the confirmation that the data has been saved.

What if you want to write names of several persons in the same file? fputs() can write one string at a time. So we will use the same method again - put the "fputs()" inside a loop.

Example 2 : Writing multiple strings to a file using fputs()


#include
#include
void main()
{
FILE *fp; // Line 1
fp=fopen("list","w"); // Line 2
char name[15]; // Line 3
char choice; // Line 4
do // Line 5
{
printf("\nEnter name "); // Line 6
scanf("%s",&name); // Line 7
fputs(name,fp); // Line 8
printf("\nName saved"); // Line 9
printf("\nWould you like to add another name (y/n) ? : "); // Line 10
scanf("%c",&choice); // Line 11
}while(choice=='y' || choice=='Y'); // Line 12
fclose(fp); // Line 13
}

Description
Line 4
Declares an extra variable "choice" which will accept the user's choice, "y" or "n".
Line 5
Line 5 contains a "do" loop inside which the user is prompted to enter name of a person at line no. 6 and 7
Line 8
The function "fputs()" will put(write) the name in the file pointer "fp".
Line 9
A confirmation message "Name saved" is shown to the user.
Line 10 and Line 11
Once the first name has been saved in the file, we are asking the user to confirm whether the user wants to continue adding the names or not. The user will enter either 'y' or 'n' for "yes" or "no".
Line 12
If the user enters 'y' for yes the condition inside the while becomes "true" and the loop runs again from line no. 5. Line no. 6 to 11 are repeated, the user enters another name which is again saved in the file. The user will keep entering the names in the file and the program will ask the user to continue or not. This process will continue till the user enters 'n' for "No".


To read the files created in example 1 or 2, please follow the instructions given in the post "How to read the file".

Friday, December 3, 2010

How to read the file you just created

The above example has created a new file with a single char written inside it. How will we know that the file has been created and the data has been stored? The message "saved" at line 7 is just a message, it is not an actual indication of whether the writing has actually taken place. Even if you remove the "fputc()" (line 6) from the above code, the "saved" message will still appear because it has nothing to do with whether writing was successful or not. Then how will we check that the program has run successfully.
You can choose any of the following methods to read the file.

1. Open the file using "My computer" :  Open my computer and search the file you have just created ("test" in the above example). Double click on the file name to open it. If Windows shows a message that "Windows can't open this file", choose "Select a program from a list of installed programs" and click on OK. From the next window which shows "Open with" select "Notepad" and click on OK. This will open the file in "Notepad".

2. In the "Turbo C" or other IDE - Select "Open" from the file menu. In the "file name" text box type the name of the file(test) and place a dot(.) at the end. For example in the above code the file we are creating a file named "test", so to open it type "test.". This will open the file inside the "C" window. You can see the char you typed there.

3. In the "Turbo C" IDE (software) Click "File--> DOS Shell". You will see a black screen called the DOS Window with some thing like "c:\tc3\bin" written inside it. This is called the DOS prompt. You will also see a cursor blinking there. Type "type test" and press enter, this is the DOS command for printing a file. Your file should get displayed here. To return to the C window type "Exit" and press enter again.

Writing a file

Now that we have seen an example of how the files are read, let's see how we can write a file using the file handling functions. As I told you in earlier articles that if you are creating a new file or editing an existing file both are called "writing" in the context of file handling. Similar to reading a file, writing can also be done using various methods. It can be char by char writing, string by string or binary writing. Let's see all these methods of creating a file.

Writing a file - char by char

To write data in a file char by char, we will use the "fputc()" function. This function is just the opposite of the function we have studied in the last sessions "fgetc()" which reads a char at a time. "fputc" on the other hand "puts" (writes) a char to the file. To write multiple chars we can use this function in a loop. The "fputc()" takes two arguments the first argument is the char that we want to write and the second argument is the file pointer in which we want to perform the writing task.

Syntax
    fputc(char,file pointer)

Example
    fputc('G',fp); // Writes the alphabet G to the file pointed by fp
    fputc('?',fp); // Writes the symbol ? to the file pointed by fp
    fputc('3',fp); // Writes the digit 3 to the the file.
   
    char f='T';
    fputc(f,fp); // Writes the value of the variable f (which is T) to the file.


    As you can see in the above examples, the function fputc() is writing any char in the file. It can used to store any type of char - be it an alphabet, symbol or a digit. The last example, instead of writing the char directly to the file, first stores it in the variable "f" and then passes this as an argument to "fputc".


Example 1 - Writing a char to the file
#include
#include
void main()
{
    FILE *fp; // Line 1
    fp=fopen("test","w"); // Line 2
    char ch; // Line 3
    printf("\nWrite a character "); // Line 4
    scanf("%c",&ch); // Line 5
    fputc(ch,fp); // Line 6
    printf("\nSaved "); // Line 7
    fclose(fp); // Line 8
}



Description

Line 1 :
    Declares a variable of type FILE which is a must to handle files in C.
Line 2 :
    Using the "fopen()" we are creating a new file named "test". Did you see the change in the "mode". It has changed from "r"(reading) to "w" (writing). This means that we are telling the compiler that we want to open a file for "writing". As soon as this program is run, the compiler will create a new file named "test" in the same directory as the program. If there is an existing file with the same name it will be overwritten. There are options by which you change this behaviour which we will learn later on. In case you want to change the location of the file, you will have to write the path like this "c:/folder1/folder2/test". This will create a new file
named "test" inside folder2 which is a sub folder of folder1. You can also add an extension to the file name so that the OS recognizes the type of the file.
Line 3,4 and Line 5 :
In these two lines we are asking the user to enter the character that has to be stored in the file. The user's value has been saved in the variable "ch". As we know that a char can save any type of char as long as it is of single length, anything that the user enters will get saved in the variable "ch".
Line 6:
Once the data is there in the variable "ch", now comes the writing part. The "fputc()" will write the value of "ch" to the file pointed by "fp" (test).
Line 7:
    Informs the user that the data has been saved.(optional)
Line 8 :
    Closes the file.


Let's create another program using "fputc()" to write multiple chars in the file.


Example 2 - Writing multiple chars to a file

#include
#include // For strlen
#include
void main()
{
    FILE *fp; /// Line 1
    fp=fopen("myfile.txt","w"); // Line 2
    char str[20]; // Line 3
    printf("\nWrite a string "); // Line 4
    gets(str); // Line 5
    for (int i=0;i
        fputc(str[i],fp); // Line 7
    printf("\nSaved a string."); // Line 8
    fclose(fp);
}

Description

Line 3 :
    Declares a string named "str", with a size of 20. You change it to any size that you want.
Line 5:
    We have used "gets()" instead of "scanf()" so that the user can enter spaces in the string.
Line 6:
    Since "fputc()" can not write more than one char at a time, we have written "fputc()" inside the loop which runs as per the length of the string. Assuming that the user enters "C Programming" in line no 2, the loop will enter the char at the "i"th position in the file. The char "C" will be entered first followed by space, 'P','R','O','G','R','A','M','M','I','N','G'. Although the code will save all the characters of the string in the file, even then it won't be correct to say that "fputc()" can write a string to the file. "fputc()" can write only a single char at a time. Therefore like "fgetc()" it is also not suitable for writing large strings.

Thursday, December 2, 2010

Reading a file string by string

The "fgetc()" function is fine for printing text files but as discussed earlier it will take a long time to process a large file using "fgetc" since it can read only a char to at a time. Therefore in order to read a large file we can make use of the "fgets()" . As the name suggest "s" in fgets() is for string. It can read a string from a file. How many chars will be read will entirely be your choice.

Syntax
    fgets(char[],int bytes,filepointer);

The first argument (char[]) is the string that will hold the chars that have been read from the file. The second argument is the number of bytes that we want to read from the file in one go. The third argument is the file pointer from where we want to read.

Example
    char str[10];
    fgets(str,10,fp);


    In this example, fgets() will read 10 chars(bytes) from the file pointed by "fp" and will store it in the string "str". Keep an eye on the size of the array and the number of bytes that we are reading. The array should be large enough to accommodate the read chars. If we are reading 20 chars from the file and the size of the array
is 10, it won't be able to store the data. If the case is just opposite, the array is large and we are reading less bytes the program will work fine but it will be a memory wastage.

Example - To read a file string by string
#include
#include
void main()
{

    FILE *fptr; // Line 1
    fptr=fopen("anyfile.txt","r"); // Line 2
    char str[15]; // Line 3
    fgets(str,15,fptr); // Line 4
    printf("\nFollowing is the data of the file"); // Line 5
    printf("%s",str); // Line 6
    fclose(fptr); // Line 7
}

Description
Line 3
    Declares a string named "str" with a size of 15 chars. The size of the array should be carefully chosen, it should not be too large or too small. When the data will be read from the file, this is the place where the date will be placed.
Line 4
    The fgets() will read the first 15 chars of the file pointed by fptr and place them in the array. If the file has more than 15 chars, the remaining chars will be ignored. It is also worth to note that the "arrangement" of text inside the file is very important here. If the 15 chars are not in one line the "fgets()" will read the data only up to the point where it meets a "enter key" or "\n". We have asked "fgets()" to read the first 15 chars,but if there is an "enter" before the 15 char can be read, "fgets()" will not read further.

Consider the following two files

File 1 has the data
abcdefghijklmnopqrstuvwxyz

the above code will read the first 15 chars and the output shown will be
abcdefghijklmno

File 2 has the same data but is spread in multiple lines
abc
defghij
k
lm
nopqrstuv
wxy
z


the above code will print only "abc" since all chars are not in a single line. The compiler will encounter "\n" after reading the alphabet "c", therefore further reading will be discontinued. So you can say that writing 15 or any other number as the second argument does not guarantee that 15 chars will be read. How many char will be printed depends on how the data is stored in the file. If the data is in the form of the second file then writing 15 will not help. For reading the second file a string of 9 will also work same as a string of 15 since the longest line in the file(nopqrstuv) has 9 chars. A smaller string will also help in saving memory.


Example 2 - Reading the whole file string by string.
#include
#include
void main()
{

    FILE *fptr; // Line 1
    fptr=fopen("goodfile.txt","r"); // Line 2
    char str[15]; // Line 3
    while(fgets(str,15,fptr)!=NULL)) // Line 4
        printf("%s",str); // Line 5
    fclose(fptr); // Line 6
}

Description
Line 4
    In line number 4, the "fgets()" has been written inside a loop. The loop will read 15 chars at a  time and will continue till it reaches the end of the file. If the file has 150 chars, how many times the loop will run? 15 times? No, it all depends on how the data is saved in the file. If all the 150 chars are written one char per line, the loop will run 150 times, and if all the chars are written in a stretch then the loop will take 15 cycles to process the whole file.
Line 5
    The data in "str" will be printed in line no. 5, first the first 15 chars, then the next 15 chars till the whole file is finished.

Wednesday, December 1, 2010

File handling in C

In the previous session we discussed about memory, files, file handling, its uses etc. Now it's time to move ahead and learn how it is practically done in C. 

In C to handle (read/write) a file, you must open it first. Since file is a collection of data, to open it, the variable must be efficient enough to handle all type of data. You can't declare an int variable to handle the contents of file since it may contain chars also. Similarly if the variable is of char type it won't be able to perform calculations. Therefore to open a file, we declare a variable using the "FILE" notation
example
    FILE *fptr;
This statement will declare a variable named "fptr" of FILE type. This variable should always be of pointer type since it will be pointing to a file. You can change the variable name "fptr" to any other valid name but the "FILE *" can not be changed. After declaration, the variable must be initialized just like all other variable are. The difference is you can not assign it a value using the "=" operator. For example, an integer variable can be assigned a value with a simple statement like "a=10" but not in case of FILE variables. To assign a value to a FILE variable, the function "fopen()" is used. The "fopen()" takes 2 arguments, the name of the file and the mode. This is how it looks

Syntax
    fptr=fopen("filename","mode");

Example
    fptr=fopen("hello","r"); // opening a file in read mode
    fptr=fopen("file1.txt","w"); // opening a file in write mode.


make sure that you choose the right mode while opening the file. Mode denotes that for what purpose are you opening the file for , it can be reading (r), writing (w), appending (a) or any other pre-defined mode. Note that you can not perform any task other than for what file has been opened. It means that if the file has been opened for writing you can not read it and vice versa.

Reading a file

To read a file, we have multiple methods. We can read a file char by char, string by string or byte by byte. Which method you will choose depends on the type of data the file contains, for example if the file contains text data we can read it char or string wise but if the data is in binary form we will have to read it byte wise. Let's see all these methods one by one.

To read a file char by char :
If we want to read a file char by char the function used will be "fgetc()". The "fgetc()" function will read the current char from the file and advances to the next char. Remember that this function reads only a char at a time, so if you want to read the whole file you must place the "fgetc()" inside a loop and process it till the end of the file. The advantage of using the "fgetc()" is that since we are reading char by char we can make programs like counting how many alphabets are in the file,counting capital letters , small letters etc. Since it reads only one char at a time, it is not suitable for reading large files because it will take a lot of time to process such a file. Let's create a program to understand the working of "fgetc()"

#include
#include
void main()
{

    FILE *fp; // Line 1
    fp=fopen("file1","r"); // Line 2
    char c; // Line 3
    c=fgetc(fp); // Line 4
    printf("%c",c); // Line 5
    fclose(fp); // Line 6
}

Description
Line 1
    Declares a pointer of FILE type. "fp" is just a variable name and can be changed.
Line 2
    The second statement initialises the variable "fp" using the "fopen()". The first argument(file1) is the name of the file that we want to open for reading. Make sure that since we are opening this file for reading, this should be the name of an existing file. If this file is not available the whole program will go for a toss and nothing will be printed on screen.  if the file to be read is located in the same directory(folder) as the program, the second statement is fine but if the source file is located else where we will have to specify the path like this - fp=fopen("c:\\my_progs\\file1"). Note the use of double back slashes (\\). Normally we use a single slash ("c:\my_progs\file1") , but C assumes anything written after a single slash as escape sequence like \n or \t so to inform the compiler that is not an escape sequence we put double slashes.
Line 4
    Now comes the reading part. The fgetc() function will read the first byte (char) of the file and puts it in the variable "c". Suppose that the file contains all the alphabets from "a-z",  fgetc() will read "a" and stores it to the variable "c"
Line 5
    The value of "c" is now being printed. If the data inside it is the alphabet "a" the screen will read "a".

Now the question is why only "a" is being printed, why not the whole file. What should I do to print the whole file? The answer is - put fgetc() inside a loop. See the code below which prints the whole file char by char.

#include
#include
void main()
{

    FILE *fp; // Line 1
    fp=fopen("file1","r"); // Line 2
    char c; // Line 3
    c=fgetc(fp); // Line 4   
    while(c!=EOF) // Line 5
    {
        printf("%c",c); // Line 6
        c=fgetc(fp); // Line 7
    }
    fclose(fp); // Line 8
}

Description

Line 1 to Line 4 is same as in the above example. The difference starts from line no. 5 where we have written a while loop. The condition inside the loop checks if the value of "c" is not equal to end of file (EOF). The loop continues to read the file char by char till the end of file. How does the program know that this is the end of file and no further reading is required? When we create a file the OS places an invisible mark at the end of the file called the "end of file marker". This marker denotes that end of the file. The loop is searching for this marker so that it can print the file data from the beginning till the end. The "fgetc()" has been written twice once outside the loop and once inside the loop. Why twice ? If you don't write it inside the loop, the value of "c" will struck to "a"(the first char) of the file. What we want to do is to read the whole file, so we should write it inside the loop also so that it can move from a to b to c till the end of the file. This is how it works, assuming that the file has the data (without the quotes)
"abcdefghijklmnopqrstuvwxyz"

Line 4 reads the first char "a", since "a" is not the end of the file, the control enters the loop. The value of c which is "a" is printed. Line 7 reads the second char which is "b", since "b" also is not end of the file the loop continues to print the value of c which is "b". Line 7 again reads the next char which is "c", "c" is printed and the program continues. Once "z" is read the compiler makes an attempt to read the next char but all the data has already been read. So the next char is the "end of file marker". The condition becomes false and the file is closed using the "fclose()". Closing a file is optional but it is a good practice to close a file to free the resources.

File Handling

What is file handling ?
File Handling allows you to move the data from RAM to the hard disc. To define, file handling is the process of storing data in a storage device to use it later.

Why is it needed ?

The computer system has 2 types of memory - Primary and Secondary. Primary memory is further divided into RAM and ROM, whereas secondary memory includes all kind of storage devices like the hard disc, CD/DVD, flash drive etc. Of all these different type of "memories", the word memory is mainly use for RAM or the Random Access Memory. Anything that you see on the monitor is loaded from a storage device to the main memory or RAM. The data that we want to show on the screen must be loaded from the secondary memory to the primary memory.  For example, the moment you switch on your computer, it starts loading the operating system (Windows, Linux) to the main memory. The OS resides permanently on the Hard disc but it is of no use unless it gets loded into the RAM. Once it does, the computer starts working. This is called "booting" in computing terminology. All the variables that we declare in a program are also stored in RAM. Remember, that RAM is a volatile memory, which means that it can not store data permanently. Therefore if you ask the user to enter some details like, name, marks, etc., you won't be able to see the entered data once the computer is switched off and turned back on.
Let's see the following code to understand this better :

#include
void main()
{
    char player_name[12];
    int goals;

    printf("\nName of the player ");
    scanf("%s",&player_name);
    printf("\nRGoals Scored ");
    scanf("%d",&goals);
   
      printf("\nName of the player %s",player_name);   
    printf("Goals Scored %d",goals);
}

When we run the above code for the first time, suppose this is the data that we entered
    Name of the player Peter
    Goals Scored 3


The output will be
    Name of the player Peter
    Goals Scored 3


If you run the above program again, it will prompt you to enter the data again. Suppose this time you enter the following values

    Name of the player Joe
    Goals Scored 2

    Name of the player Joe
    Goals Scored 2


Now, note that when the program runs for the second time it doesn't print the data of the first player. Why ? Because the data you entered in the second run of the program (Joe and 2) it overwrote the data entered in the first time(Peter, 3). So when you ask it to print the names and goals, its prints the most recent values.  At the core of this problem is the difference between the primary and secondary memory. The data you are entering in the variables is being stored in the primary memory (RAM) and not in the secondary memory(hard disc, DVD etc.) RAM being temporary, overwrites the previous data once you enter the new data or simply close the program or switch off the system. If you want to the data to be saved permanently so that you can view/edit/ delete it in the future, you must save it to the secondary memory. To summarize, if you want to store the data permanently so that you can use it later, save the data in the secondary memory instead of the primary memory.

How?
A file is a "collection of data". This "data" can be in the form of text, graphics, audio or even a video clip.  There are 2 only operations that can be performed on a file - Reading and Writing.

Reading - is the process of either reading the data of the file fully or partially. Partial reading means reading only the desired data or part of the file.
Writing - is the process of either creating a new file or editing its contents. Editing includes modifying existing data, deleting data etc. It can be said that if you are not reading a file, you are writing it.