 Good morning everybody. Welcome to the workshop once again. Today we are primarily going to discuss file IO and all related issues. One of the problems which I am going to discuss today although it is about handling file but it is more about handling data in the file. And this is something that I would like to start our discussions with. File IO is merely a container of our data. What we are handling in our program are the values in the data. Files do tell us how the data is best organized and how the data can be accessed efficiently. These are the topics that I wish to discuss today. First, the need for processing data in files. Next, the operating system view of files. How does operating system view files? More specifically, every operating system gives a particular environment to any running program. So whenever we say dot slash a dot out for example, that means we are asking the operating system to run our program, the operating system actually gives our program a certain environment. What is that environment? It is called the execution time environment. In particular, we will see some standard files which are automatically given to our program at the beginning of its execution. Then we will look at files in C. More specifically, before the T break, we will look at simple IO operations and the dreaded scan F and print F which we have so far as seriously kept away from our discussions. Subsequently, we will look at various other file operations. For example, can I directly access a file? Can I write anything anywhere in between? Can I read without going through the sequence of records? The answers are yes, particularly for this files and we will see what are the functions that C programming language provides through its standard library. We will specifically discuss binary files also and C functions for file handling. Of course, as usual, we will have examples not necessarily at the end but throughout the lecture. So first of all, what are files? A file actually is regarded as a large collection of bytes stored outside the main memory, typically on a disk. Disk files are the files that with which you are most familiar with, but there are files associated with other devices as well. We shall see that in a moment. Files on the disk are managed by the operating system. Operating system has various components such as memory management, process management. One component is file management. So, the file system of the operating system actually handles management of data on desk. The files are organized in directories and sub directories. We are very well familiar with them. Each file can be created. We can write data to it and we can retrieve data or read data from it. So, operations like create a file, read data from the file or write data onto the file are natural operations. Additionally, if there is a file on the desk, we can insert data into it. Obviously, this is effectively like an external memory. So, if I insert data into a memory location which already contains something, that data would be lost. Such responsibility we will have to take. So, we will have to find out the available space on the disk and write in the file and write it. Typically, when you write to an existing file, you always write at the end. This is called an append operation and there are specific modes for that operation. That means when you say I want to handle this file in append mode, automatically you are creating an output file, but not new file. You are appending to an existing file. Similarly, you can delete data from an existing file. Each file has certain properties. The file has a name, the file has size, the file has a path, the file has permissions. These permissions are called excess permissions and the physical location of a file along with its properties, as I mentioned, are known to the operating system. So, it is essentially when we say in our program, we are handling files. We are never directly handling any data on the file. We do that strictly through the operating system. It is the operating system which is in charge of interaction with all external devices. Our program actually runs in a shell provided by the operating system. And whenever we want to interact with the external world, particularly with this to read or write files, we take help of operating system and all our statements which are essentially function calls in C, because as we had noticed, C programming language does not have any instruction for input and output intrinsically. So, whenever we make a function call, the calls are executed by internal function calls, corresponding function calls of the operating system. For those of you who are not familiar with the organization of data on DES, I thought a small pictorial diagram would be useful. I have found it useful when showing it to students. I also have an animation. I will show it to you after the tea break of how the DES rotates and the data gets written. Since most of you would be familiar with these details, I will just mention it in the context of how to explain it to the students. It may take about 5 to 10 minutes when you explain, but it is worthwhile to tell people that there is a spindle which actually rotates and these DES rotate along with it. You can also have a single DES which is the case when you have a floppy DES drive or a CD drive or something, but typically the magnetic DES are put together in form of a multi-platter drive. There is an arm which moves forward and backward, covering different tracks on the disk and since there is an assembly of arms, the entire assembly moves forward and backward in one shot and therefore if the top arm is on let us say track number 44, then all the arms will be on the track number 44 and the circular track number 44 on each of the DES together will form what we call a logical cylinder. Whenever the arm is over a particular track, the data can be written onto the track or read from the track. For convenience, the track is divided into several sectors as is shown here. So essentially a sector becomes roughly equivalent to a block. Incidentally, all disk IO at the logical level is always done in terms of blocks. That means a block of data is written onto disk or a block of data is read from the disk. The location of the block could be anywhere and that is determined by the surface on which the block lies, the track in which the block lies and the sector within the track where the block lies. But all these computations we need not worry about in our higher level language programs. As far as we are concerned, we can consider the entire disk to be a series of blocks. Various files are allocated space in this disk. The space is released when this file is deleted or is shortened because of the editing etcetera or changes in the data. All of this is handled by the operating system. In a nutshell then, as far as we are concerned as programmers, we get a very clean interface to the file system through the operating system. How does the operating system view the files? I had mentioned it briefly in the first slide. Here are some more details. Files residing on disks are logically organized into directories and subdirectories. We have seen that. In the Unix file system, the directory itself and every subdirector is regarded as an independent file. So, just as file has a name, a directory has a name. Only thing is that data contained in a directory is not usually manipulatable by us and operating system organizes that data. Because it organizes the files in directories and subdirectories, the operating system is able to give us some kind of a niche area on the disk. It is not a single physical area. It is sort of logical space which is governed by what we call the home directory. In fact, whenever we log into a Unix system, operating system automatically takes us to a home directory and all our files or subdirectors will be contained in that home directory. As far as the operating system is concerned, a file is essentially a number of bytes which is the size of the file. It is important to note that for operating system, a file is just a collection of bytes and I am talking about files which we use in our application programs, not directories and subdirectories, the actual file. Now, it is possible that in some file, we may sort of put in numerical values of data such as values of the elements in matrices. In some files, we may keep data about employees of the organization or student's roll number, name, etcetera. In some other file, we could keep digital images such as what we had seen. In still another file, we could record a song. Now, the fact that different type of information exists in a file that is created by us is only known to us. That means to the program which created it and the program which is going to read and interpret that information. The semantics associated with the bytes stored in the disk is completely unknown to operating system. So, this is important to note as far as operating system is concerned, it does not care at all about what is the meaning of the contents inside the file. For it, it is merely a file. It is a set of bytes, ordered bytes. So, there is a notion of first byte, second byte, third byte, etcetera. The fact that a few bytes together form a disk block is also hidden from us. We need not know how physically file is organized on the disk. It actually creates a great simplicity for a programmer who can therefore regard a file as a stream of bytes. Just like a stream of water, the water flows in one direction. Similarly, the bytes flow. The flow is bi-directional in a file. I can let the bytes flow from a device to me or I can let the bytes flow from my program to the device. The first one will be reading operation, the second one will be writing operation. When the operating system reads data from a file, it is capable of detecting when there is no more data left in the file to read. This is important. If I am reading data from a file, let us say I have stored record of 2,000 employees. I do not know the exact numbers. It may be 1,958 because unlike in my program where I say give the number of employees and then read the data, etcetera, etcetera, which I might do while creating the file. But I will not necessarily maintain the number of employees as a separate information inside that file. That file may contain merely information about whatever 1,958 employees or whatever. There would be a program which will be maintaining this file. If a new employee joins, his or her record will be added. If an existing employee goes away, his or her record will have to be deleted. In short, at any point in time, the file may contain records of as many employees as are there on the roll and on a day to day basis, any user of the file may not know exactly how many employees are there as of now. Consequently, when I write a program to read data from the file and let us say I am reading the data sequentially one after another, I merely want to let us say get the names and let us say salary information about all the employees. Now, when I start reading the file, I will read it record by record. One employee data at one time. We shall see exactly how a record is to be described, etcetera. However, since I do not know in advance how many employees are there, suddenly while reading it will so happen that I have already read the data of the last employee. And when I say read data again, there is nothing in the dish to give it to me. Now, what will happen in that case? Should the program abort with an error? No. First of all, I should provide in my program some instructions which will say what is to be done in case the file ends. And second of all, my program must know when the file ends. It is the operating system which is capable of detecting the end of file. And it gives us a signal. It is called an end of file flag or EOF flag. We shall see how exactly EOF flags are handled in our program. But it is important to note there is the operating system's responsibility to tell us that file has ended. So, we can keep reading as long as we have provided for handling end of file situation, we can keep reading. And we can rest assured that the operating system is capable of giving us a signal saying file has ended. This is also important in the context of files which are not necessarily on the disk. Unique operating system in particular when it deals with other devices such as keyboard or a terminal. It actually treats these devices also as files called special files. Now, what is the meaning of keyboard as a file? Imagine that the keyboard was a disk and the data is not pre-written in that disk but a user is typing data. So, whatever user is typing data, that type data is available for me to read. Similarly, imagine terminal to be a file to which I am writing data. What happens to the data on the terminal? Well, some people read it. Even if you do not read it, if I keep throwing data on the terminal on the monitor, that means the data will keep vanishing. In fact, monitor represents effectively an endless target or endless capacity target of bytes. I can keep pushing bytes, infinite bytes because nothing is stored there. It evaporates in thin air. Similarly, a keyboard can be regarded as a limitless content of a file which is being fed to me to my program. Of course, I am careful. I will read characters by characters or line by line from a keyboard and I will write character by character onto a monitor. The point is while I write to the monitor, the end of file is to be signaled by my program. Whenever I stop writing, that is the end of the map. But when I am reading from the keyboard, I have to create something equivalent of an end of file. There is no end of file because as long as a human being is sitting there and I am reading characters, well, the data field can continue. But if for some reason the user of the program wants to tell me why my program is running, then look, Baba, there is no more data. Then there is no mechanism by which the user can signal an end of file and that is detected by the operating system. And the operating system is capable of giving me that signal, the same EOF signal that we saw earlier here. Incidentally on Unix systems, when you are sitting on a keyboard and you are expected to give any input because the program is waiting for an input, you can type control D as shown here. This control D signifies end of file on the keyboard. That is the convention that the Unix operating system follows. Now, I will describe the program execution environment. There is much more to the program execution environment than what is described here. What I have described is merely the set of standard files which are automatically opened by the operating system whenever my program starts execution and the operating system hands over these files to the program. Actually the operating system runs my program as what is called as a process. There is a context to a process. The process has a number. The process is allocated some memory. The process has several associated other paraphernalia called environment variables. For example, which will include a variable called path which will say which directories or sub directories would be searched if at all I am going to open a file. In fact, when I run a program if I just say dot a dot out then no program executes. But if my path contains the current directory dot then it will execute. Otherwise I have to say dot slash a dot out. So this is some peculiarities of the environment. More importantly whenever a program runs for example I have written a C program which has input output statements and may have some files. Whenever my program compiled program starts execution the operating system automatically gives three standard files to every program. These files as far as my running program is concerned are called standard input file or STD in, standard output file or STD out and standard error file or STD err. So STD in, STD out, STD err are the names of the files which are always opened by the operating system and they are attached to my program. Every program if there are ten programs running each of those ten programs actually will get these three files opened. As the direction of arrow indicates and the names suggest STD in is an input file that means the program can read bytes from the STD in. STD out is an output file that means a program can send bytes on to the output file. But when I say I will read in where from do I read in? When I say I will write out where do I write out? Well we shall see that in a moment. Let us very quickly look at STD err. STD err is a file which the operating system uses to send error messages to. So suppose the program has terminated or you are running a compiler, compiler is compiling your program and compiler is producing error messages. In general all error messages by convention are sent on STD err. As a matter of fact a good programmer will write a program in C also where the error messages will be directed to STD err. What is the objective? Let us quickly look at the first question that I asked. I have an input file but I do not know where the input is coming from. I have an output file I do not know where the output is going to and I have an STD err where again I do not know where the output is going. The operating system when it starts my program actually gives me a logical connection automatically also along with opening these files. This is the logical connection. By default the operating system connects these standard files to meaningful devices. So STD err is connected to keyboard so that means whenever user types a character that character can be read my program. Alternately whenever my program has any input command such as C in or scan F as we shall see later. By default characters will be read from the keyboard that means user will have to type something that will be ready. Similarly whenever I have a standard output command such as C out in C++ or print F. This is a function in C. Notice that print F does not mention any file where to print my formatted output. That file actually is STD out by default and STD out by default is connected to a display monitor. Curiously the STD err 5 which is given to my program is also connected to the same monitor. Why? Because ordinarily a user is expected to be sitting in front of a monitor and a keyboard. So if user wants to give any input it will be done through keyboard but if user wants to see the output produced by the program it is the monitor. Since only one monitor is there if there is an error while executing the program an operating system has to give an error message it will also come here. This then is the organization of default file arrangement that operating system provides. Now perhaps we are in a better position to understand the notion of redirection. Whenever at the command prompt before running the program I use redirection you already see what redirection is. These standard files are disconnected from the default devices and are connected instead to the named files. For example when I execute .slash a.out that is all and press return I will be expected to give input on keyboard and collect output or see output on the terminal. But if I say .slash a.out less than in data.text greater than out data.text then effectively what I am saying is please disconnect my STD in connection to the keyboard and instead connect it to in data.txt which is this file. Similarly I am saying when I say greater than out data.txt I am telling operating system you give me the STD out plus but please disconnect it from my monitor instead divert all the traffic of bytes that my program will generate to a file called out data.txt. Notice how easy then it becomes that while testing a program I may use keyboard and monitor. Let us say that I have primarily got my program errors more or less routinely moved out then I can simply create an output file. If I have a large data I can always make it read data from an input file. This is what will happen if for example I have to feed in the data of 2000 employees or feed in a data about a 200 by 200 matrix. If I have to run the program 20 times it is stupid for me to keep typing it every time. So we have seen how important and useful the real direction is and this is what happens inside in terms of the file system and file handling. Now we will look at the basic input output in C. First of all I reiterate that intrinsically the C programming language does not have any instruction for reading or writing data. This is very peculiar why if you take all earlier languages Fortran, Coball, Baskar they all had input output statements as part of the instruction set of the programming language itself. So in Fortran you could say read star something print star something you had a write command where you could give a device identity and give a format and so on. So formatted and formatted read write etcetera are intrinsically instructions built into the programming languages. C is a programming language which does not have any such instruction. Does it mean that C cannot do any input output? On the contrary it can do very powerful input output but all the input output is done through functions. So this is what is important that all input output operations in C if it all you want to do any reading any writing any insertion any deletion whatever whatever you have to use functions. So you have to invoke function calls. Spatial functions have been written and made available in the standard library to permit us to do that particularly to perform IO with keyboard and terminal. These spatial functions are scan f and print f as we know in C plus plus there are object classes and operators such as C in and C out which perform exactly the same. Parameters to these functions include a format stream followed by data values or expressions to be read or printed. So these are very special functions and the exact syntax of these functions is defined. Every textbook defines the simple syntax. What I have tried to do is I have gone to the website of the C programming standards. There is a standard library standard. It is very detailed how exactly format strings are to be supplied or specified what is the meaning of this etcetera etcetera. I am going to very quickly run through all of those not because I believe that we should discuss all of these with our students. Some simple formatting statements are good enough for the students initially and later on some additional details can be provided. But we as teachers ought to know the details about all flags, all parameters, all possible combinations that we can give etcetera so that if a student does the question we are in a position to answer it correct. What C does is that since as I said it has a format string followed by data values. So C applies the appropriate pattern to each value either for interpreting input characters or for generating formatted output. Very obviously then these are text files and more importantly these files are always read or written sequential. It is not possible for you to write a data on STD out which is let us say third record and later on write the first record. Because whatever you write is a sequence of byte in a stream is going as a sequential stream and this is an important difference between the STD in STD out files and the other files which I may want to open and handle on the disk. These files are different these are special devices. On the disk also I can write files which are written sequentially byte by byte or read sequentially byte by byte. In fact I can write to STD out and simply redirect it to a file on the disk and what gets created is a regular disk file. But it is read or written sequentially. Coming back to this scanf and printf therefore form perhaps the most widely used input and output commands for reading formatted data or writing formatted data. So let us look at printf. This function displays one or more values on the user terminal. Please take this with a pinch of salt. The statement technically should read this function writes one or more formatted values on STD out as far as Unix operating system. But mostly since STD out is connected to the terminal this statement is correct. Here is an example given printf percent d is a number backslash n n. Notice that the first entire string is a format string. What follows after comma is the parameter whose value is to be printed. So n is the value which I want to print. The string only tells the computer how exactly the value should appear. So look at the format specifier. In this case it is percent d. This means that convert n into a formatted value using this format specifier. We shall see shortly what are the different format specifiers and what they mean. The other characters inside the format string are displayed exactly as they are. Consequently I will get this percent d will be associated with the value that is to be printed n. So output that will be produced will be the value of n. Let us say n is 28. So it will say 28 is a number. That is what will appear as the output. Backslash n as you know represents a new line character. We can use backslash t for whatever whatever we want. What is important to notice whatever is written in this string is reproduced verbatim except for the format specifier. And format specifiers are always preceded by a percent symbol. So percent symbol followed by a character means I am specifying a format. Also if I am specifying a format I have some variable or expression in mind whose value I want to print. And therefore corresponding to every occurrence of a format portion here I must have a corresponding value to be printed. The format specifiers can appear anywhere but as I said each must correspond correctly to the corresponding value following the format. So if I have two format specifiers there should be two elements n, m, whatever x, whatever. And depending upon the type of value that is being indicated here for printing the corresponding format specifier should be applicable to those type of values. This is a slightly complex way of describing output format specifier in print m. This is also a very formal way. I have deliberately included this here for the sake of completeness. I remind you again of what I said sometime ago. This is not the way we should teach our students. However many times what happens is that when we are teaching fresh students we ourselves get used to get so much used to simple things that we sometimes forget the power of the specification that is available to us through the parameters of the function in the specification. This is to remind all of us that the format specification is very powerful in print f and scan f. This material I have given somewhere the reference. The reference is I think from a C++ website but any website which gives you the standard library description of functions will contain these things. So here is some very quick glimpse of what a format specification would look like. Format specification takes the following form with optional parts shown enclosed in angle brackets. Percent flags with precision length conversion. So notice now that optional parts are written in angle brackets. That means flag is optional, width specification is optional, precision specification is optional, length is optional. Only the conversion is mandatory after percent. So recall that the previous slide we had percent d. Obviously that d must be this conversion. So there are letters which are actually conversion letters and we shall see those letters also and ordinarily that is what we use percent d, percent d, percent f, percent d whatever. We rarely use these details. We do occasionally use length that occupies so many bytes on the output. This is a term to remind all of us that there is much more to the specification. So let me very quickly describe something more about as I said we are only having a glimpse of all these data. This is not exactly what we should ever teach students at least in the initial classes. However I would like to mention that there will be a few students in our class who will be interested in knowing more and it is always a good idea somehow to locate those students. You will know them within a month or so and sort of feed them or feed their intellectual hunger by something more and more and more and you can throw them to the larger part of the standard. So zero or more of the following flags can be given. Minus psi means left justify the conversion within its field plus psi means a signed conversion will always start with a plus or minus psi. So if a number is positive it will always have a plus, a number is negative it will always have a minus. Plus does not mean plus is printed. Plus means the conversion is signed conversion and minus means the left justify the conversion within the field. So observe that minus and plus have widely differing implications. Space if there is a space after percent if there is a space then it means if the first character of a signed conversion is not a signed insert a space it is over written by plus if it is present. Look at how precise the prescription is. A hash symbol forces an alternative form of output which is what? The first digit of an octal conversion will always be O. Inserts OX in front of a non-zero hexadecimal conversion. Notice that yesterday when we were seeing C out and we were printing values of the pointer. Notice that the pointer value which is essentially an address was printed in the sample output that I showed you in hexadecimal format. Notice that we observed that when the hexadecimal value of the address was printed it was preceded by 0X. Obviously internally the C programming language is using this as a default for printing hexadecimal numbers. Take this. So it will say pad D I O U X X E F F N G conversions on the left with zeros up to the field width. So if you have a zero flag that means the number 99 if you have asked it to write in five spaces it will not be written as blank blank blank 99 but as 0 0 0 9 9. If a precision is specified for any one of these conversions the flag is ignored but if the precision is not prescribed then this is what will happen and the behavior is undefined for other conversions. So look again at the precision of specification. Incidentally you would have now guessed that all these letters that I have you see here are actually the conversion specified. That is why ordinarily you will see in our programs percent D percent I percent E percent capital E percent F percent G etcetera. The decimal point which is a decimal integer specifying the minimum output field width I will not go through these details. These slides are available on the model you can actually go through these details but more importantly more than the slides these slides are only if you want to use them in the class at some later stage for a longer explanation or for yourself to peruse. Ideally you should see the standard library. As a matter of fact most of us even though we are teachers and we supposed to read tens of books when we are teaching a subject because the hustle bustle in life it does not happen that if we end up reading two or three books while we are teaching a course many times we say it is good enough. But it is important I believe for us teachers to occasionally look at reference material such as programming language standard or the complete description of standards library. Believe me there is a huge amount of very rich knowledge and useful knowledge which many times we do not apply because we do not know about it. So, this is just one suggestion. So, you can read these details I will just keep this precision for example. So, it specifies the minimum number of digits for some of the specifiers for the conversion. And then it says exactly how these will happen how these will be printed for which conversion what will be printed etcetera etcetera length. It precedes a specifier to print an integer type causes it to be treated as if it were a short look at again the procedure. Sometimes the meaning of these is not very clear even when you read that standard description two or three time. The best way in such a case is to casual up an example write a small program assign values to some variables arbitrarily and print them using this print f 1. Then that will clarify when we see on the output what is appearing that will clarify to us many of the doubts I strongly suggest that we should practice these things. Here are the format conversion specifiers D stands for signed decimal I stands for signed decimal U stands for unsigned decimal O for unsigned octal X for unsigned hexadecimal which will include digits 0 1 2 3 4 5 6 7 8 9 a b c d e f. Observe that if I use small x the hexadecimal number will be printed wherever the digit a b c d e f occurs represent the values 10 11 12 13 14 15 these will be printed in small alphabet. If I use capital X it will be printed in capital alpha f is for printing a double value. So all these specifications are useful to us in deciding how I can print as a particular value and I can control the exact way in which the printout will appear on my output device. Here are some more details on e g c e s etcetera you can go through these later. Here is an example this is simple and this is this kind of things we definitely use and should use while teaching our students. So percent six d will print a integer in six spaces percent seven s string fitted in seven character space percent eight point two f means it is a floating point number totally eight digits two after the decimal point percent eight point two g same but it will switch to exponential notation if required that means if the number is too large it cannot be fitted in this then it will print a mantissa write a letter e and write the appropriate exponent of course the number will be seen in a convention decimal notation not in the binary or hexadecimal notation. Here is an example include std i o dot h int main int a b c float p q r a is equal to minus 1 b is equal to 10 c is equal to 100 p is equal to 123 point 456 456 q is equal to 0.1234 r is equal to minus 12.34 these values have been these are obviously artificial values but they have been chosen to indicate what happens to our print out when we give different format specification. Also observe that in this entire workshop this is probably the first pure c program that we are writing there is no name space std whatever whatever we are using actually including of c functional library std i o dot h is the header five which gets included when I write the program and this is standard with most c program here is what will happen. So, these are the print out statements the first three print out statements use percent five d followed by a back slasher and they print the values of a b c if you recall that the values were minus one ten and hundred then this will print five decimal places. So, it will produce so many blanks before that what is important to notice that if my specification of length is only two and if a number is larger than two then it will occupy three places but you still print that number correct. Let us look at the print f with float numbers you recall the values of p q n r was 123 456 0.1234 minus 12.34 etcetera look at this specification the first three print out statements all ask the value of p q n r to be printed in eight digits with four digits after decimal point. So, here I have these eight spaces four digits here 0.321 that is the correct value the next one 0.1234 the next one actually r has a value minus 12.34 but since I have specified 8.4 it will print four digits after decimal point. On the other hand imagine if I have given a specification 4.2 f then the values will be printed like that 123.46 0.12 minus 12.36 observe that here I have said four total digits out of which two after decimal point. So, here I am getting two digits after decimal point two before the decimal point but here I have a larger number it will get printed. So, it will occupy one more space exactly similar treatment is given to the scan f function scan f needs to be passed pointers to its arguments remember we already discussed passing by reference and passing by value. So, scan f in order to print values it need to be passed pointers to its argument. So, that the values read can be assigned to the proper destinations forgetting to pass a pointer is a very common error please note that output we are taking the value and giving it out but input which is scan f we are taking a value from outside and that value has to be deposited in the storage memory location allocated to a variable. So, consequently if I want to read a value and store it in n then when n is mentioned in my scan f I must remember to pass a pointer. If I just say n the compiler would not know where to put it and arbitrary things will happen this is something that we ought to warn our students that they need to pass a pointer. By the way this should also tell you why I dislike scan f function for introduction to our students in the early part of the course remember at that time we have never discussed pointers. So, we have to tell our students that they have to imagine that this is like a rule in Bible, Gita or Kulaar that they have to say and n or and p at that time they have no clue what these and are they know n and m with some difficulty they associate that with storage locations. Maybe we I use the model of a Dumbo you might use some other model but the moment you say scan f something something and something believe me the students do get completely confused this is the reason why I strongly recommend that while you might have a course in C programming. But if you use GCC then there is absolutely no harm in using C in and C out for the most part of the early course and only at a later stage not necessarily towards the very end of the course you can introduce this scan f and print f somewhere in between. You may not even discuss pointers in complete details but describe in a few slides such as the examples that I had taken and that would be adequate for most students to understand the need for putting a pointer in scan f. But other than that I have found it extremely difficult to explain it to students if you are attempting to do that to sort of first year programming students this is my opinion.