You are on page 1of 37

About C

C is a programming language developed at AT&T’s Bell laboratories of USA in 1972 by Dennis Ritchie. In 1960 there are so many languages, almost each for a specific purpose. For example, COBOL was being used for commercial applications, FORTRAN for engineering and scientific applications and so on. The idea of having one language which can program all possible applications has been raised. Then some languages like ALGOL 60, CPL, BCPL, and B were developed. But they failed due to their loss of generality. Ritchie inherited the features of B and BCPL , added some of his own and developed C.

A Very Simple Program ( Structure of a C program)
This program which will print out the message - This is a C program #include <stdio.h> main() { printf("This is a C program\n"); } Though the program is very simple, a few points are worthy of note. Every C program contains a function called main. This is the start point of the program. #include <stdio.h> allows the program to interact with the screen, keyboard and filesystem of your computer. You will find it at the beginning of almost every C program.

main() declares the start of the function, while the two curly brackets show the start and finish of the function. Curly brackets in C are used to group statements together as in a function, or in the body of a loop. Such a grouping is known as a compound statement or a block. printf("This is a C program\n"); prints the words on the screen. The text to be printed is enclosed in double quotes. The \n at the end of the text tells the program to print a newline as part of the output. Most C programs are in lower case letters. You will usually find upper case letters used in preprocessor definitions or inside quotes as parts of character strings. C is case sensitive, that is, it recognizes a lower case letter and it's upper case equivalent as being different.

In C, a variable must be declared before it can be used. Variables can be declared at the start of any block of code, but most are found at the start of each function. Most local variables are created when the function is called, and are destroyed on return from that function. A declaration begins with the type, followed by the name of one or more variables. For example, int high, low, results[20]; Declarations can be spread out, allowing space for an explanatory comment. Variables can also be initialised when they are declared, this is done by adding an equals sign and the required value after the declaration. int high = 250; int low = -40; /* Maximum Temperature */ /* Minimum Temperature */

int results[20]; /* Series of temperature readings */ C provides a wide range of types. The most common are

There are also several variants on these types.

All of the integer types plus the char are called the integral types. float and double are called the real types.

Variable Names
Every variable has a name and a value. The name identifies the variable, the value stores data. There is a limitation on what these names can be. Every variable name in C must start with a letter, the rest of the name can consist of letters, numbers and underscore characters. C recognizes upper and lower case characters as being different. You cannot use any of C's keywords like main, while, switch etc as variable names. Examples of legal variable names include x x1 result x2 outfile out_file bestyet est_yet

It is conventional to avoid the use of capital letters in variable names. These are used for names of constants. Some old implementations of C only use the first 8 characters of a variable name. Most modern ones don't apply this limit though. The rules governing variable names also apply to the names of functions.

You should be familiar with operators such as +. • • • Octal constants are written with a leading zero . In addition. Expressions and Operators One reason for the power of C is its wide range of useful operators.Constants A C constant is usually just the written version of a number. 0. or force them to be treated as long integers. a required bit pattern can be specified using its octal equivalent. Character constants are usually just the character enclosed in single quotes. -. Some characters can't be represented in this way.890L. since string constants are more convenient. 'c'. 'a'. /. We can specify our constants in octal or hexadecimal. 'b'.015.73. A string constant is surrounded by double quotes eg "Brian and Dennis". The null character '\0' is automatically placed at the end of such a string to act as a string terminator. An operator is a function which is applied to values to give a result. Long constants are written with a trailing L . For example 1. so we use a 2 character sequence. 12. Hexadecimal constants are written with a leading 0x . . A character is a different type to a single character string.5e9. The string is actually stored as an array of characters. '\044' produces bit pattern 00100100.0x1ae. Character constants are rarely used. 5.

/ and % will be performed before + or . Here are some arithmetic expressions used within assignment statements. and the result is saved in a any expression. usually causing the program to crash. A simple example might look like y = (m * x) + c This assignment will save the value of the expression in variable y. Where division is performed between two integers. . Other operators are used for comparison of values.Arithmetic operators are the most common. Modulo reduction is only meaningful between integers. combination of logical states. Operators and values are combined to form expressions. with remainder discarded. Arithmetic operators Here are the most common arithmetic operators *. Brackets can be used to force a different order of evaluation to this. this will cause an error. and manipulation of individual binary digits. The values produced by these expressions can be stored in variables. If a program is ever required to divide a number by zero. the result will be an integer. or used as a part of even larger expressions. Assignment Statement The easiest example of an expression is in the assignment statement. An expression is evaluated.

Otherwise where types of different size are involved.velocity = distance / time. force = mass * acceleration. Type conversion You can mix the types of values in your arithmetic expressions. Versions where the operator occurs before the variable name change the value of the variable before evaluating the expression. C has some operators which allow abbreviation of certain types of arithmetic assignment statements. count = count + 1. char types will be treated as int. so Another shorthand notation is listed below These are simple to read and use. These operations are usually very efficient. the result will . They can be combined with another expression.

short. It is rare for logical values to be stored in variables. This is often done deliberately by the programmer. There is usually no trouble in assigning a value to a variable of different type.usually be of the larger size. int root root = sqrt( (double) i). (double) in this example. The result of sqrt( (double) i). They are usually generated as required by comparing two numeric values. the result will be a double. In this case it will be corrupted. int i = 256. The value is rounded down. long. • • The variable is too small to hold the value. The function has no way of determining the type passed to it. The variable is an integer type and is being assigned a real value. The function sqrt finds the square root of a double. The cast is made by putting the bracketed name of the required type just before the value. so a float and a double would produce a double result. but this is automatically converted to an int on assignment to root. The value will be preserved as expected except where. This is where the comparison operators are used. It improvises by using any of the integral types char. is also a double. so automatic conversion cannot take place. with a value of 0 representing false and any other value representing true. Values passed as function arguments must be of the correct type. unsigned. Relational Operators: C has no special type to represent logical or boolean values. The solution is to use a method called casting which temporarily disguises a value as a different type. . eg. This can lead to corrupt results. Where integer and real types meet. int. they compare two numeric values and produce a logical result.

x == y i > 10 a + b != c These comparisons are most frequently used to control an if statement or a for or a while loop. Or and Not operators. Logical Operators: These are the usual And. In such cases the second test is not evaluated. Comparison operators are used in expressions like the ones below. They evaluate their left hand operand.Note that == is used in comparisons and = is used in assignments. true || anything is always true. Not operates on a single logical value. its effect is to reverse its state. They are frequently used to combine relational operators. and then only evaluate the right hand one if this is required. . These will be introduced in a later chapter. Clearly false && anything is always false. for example x < 20 && x >= 10 In C these logical connectives employ a technique known as lazy evaluation. Here is an example of its use.

data is read in or printed out. Where a statement involves the use of several operators. the program makes a decision about what to do next. those with the lowest number in the table will be applied first. Input / Output.if ( ! acceptable ) printf("Not Acceptable !!\n"). • Assignment. Programs can be much more powerful if we can control the order in which statements are run. Control Statements: A program consists of a number of statements which are usually executed in sequence. are stored in variables. Statements fall into three general types. • • . Control. usually the results of calculations. where values. Precedence of C operators The following table shows the precedence of operators in C.

Each version consists of a test. After this. If we wish to have more than one statement following the if or the else. if (result >= 45) { printf("Passed\n"). or to decide between two courses of action. printf("Congratulations\n") } else { printf("Failed\n"). If is is false then the statement following the else is obeyed if present. The following test decides whether a student has passed an exam with a pass mark of 45 if (result >= 45) printf("Pass\n"). If the test is true then the next statement is obeyed.The if else Statement This is used to decide whether to do something at a special point. else printf("Fail\n"). Such a grouping is called a compound statement or a block. if (temperature < 0) print("Frozen\n"). (this is the bracketed statement following the if). they should be grouped together between curly brackets. It is possible to use the if part without the else. the rest of the program continues as normal. printf("Good luck in the resits\n"). } .

else if (result >= 45) printf("Passed: Grade C\n"). The switch Statement This is another form of the multi way decision. This works by cascading several comparisons. short or char). In the following example we are awarding grades depending on the exam result. The most general way of doing this is by using the else if variant on the if statement. .Sometimes we wish to make a multi-way decision based on several conditions. if (result >= 75) printf("Passed: Grade A\n"). In this example. As soon as one of these gives a true result. else if (result >= 60) printf("Passed: Grade B\n"). The same pattern can be used with more or fewer else if's. long. It is useful where we are only concerned in measuring a quantity when it is quite small. each test may involve a different variable or some combination of tests. and the final lone else may be left out. The variable must be an integral type. Each possible value of the variable can control a single branch. but can only be used in certain cases where. • Only one variable is tested. This is a function which converts an integer into a vague description. and no further comparisons are performed. In other cases. It is well structured. the following statement or block is executed. all comparisons test a single variable called result. default branch may optionally be used to trap all unspecified cases. • An example will clarify things. all branches must depend on the value of that variable. else printf("Failed\n"). It is up to the programmer to devise the correct structure for each programming problem. catch all. (int. A final.

.estimate(number) int number. case 1 : printf("One\n"). } } Each interesting case is listed with a corresponding action. break. they continue on allowing the same action for several values of number. one. break. break. case 3 : case 4 : case 5 : printf("Several\n"). case 2 : printf("Two\n"). many */ { switch(number) { case 0 : printf("None\n"). several. break. Since case 3 and case 4 have no following break. Both if and switch constructs allow the programmer to make a selection from a number of possible actions. /* Estimate a number as none. default : printf("Many\n"). The break statement prevents any further statements from being executed by leaving the switch. break. two.

This ensures that the loop body is run at least once. here is a function to return the length of a string. Computers are very good at repeating simple tasks many times. Loops allow a statement. do while and for. It is very flexible. while (string[i] != '\0') i++. '\0'. The for loop is frequently used. while. int string_length(char string[]) { int i = 0. to be repeated. return(i).The other main type of control statement is the loop. } Remember that the string is represented as an array of characters terminated by a null character . • The do while loops is similar. • The while loop keeps repeating an action until an associated test returns false. or block of statements. but the test occurs after the loop body is executed. • The while Loop The while loop repeats a statement until the test at the top proves false. Loops C gives you a choice of three types of loop. and novice programmers should take care not to abuse the power it offers. This is useful where the programmer does not know in advance how many times the loop will be traversed. usually where the loop will be traversed a fixed number of times. As an example. the loop is C's way of achieving this.

The for Loop The for loop works well where the number of iterations of the loop is known before the loop is entered. The second is a test. . the function will work for a string of any size. and loops back to read again if it was unacceptable. scanf("%d". The function takes the array and the number of elements as arguments. This guarantees that the loop is executed at least once before continuing. The do while Loop This is very similar to the while loop except that the test occurs at the end of the loop body. The size of the array is not specified.The string is passed to the function as an argument. This is usually the initialisation of the loop variable. The head of the loop consists of three parts separated by semicolons. • The first is run before the loop is entered. • • The example is a function which calculates the average of the numbers stored in an array. Then the loop is exited and the index of the null is returned. 0 for no :"). While the character isn't null. The test then verifies the data. The while loop is used to look at the characters in the string one at a time until the null character is found. Such a setup is frequently used where data is to be read. This is usually an increment of the loop counter. the loop is exited when this returns false. The third is a statement to be run every time the loop body is completed. } while (input_value != 1 && input_value != 0). the index is incremented and the test is repeated. do { printf("Enter 1 for yes. &input_value).

This will cause the loop to run indefinitely unless interrupted by some other means. control passing to the first statement beyond the loop or a switch. This allows a loop with more than one controlling variable. for(i = 0. int count) { float total = 0. } The for loop ensures that the correct number of array elements are added up before calculating the average. . i < count.0. The example below illustrates the definition of such a loop. It is used to exit from a loop or a switch. A blank comparison statement will always be treated as true. A blank first or last statement will mean no initialization or running increment. hi--. This might be a return or a break statement. It is also possible to squeeze several statements into the first or third position. with variables hi and lo starting at 100 and 0 respectively and converging.float average(float array[]. return(total / count). lo++) The for loop is extremely flexible and allows many types of program behavior to be specified simply and quickly The break Statement We have already met break in the discussion of the switch statement. The three statements at the head of a for loop usually do just one thing each. separating them with commas. for (hi = 100. hi >= lo. lo = 0. however any of them can be left blank. i++) total += array[i]. int i.

jump to the test statement. Where an array is declared in the main function it will usually have details of dimensions included. In a do while loop.With loops. Individual array elements are identified by an integer index. Arrays can have more dimensions. It is possible to use another type called a pointer in place of an . Each index has its own set of square brackets. jump to the test. Like a break. In a for loop. jump to the test statement. and perform the iteration. break can be used to force an early exit from the loop. or to implement a loop with a test to exit in the middle of the loop body. You are unlikely to use it very often. The continue Statement This is similar to break but is encountered less frequently. Arrays An array is a collection of variables of the same type. Single dimensioned arrays which are declared like this int results[20]. In C the index begins at zero and is always written inside square brackets. • • • In a while loop. in which case they might be declared as int results_2d[20][5]. int results_3d[20][5][3]. A break within a loop should always be protected within an if statement which provides the test to control the exit condition. It only works within loops where its effect is to force an immediate jump to the loop control statement. continue should be protected by an if statement.

So for example if we have a function which sorts a list (represented by an array) then the function will be able to sort lists of different sizes. When passed as an argument to a function. It provides very precise control. Most computers perform buffering of input and output. This means that they'll not start reading any input until the return key is pressed. It is therefore usual to compare this . } Character Input / Output This is the lowest level of input and output. so this information will have to be passed as an additional argument.array. This means that dimensions are not fixed immediately. the receiving function need not know the size of the array. but space can be allocated as required. i++) total += array[i]. i < size. This is an advanced technique which is only required in certain specialised programs. here is a simple function to add up all of the integers in a single dimensioned array. int size) { int i. for(i = 0. int add_array(int array[]. As an example. The drawback is that the function is unable to determine what size the list is. return(total). If there is an error then EOF (end of file) is returned instead. int total = 0. and they'll not print characters on the terminal until there is a whole line to be printed. but is usually too fiddly to be useful. getchar getchar returns the next character of keyboard input as an int.

} putchar putchar puts its character argument on the standard output (usually the screen).h> /* For definition of toupper */ #include <stdio. The following example program converts any typed input into capital letters.h> /* For definition of getchar.d. } . EOF can be generated by typing Control . it will never be equal to EOF. #include <stdio. while((ch = getchar()) != EOF) i ++. If the return value is stored in a char.h> main() { int ch. EOF */ main() { int ch. To do this it applies the function toupper from the character conversion library ctype.h to each character in turn. i = 0. while((ch = getchar()) != EOF) putchar(toupper(ch)). here is a program to count the number of characters read until an EOF is encountered. putchar. As an example. printf("%d\n". i). so error conditions will not be handled correctly.value against EOF before using it. #include <ctype.

printf This offers more structured output than putchar. a control string. Control string entries which match values to be read are preceeded by the percentage sign in a similar way to their printf equivalents. followed by a list of values to be substituted for entries in the control string. It is also possible to insert numbers into the control string to control field widths for values to be displayed. Character strings are an exception to this. but can be right justified by putting a . . followed by the list of items to be read. However scanf wants to know the address of the items to be read. a decimal integer right justified in a 6 space field. For example %6d would print a decimal value in a field 6 spaces wide. and usually the easiest to use for input and output. The versions offered under C are a little more detailed. Display is left justified by default. Since a string is already a character pointer. since it is a function which will change that value. %8.Formatted Input / Output They are closest to the facilities offered by Pascal or Fortran.before the format information. which controls what gets printed. Its arguments are. we give the names of string variables unmodified by a leading &. Like printf it has a control string. for example %-6d. Therefore the names of variables are preceeded by the & sign.2f would print a real value in a field 8 spaces wide with room to show 2 decimal places. scanf scanf allows formatted reading of data from the keyboard. in order. offering precise control of layout.

Whole Lines of Input and Output Where we are not too interested in the format of our data. /* Define string sufficiently large to store a line of input */ while(gets(line) != NULL) /* Read line { } } Note that putchar. Example: Program which uses gets and puts to double space typed input. or perhaps we cannot predict its format in advance. printf("\n"). #include <stdio. So can getchar. This approach allows us to read in a line of input. and follows it with a newline character. When all input is finished. and then use various string handling functions to analyse it at our leisure gets gets reads a whole line of input into a string until a newline or EOF is encountered. printf and puts can be freely used together. scanf and gets puts(line). /* Print line */ /* Print blank line */ */ . we can read and write whole lines as character strings. It is critical to ensure that the string is large enough to hold any expected input lines. NULL as defined in stdio.h> main() { char line[256].h is returned. puts puts writes a string to the output.

} The function follows a simple algorithm. double power(double val. If no return value is required. Let us examine the details of this function. each pair separated by commas. Here is a function which raises a double to the power of an unsigned. . double power(double val. none should be used when calling the function. the name of the function. The arguments and their types are enclosed in brackets. unsigned pow) This line begins the function definition. If the programmer wants a return value.0. unsigned i. and variable ret_val stores the value to be returned. C assumes that every function will return a value.Functions in C Almost all programming languages have some equivalent of the function. return(ret_val). for(i = 0. A for loop is used to control the number of multiplications. Some languages distinguish between functions which return variables and those which don't. and returns the result. unsigned pow) { double ret_val = 1. multiplying the value by itself pow times. You may have met them under the alternative names subroutine or procedure. and a list of arguments used by the function. i++) ret_val *= val. It tells us the type of the return value. i < pow. this is achieved using the return statement.

This function also demonstrates a new feature. line). Any variables declared here will be treated as local unless specifically declared as static or extern types. fprintf(stderr. Some void type functions might use return. pow). It shows that no return value is used. any return value will then be meaningless.The body of the function is bounded by a set of curly brackets. void error_line(int line) { } The definition uses type void which is optional. "Error in input data: line %d\n". This calls the function power assigning the return value to variable result. On reaching a return statement. The example function can be called by a line in another function which looks like this result = power(val. Otherwise the function is much the same as the previous example. line). fprintf (stderr. except that there is no return statement. This is rather like using break to jump out of a loop. but only to force an early exit from the function. control of the program returns to the calling function. return(ret_val). and not to return any value. If the final closing curly bracket is reached before any return value. Here is an example of a function which does not return a value. The bracketed value is the value which is returned from the function. "Error in input data: line %d\n". then the function will return automatically. .

but this seems a good place to introduce the pointer type. stderr is a special UNIX file which serves as the channel for error messages. Messages sent to stderr will appear on screen even if the normal output of the program has been redirected to a file or a printer. Local variables are declared within a function. Pointers in C Pointers are not exclusive to functions. The function would be called as follows error_line (line_number).This is a variant on the printf statement. and it becomes available when the function is called again. fprintf sends its output into a file. Its address could be represented by the symbol &i. they don't die on return from the function. and is available to any other function which accesses them. Global variables don't die on return from a function. the file is stderr. Static variables are slightly different. Scope of Function Variables Only a limited amount of information is available within each function. They are created anew each time the function is called. Variables declared within the calling function can't be accessed unless they are passed to the called function as arguments. Values passed to the function as arguments can also be treated like local variables. it should be stored like this. If the pointer is to be stored as a variable. The only other contact a function might have with the outside world is through global variables. Imagine that we have an int called i. Their value is retained. so this is a good way to display error messages from your programs. . In this case. Instead their last value is retained. It is usually connected to the console of the computer system. and destroyed on return from the function.

i. fiddle(int x. A very simple program to call this function might be as follows. which gives the value at the end of the pointer is *. printf("Finishing fiddle: x = %d. The opposite operator. The following function fiddle takes two arguments. pointer declaration and pointer de-referencing. would be i = *pi. x ++. x is an int while y is a pointer to int. . This is a very confusing subject. int * is the notation for a pointer to an int. x. *y). y = %d\n". we must de-reference it before incrementing its *pi = &i. It changes both values. int j = 0. fiddle(i. y = %d\n". j). printf("Calling fiddle now\n"). so let us illustrate it with an example. printf(" Starting main : i = %d. } since y is a pointer. j = %d\n". An example of use.. as in &i we say it is referencing i. &j). known as de-referencing pi. (*y)++. Multiplication. int *y) { printf(" Starting fiddle: x = %d. main() { int i = 0. printf("Returned from fiddle\n"). & is the operator which returns the address of its argument. Take care not to confuse the many uses of the * sign. *y). When it is used. x.

has changed. arr is an array. Dereferencing the array name will give the 0th element. The result of running the program will look like this. j). Where the value of an argument isn't modified. Starting main : i = 0 . In the following examples. j = %d\n". If you wish to use arguments to modify the value of variables from a function. &j).j = 0 Calling fiddle now Starting fiddle: x = 0.printf("Finishing main : i = %d.. j = 1 After the return from fiddle the value of i is unchanged while j. y = 0 Finishing fiddle: x = 1. } Note here how a pointer to int is created using the & operator within the call fiddle(i. The array is treated as a constant in the function where it is declared. Arrays and Pointers An array is actually a pointer to the 0th element of the array. these arguments must be passed as pointers. This means that we can modify the . i. This gives us a range of equivalent notations for array access. and de-referenced within the function. which was passed as a pointer. y = 1 Returned from fiddle Finishing main : i = 0. There are some differences between arrays and pointers. the value can be passed without any worries about pointers.

While you will inevitably meet pointers in the form of strings. This is met most frequently in the case of character strings. and are made available by putting the line #include <strings. the UNIX system has a number of other string handling functions within its libraries. A number of the most useful ones are contained in the <strings. or as variable arguments for functions.h> file. .h> near to the head of your program file. all the difficult stuff gets done automatically. A couple of the functions are described below. but not the array itself. In the same way. Other String Handling Functions As well as sprintf and sscanf. they need not be used in most other simple types of programs. Since an array is like a pointer. Since the array is implemented as a hidden pointer. but is most frequently written as char *string. and modify elements of that array without having to worry about referencing and de-referencing. This could be declared as char string[]. Either of these definitions is independent of the size of the array being passed. the argument vector argv is an array of strings which can be supplied to function main. so statements like arr ++ are illegal. which are implemented as an array of type char. It can be declared as one of the following. A function which expects to be passed an array can declare that parameter in one of two ways. but arr[n] ++ is legal.values in the array. Don't panic if you find pointers confusing. we can pass an array to a function.

course. allowing its use throughout the program. thus extending the number of available types. A structure is a convenient way of grouping several pieces of related information together. typedef defines and names a new type. int age. A structure can be defined as a new named type. The variable name is st_rec. Defining a Structure A structure type is usually defined near to the start of a file using a typedef statement. it has members called name. Here is an example structure definition. It can use other structures. This defines a new type student variables of type student can be declared as follows. student st_rec. int year. } student. though this can get complicated unless you are careful. arrays or pointers as some of its members. . char course[128]. These variables can be of different types. typedef struct { char name[64]. and each has a name which is used to select it from the structure.Structures in C A structure is a collection of variables under a single name. age and year. typedefs usually occur just after the #define and #include statements in a file.

which is easier to re-use. If we are only interested in one member of a structure. however we refer to it by the name t_rec.Accessing Members of a Structure Each member of a structure can be used just like a normal variable. Of course if we wish to change the value of that member. Since selecting a member from a structure pointer happens Here the dot is an operator which selects a member from a structure. This method is a little clumsy to type. Where we have a pointer to a structure we could dereference the pointer and then use dot as a member selector. it has its own operator -> which acts as follows. it is probably simpler to just pass that member. member name of structure st_rec will behave just like a normal array of char. When a structure is passed as an argument. but its name will be a bit longer. This can prove expensive where structures are large or functions are called frequently. Assume that st_ptr is a pointer to a structure of type student We would refer to the name member as st_ptr -> name Structures as Function Arguments A structure can be passed as a function argument just like any other variable. we must pass a pointer to that structure. To return to the examples above. This will make for a simpler function. . This is just like passing a pointer to an int type argument whose value we wish to change. Where we wish to modify the value of members of the structure. Passing and working with pointers to large structures may be more efficient in such cases. This raises a few practical issues. we should pass a pointer to it. each member of the structure is copied.

C File Handling .File Pointers C communicates with files using a new datatype called a file pointer. You will usually use fopen as follows if ((output_file = fopen("output_file". This type is defined within stdio. This would be done using a statement like fclose(output_file). . "output_file"). which is usually one of: Closing a file using fclose The fclose command can be used to disconnect a file pointer from a file. both are strings. This is usually done so that the pointer can be used to access a different file. Opening a file pointer using fopen Your program must open a file before it can access it. the second is an access character. A file pointer called output_file is declared in a statement like FILE *output_file. If the file cannot be opened for any reason then the value NULL will be returned.h. so it is a good idea to close a file when you have finished using it. and written as FILE *. which returns the required file pointer. the first is the name of the file to be opened. "w")) == NULL) fprintf(stderr. "Cannot open %s\n". Systems have a limit on the number of files which can be open simultaneously. fopen takes two arguments. This is done using the fopen function.

The data is formatted according to a control string of the same form as that for p rintf. They are called sprintf and sscanf. However it is usually better to close the files properly. gets requires the programmer to specify the maximum number of characters to be read. Character Input and Output with Files This is done using equivalents of getchar and putchar which are called getc and putc. sscanf is very useful for converting strings into numeric v values. Whole Line Input and Output using File Pointers Predictably. The programmer should be careful in using them. sscanf takes data from a string and stores it in other variables as specified by the control string. This is done in the same way that scanf reads input data into variables. fgets and fputs retain the trailing newline character on the line they read or write. . sprintf puts formatted data into a string which must have sufficient space allocated to hold it. wheras gets and puts discard the newline. which identifies the file pointer to be used for input or output. Each takes an extra argument. the simplest way to avoid incompatibility with the newline is to use fgets and fputs for files and standard channels too.If files are still open when a program exits. equivalents to gets and puts exist called fgets and fputs. since they are incompatible with gets and puts. This can be done by declaring it as an array of char. When transferring data from files to standard input / output channels. the system will close them for you. Formatted Input Output with Strings These are the third set of the printf and scanf families.

NULL is commonly written as '\0'. There is an example of this in the string_length function example in the section on Functions in C. then the pointer variable does not reference any object (i. It is returned by read commands of the getc and scanf families when they try to read beyond the end of a file. NULL is returned by read commands of the gets family when they try to read beyond the end of an input file. The End of File Marker EOF is a character which indicates the end of a file. If a pointer. See the section on fopen for an example of this. stdout).For Example. since it is handled automatically. It is the string termination character which is automatically appended to any strings in your C program. read a line from the keyboard using fgets(data_string. Where it is used as a character. The Null Pointer or Character NULL is a character or pointer value.e. However it sometimes makes a useful target to terminate a string search. a pointer to nothing). EOF. and write a line to the screen using fputs(data_string. It is usual for functions which return pointers to return NULL if they failed in some way. NULL. 80. You usually need not bother about this final \0'. Deleting a File: You can delete a file with the function remove. The return value can be tested. . stdin).

it remains accessible under its other names. then the file is deleted as well. Random access to files: Sometimes it is required to access only a particular part of the and not the complete file. If this is the file's only name. (If the file had any other names aside from oldname. Offset is a number or variable . position).) The directory containing the name newname must be on the same file system as the file (as indicated by the name oldname). int remove (const char *filename) The name remove is declared in `stdio. Fileptr is a pointer to the file concerned.h'. it continues to have those names.Deletion actually deletes a file name.offset. const char *newname) The rename function renames the file name oldname with newname. The file formerly accessible under the name oldname is afterward accessible as newname instead. This can be accomplished by using the following function: fseek fseek function: The general format of fseek function is a s follows: fseek(file pointer. int rename (const char *oldname. Renaming a File: The rename function is used to change a file's name. This function is used to move the file position to a desired location within the file. If the file has other names as well.

Value Meaning 0 Beginning of the file 1 Current position 2 End of the file. that corresponds to the current position. Using #define to Implement Constants We have already met this facility. in its simplest form it allows us to define textual substitutions as follows. rewind (fp). n = ftell (fp). It returns number of bytes from the beginning of file. #define MAXSIZE 256 This will lead to the value 256 being substituted for each occurrence of the word MAXSIZE in the file. Offset specifies the number of positions (bytes) to be moved from the location specified bt the position. ftell function: ftell takes a file pointer as input and return a number of type long.of type long. The position can take the 3 values. and position in an integer number. rewind function: rewind function takes a file pointer and resets the position to the start of the file. Using #define to Create Functional Macros .

integers or a mixture of the two. The problem can be solved using a more robust definition of DOUBLE #define DOUBLE(x) (x+x) Here the brackets around the definition force the expression to be evaluated before any surrounding operators are applied. And since * has a higher priority than +. In particular the textual substitution means that arithmetic expressions are liable to be corrupted by the order of evaluation rules. Macros don't care about the type of their arguments. Macros are full of traps for the unwary programmer. • • • Macros are generally fairly small. Here is an example of a macro which won't work. Programmers sometimes call such type flexibility polymorphism. . a = b + (b * c). there is no effect on program performance (as with functions). This should make the macro more reliable. but with the following minor differences.#define can also be given arguments which are used in its replacement. #define DOUBLE(x) x+x Now if we have a statement a = DOUBLE(b) * c. Recursive macros are generally not a good idea. This will be expanded to a = b+b * c. The definitions are then called macros. Macros work rather like functions. Hence macros are a good choice where we might want to operate on reals. the compiler will treat it as. • Since macros are implemented as a textual substitution.

The code will print the command line parameters xxx.argc). argv and argc. yyy and zzz. argv[0] points to a string that contains the first parameter on the command line (the program's name).Command-line arguments C provides a fairly simple mechanism for retrieving command line parameters entered by the user. each element of the array is a pointer. The char *argv[] line is an array of pointers to string. In other words. one per line. . } In this code. Enter the following code and compile it: #include <stdio. x<argc. for (x=0. so understanding them is useful to any C programmer. argv structures appear in a fair number of the more advanced library calls. The argv parameter is an array of pointers to string that contains the parameters entered when the program was invoked at the UNIX command line. argv[1] points to the next parameter. To try this. Thus. compile the code to an executable file named aaa and type aaa xxx yyy zzz. The argc integer contains a count of the number of parameters. It passes an argv parameter to the main function in the program. x++) printf("%s\n".h> int main(int argc. return 0. the main program accepts two parameters. and so on. to the first character of the string). printf("%d\n". char *argv[]) { int x. This particular piece of code types out the command line parameters. and each pointer points to a string (technically. You will find that the preceding code does nothing more than print each of the valid strings pointed to by argv. The argc variable tells you how many of the pointers in the array are valid.argv[x]).

data type). These two macros use a variable of type va_list. The va_arg returns a data value of data type from list to which va_list variable is pointed.Because argv exists. The number of arguments supplied to printf() is not constant. } Variable Length Arguments: We have used printf() to print output on the monitor. you might have your program detect the word help as the first parameter following the program name. The syntax of va_arg is: Variable = va_arg ( va_list variable. File names can also be passed in and used in your fopen statements. For example. At least one parameter must precede the ellipses. These macros provide a method for accessing the arguments of the function when function takes a fixed number of arguments followed by a variable number of arguments.h” called va_start. which allow us to handle variable length arguments. va_arg and va_list. The number of arguments is variable. and dump a help file to stdout. There are three macros available in the file “stdarg. C supports to write functions with variable length arguments. The ellipses in the function represent the variable length arguments. Va_arg is used to move the pointer to the next argument. Variable-length argument lists are specified in function prototypes with ellipses. … ). . you can let your program react to command line parameters entered by the user fairly easily. For example: char function_name( int lower. Out of these macros va_start is used to initialize a pointer to the beginning of the list of optional arguments.

} . num.h> main() { int max. va_list ptr. va_start(ptr. 100. 1.max). printf(“\n maximum of 23. 1. int). 15. 300. printf(“\n maximum of 23. max=va_arg(ptr. count. } return(max). count<tot_num.max). 92. irrespective of the number of values passed to it. 92. } findmax( int tot_num.h> #include<stdio. # include<stdarg. tot_num). The first argument it takes is the count of the numbers. 50 is : %d”. max = findmax(3. 92. 1.For example consider a function findmax(). 50 is : %d”. 50). 29). max = findmax(5. 15. which would find out maximum value from a set of values. for(count=1. … ) { int max. count++) { num = va_arg(ptr. if (num>max) max=num. 15.