C category list
Pointers
A pointer is a variable that stores a memory address. A pointer declaration takes the following form:
datatype *pointer_name;
Here, datatype is the pointer's base type and must be a valid C data type and pointer_name is the user-defined name. The asterisk indicates that the declaration is a pointer. The base type is important because the compiler needs to know how many bytes make up the value pointed to.
Initialising a Pointer.
Pointer initialisation is the process of assigning the address of a variable to a pointer variable. Each pointer is set to the address of the first byte of the pointed-to variable. When a variable's address is unknown during the declaration, a null value should be assigned to the pointer. A pointer which is assigned a null value is called a null pointer. A non-initialised pointer is called a wild pointer and will contain a random or junk value. Wild pointers are dangerous because they cause a program to access invalid memory locations leading to unpredictable results. To store the address of this variable in a pointer use the referencing operator.
Assigning and Accessing Values
The indirection operator or dereferencing operator (*) operates on a pointer and returns the value stored in the address kept in the pointer variable.
In the example below, pTr is created as an int pointer initialised with a NULL value. This pointer is then assigned to the address of the int variable a_value . The dereferencing operator is then used to output the value stores at the address of pTr.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int a_value = 30; // declares int variable to value 30 int * pTr=NULL;// declares pointer name pTr of type int and assigns NULL value pTr= &a_value; //sets pointer pTr to address of a_value printf("%d",*pTr); }
Pointer Arithmetic
There are only four arithmetic operators that can be used on pointers: ++, – –, +, and –
An increment or decrement operation on a pointer will point to the next value in the memory block. The new location will represent the location of the next variable value and not the next byte of memory. For instance, using the ++ on an int pointer tells the compiler to point to the next consecutive integer. Decrementing pointers ( -- ) has the opposite effect. The pointer address is decremented by the size of the type being pointed to. This ensures that the pointer points to the beginning of some valid data and not an arbitrary memory location. In the case of char pointer, an increment or decrement will only change the pointer value by 1 since characters are one byte long. Every other pointer type will increase or decrease by the size of its base type.
Pointer to an Array
Pointers can also be used to address elements of an array. When an array is declared the compiler allocates sufficient memory to access all the elements of that array. The base address is the address of the first element. If a pointer is declared to point to the array then each array element can be accessed by increasing or decreasing this pointer.
int main() { int a[5]={1,2,3,4,5};//declare array int *ptr=a;//set pointer *ptr to start of array for (int i=1;i<=5;i++) { printf ("%d",*ptr);//dereference value held at pointer address *ptr++;//increase pointer }
}
Note that there is no requirement to use the address operator (&) when assigning a pointer to an array.
- Details
- Category: C category list
- Hits: 88
Structures
A structure is a user-defined collection of one or more variables grouped under a single name. This allows a programmer to wrap related variables with different data types into a single entity. This makes it easier to manipulate data in the program. The variables in a structure can be of different data types. Each variable within a structure is called a member of the structure.
Defining and Declaring Structures
The struct keyword is used to declare the beginning of a structure definition followed immediately by the name of the structure. Following the structure tag is an opening curly brace followed by a list of the structure’s member variables and a closing curly brace. Once the structure type has been defined, variables of that structure type can then be declared with structure definition or after the structure is defined (see below)
struct account { int accountno; char *lastname; char *firstname; int age; unsigned int telephone; } user1;//structure variable defined with structure struct account user2, user3;//structure variable outside of the structurevid, Jack;
Note: In C++, the struct keyword is optional before the variable declaration. In C, it is compulsory.
Accessing Members of a Structure
Structure members are accessed using the dot operator between the structure and the member name. Thus, to set the value of variable age for user1 in the above structure account use the following -
user1.age = 21;
Initialise Structures
When initialising a struct, the initialiser consists of a brace-enclosed, comma-separated list of values in the same order as the variables in the structure definition.
For instance to initialise a struct variable user4 using the structure above -
struct account user4={123,"john","doe",12,123456789};
Structure members cannot be initialised within the declaration because when a datatype is declared, no memory is allocated for that datatype. Memory is allocated only when variables are created.
Designated Initialisation - allows structure members to be initialised in any order. Each value is preceded by a designated initialiser corresponding to the structure variable name. Initialisation then moves forward in order of declaration if no further designated initialisers are specified. This feature has been added to the C99 standard. For example -
struct account user5={.lastname="jill","doe",123456789};
Any remaining members not initialised will be set to Zero.
Arrays of Structures
An array of structures is a sequential collection of structures. After the structure has been defined, an array of structures is declared as follows-
struct userdetails list[100];
The above statement declares an array named list that contains 100 elements. Each element is a structure of type userdetails and is identified by subscript. The structure data can be manipulated by specifying the appropriate index value of the array. Like a standard Array, an array of structures can be initialised at compile time.
Structures and Pointers
Structures can be accessed and manipulated by pointers. Pointers to structures can be declared by preceding the variable name with an asterisk. The individual member variables are accessed using the operator instead of the .(dot) operator
#include <stdio.h> int main(void) { struct account{ unsigned int accountno; char *firstname; char *lastname; unsigned int telephone; } user1={123,"joe","blogs",123456789};//structure variable user1 defined and initiated struct account *ptrStr;//create pointer of type struct account ptrStr = &user1;//set pointer to address of user1 printf("%d %s %s %d", ptrStr->accountno,ptrStr->firstname, ptrStr->lastname,ptrStr->telephone);//access elements using -> return 0; }
Passing Structures as Arguments to Functions
An entire structure can be passed to a function as a parameter. This structure can be transferred to a function either using call by value or call by reference scheme
#include <stdio.h> struct account{ //declare stucture unsigned int accountno; char *firstname; char *lastname; unsigned int telephone; }; void function1(struct account user1copy) //declare fuction with argument type struct account { printf("%d\n",user1copy.accountno); printf("%s\n",user1copy.firstname); printf("%s\n",user1copy.lastname) ; printf("%d\n",user1copy.telephone); } int main(void) { struct account user1={123,"joe","blogs",123456789};//initialise structure function1(user1);//call structure passing parameter user1 return 0; }
Passing a structure parameter by value – To pass a structure parameter by value declare the function to use the structure type. When the function is called, the function creates and uses a copy of the structure. Any modification to the structure made inside the function won't affect the original value.
Passing a structure parameter by reference - To change the structure inside of our function, then it must be passed by reference. Any changes made to the structure members are reflected in the original structure. This is because pointers deal directly with the data stored in the memory.
Structures Within Structures
In C, a structure declaration can be placed inside another structure (nesting). This declaration can either be an Embedded Structure Declaration or by making two separate structure declarations.
#include <stdio.h> int main(void) { struct outer {//declare outer stucture int member1; int member2; int member3; struct embedded{//declare inner structure int member_1; int member_2; int member_3; } embeddedvar;//declare inner struct variable } outervar={3,4,5,{1,2,3}};//declare outer stuct variable and initialise outer values and then inner values // structure embedded printf("%d", outervar.embeddedvar.member_1);//output embedded member_1 printf("%d", outervar.member1);//output member1 return 0; }
Separate nested Structure example
#include <stdio.h> int main(void) { struct embedded { int member_1; int member_2; int member_3; }; struct outer { struct embedded embeddedvar; //declare embadded variable int member1; int member2; int member3; } outervar={{1,2,3},3,4,5}; printf("%d", outervar.embeddedvar.member_1); printf("%d", outervar.member1); return 0; }
- Details
- Category: C category list
- Hits: 70
Unions
A union is a special data type that stores different data types in the same memory location. Unions are similar to structures in that a union can be defined with many members, but only one member can contain a value at any given time.
Declaring, and Initialising Unions
Unions are defined and declared in the same fashion as structures however the keyword union is used instead of struct. The union is created only as big as necessary to hold its largest data member. A union can be initialised on its declaration but because only one member can be used at a time, only one member can be initialised. Unions initialised with a brace-enclosed initialiser only initialise the first member of the union but individual members can be initialised by using a designated assignment value(see initialising structures). The format and initialisation of the union statement are as follows:
#include <stdio.h> int main( void ) { union shared_tag { char c; int i; float f; double d; } shared={33}; printf("%c character value",shared.c); printf("\n%d integer value ",shared.i); printf("\n%f float value",shared.f); printf("\n%d double value",shared.d); shared.i = 33; printf("\n%c",shared.c); printf("\n%i",shared.i); printf("\n%f",shared.f); printf("\n%f",shared.d); shared.d = 33.333333333333; printf("\n%c",shared.c); printf("\n%i",shared.i); printf("\n%f",shared.f); printf("\n%f",shared.d); return 0; }
Individual union members can be accessed by using the member operator however, only one union member should be accessed at a time.
Unions and Pointers
Unions like structures can be accessed and manipulated by pointers and are declared by preceding the variable name with an asterisk. The individual member variables can be accessed by using the → operator
#include <stdio.h> int main(void) { union data { char c[10]; int i; }; union data charvalue={"union data"}; union data *ptrcharvalue; ptrcharvalue=&charvalue; union data intvalue={13}; union data *ptrintvalue; ptrintvalue=&intvalue; printf("%s", ptrcharvalue->c); printf("\n%i",ptrintvalue->i); return 0; }
This union can hold either a character value c or an integer value i but only one value at a time.
- Details
- Category: C category list
- Hits: 91
File Input and Output
Creating and linking a stream to a disk file is called opening a file. When a file is opened, it is available to the OS for reading, writing or both.
Opening a File with fopen()
The fopen() library function is used to open a file:
FILE *fopen(const char *filename, const char *mode);
The fopen call will initialise a structure of type FILE, which contains all the information necessary to control the stream and return a pointer to that structure. This pointer is used in all subsequent operations on the file. If fopen() fails, it returns NULL.
The parameter filename contains the name and address of the file to be opened. The filename argument can be a literal string enclosed in double quotation marks or a pointer to a string variable. The parameter mode specifies the mode in which to open the file. The file may be binary or text and maybe opened for reading, writing, or both. Values of mode for the fopen() function are listed below.
Sr.No. | Mode & Description |
---|---|
r | Opens an existing text file for reading. |
w | Opens a text file for writing. If it does not exist, then a new file is created. Here your program will start writing content from the beginning of the file. |
a | Opens a text file for writing in appending mode. If it does not exist, then a new file is created. Here your program will start appending content in the existing file content. |
r+ | Opens a text file for both reading and writing. |
w+ | Opens a text file for both reading and writing. It first truncates the file to zero length if it exists, otherwise creates a file if it does not exist. |
a+ | Opens a text file for both reading and writing. It creates the file if it does not exist. The reading will start from the beginning but writing can only be appended. |
A failure to open a file will see fopen return NULL. Errors may be caused by factors such as an invalid filename or a nonexistent location
Closing a File
To close a file, use the fclose( ) function. The prototype of this function is −
int fclose( FILE *fp );
The fclose() function returns zero on success, or EOF if there is an error in closing the file. When a file is closed, the file’s buffer is flushed (written to the disk) and the memory is released.
Writing to a File.
Data can be written to a disk file in three ways:
- Using formatted data files.
- Using character output to save single characters or lines of characters to a file.
- Using direct output.
Unformatted Output with fputc
Writes a character to the stream and moves the position indicator forward. The prototype of fputc is −
int fputc( int c, FILE *fp ); int fputs( const char *s, FILE *fp );
The function fputc() writes the character value c or the string s to the output stream referenced by fp.
If successful it returns the written character written or EOF if there is an error. The character is written at the position indicated by the internal position indicator of the stream, which is then automatically advanced by one.
Formatted Output using fprintf
Formatted file output is done with the library function fprintf() . The prototype of fprintf() is-
int fprintf ( FILE * stream, const char * format, ... );
The first parameter is a pointer to type FILE. To write data to a storage location, use the pointer returned with the fopen() call. The second argument is the format string. The format string used by fprintf() follows the same format as printf(). In the function prototype, ellipses represent a variable number of additional arguments.
Direct Output with fwrite
The fwrite() function is used to write records (a sequence of bytes) to the output stream. These records may be such things as arrays and structures. The syntax of fwrite() function is as follows
fwrite( ptr, int size, int n, FILE *fp );
The fwrite() function accepts four arguments.
ptr points to the block of memory which contains the data items to be written.
size specifies the number of bytes of each item to be written.
n is the number of items to be written.
FILE* is a pointer to the file where data items will be written in binary mode.
When the code below is compiled and executed, it creates a new file test.txt in the //home directory on a linux system and writes two lines.
#include <stdio.h> main() { FILE *fp; fp = fopen("//home/m/test.txt", "w+"); fprintf(fp, "create output file...\n"); fputs("Use fputs file...\n", fp); fclose(fp); }
Reading from a file
Unformatted Input with fgetc
The fgetc() function reads a character from the input file referenced by fp. It returns the character read or EOF on reaching the end of the file. The prototype of fgetc() is-
int fgetc( FILE * fp );
The function fgets() reads up to n-1 characters from the input stream referenced by fp. The following string reads an input string into the buffer ibuf, appending a null character to terminate the string.
char *fgets( char *ibuf, int n, FILE *fp );
Formatted File Input with fscanf
The fscanf() function reads formatted input from a file. The prototype of fscanf() is-
int fscanf(FILE *fp, const char *fmt, ...);
The parameter fp is a pointer to type FILE returned by fopen(). The parameter fmt is a pointer to the format string that specifies how fscanf() is to read the input. Finally, the ellipses ( ... ) indicate one or more additional arguments.
Direct Input with the fread()
The fread() function is used to read binary data and is complementary to fwrite(). The function prototype is as follows
fread( ptr, int size, int n, FILE *fp );
The fread() function accepts four arguments.
ptr is the address of the memory block where data is stored after reading.
size specifies the number of bytes of each item to be read.
n is the number of items read from the file where each item occupies the number of bytes specified in the second argument.
FILE* is the file from where the data is read in binary mode.
On success, it reads n items from the file and returns n. On error or end of the file, it returns a number less than n.
The position indicator of the stream is advanced by the total amount of bytes read.
The total amount of bytes read if successful is (size*count).
#include <stdio.h> int main () { char str1[20]; FILE * fp; fp = fopen ("file.txt", "w+"); fputs("output_file", fp); rewind(fp); fscanf(fp, "%s", str1); printf("%s\n", str1 ); fclose(fp); return(0); }
Sequential Versus Random File Access
Every file IO operation has a position indicator indicating where data is read from and written to. The position is always given in terms of bytes from the beginning of the file. When the data in a file is read or written sequentially the file indicator position is taken care of automatically.
Manual control over the file position indicator is known as random file access. This means that the programmer can read data from or write data to any position in a file without reading or writing all the preceding data.
ftell() and rewind()
To move the position indicator to the beginning of a file, use the function rewind(). The prototype is
void rewind(FILE *fp);
The parameter fp is the FILE pointer associated with the stream. After calling rewind() the file’s position indicator is set to the beginning of the file (byte 0).
To determine the value of a file’s position indicator, use function ftell(). The prototype is
long ftell(FILE *fp);
The argument fp is the FILE pointer returned by fopen(). ftell() returns a type long that gives the current file position in bytes from the
start of the file (the first byte is at position 0). If an error occurs, ftell() returns -1L
fseek()
fseek() sets the position of file indicator to anywhere in the file. The function prototype is
int fseek(FILE *fp, long offset, int origin);
The argument fp is the FILE pointer associated with the file. The distance to move the position indicator is given by offset in bytes, the argument origin specifies the move’s relative starting point.
There can be three values for origin. The symbolic constants are defined in io.h
SEEK_SET 0 - Moves the indicator offset bytes from the beginning of the file.
SEEK_CUR 1 - Moves the indicator offset bytes from its current position.
SEEK_END 2 - Moves the indicator offset bytes from the end of the file.
#include <stdlib.h> #include <stdio.h> #define BUFLEN 6 char readdate[] = "abcdefghijklmnopqrstuvwxyz"; int main( void ) { FILE *fp; char buf[2]; if ( (fp = fopen("random.TXT", "w")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } if (fputs(readdate, fp) == EOF) { fprintf(stderr, "Error writing to file."); exit(1); } fclose(fp); if ( (fp = fopen("random.TXT", "r")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } printf("\nAfter opening the file the file pointer is at position = %ld", ftell(fp)); fgets(buf,2, fp);//read first character printf("\nThe character at position zero is %s",buf); printf("\nNow the file pointer is at position = %ld", ftell(fp)); fseek(fp, 10, 0);//move to pointer to position 10 printf("\nMove position marker to position 10"); fgets(buf,2, fp); printf("\nThe character at position 5 is %s",buf); printf("\nMove position marker to start of file"); rewind(fp);//move file pointer to start of file printf("\nNow the file pointer is at the start of the file = %ld", ftell(fp)); fgets(buf,2, fp); printf("\nThe current character is = %s", buf); fclose(fp); return 0; }
Detecting the End of a File
There are two ways to detect end-of-file.
Detecting EOF character - When a character input function reads the EOF this indicates the end of the file
Checking FEOF character - The function feof() returns 0 if the end of file fp hasn’t been reached, or a nonzero value if end-of-file has been reached.
File Management Functions
Deleting a File
To delete a file use the function remove(). The prototype is
int remove( const char *filename );
The variable *filename is a pointer to the file name to be deleted. If the file exists, it is deleted and the remove function returns 0. If the user does not have sufficient access rights, does not exist or is already open then the delete operation will fail returning -1.
Renaming a File
The rename() function changes the name of an existing disk file. The prototype is
int rename( const char *oldname, const char *newname );
The function returns 0 on success, or -1 if an error occurs. For the function to work the old filename must exist and the new filename must not exist. Both files must be on the same disk.
Temporary Files Names
A temporary file is a file that is created and used by the program during program execution and then deleted before the program terminates. The function tmpnam() returns a string containing a unique file name suitable to safely use without risking overwriting any existing files. The prototype is as follows:
char *tmpnam(char *f);
The parameter f must be a pointer to a buffer large enough to hold the filename. A null pointer ( NULL ), means the temporary name is stored in the tmpnam() buffer. The function returns a pointer to that buffer.
#include <stdio.h> int main( void ) { char temp[20], *t; tmpnam(temp);/* create temporary name and store in temp buffer. */ t = tmpnam(NULL);/* create another name, this time in the function’s internal buffer */ /* Display the names. */ printf("Temporary name 1: %s", temp); printf("\nTemporary name 2: %s\n", t); return 0; }
- Details
- Category: C category list
- Hits: 104
Advanced pointers
Pointers to pointers (multiple indirection)
A normal pointer contains the address of a variable. When defining a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location of the variable. A pointer to a pointer is declared by placing an additional asterisk in front of its name. For example, the following declaration declares a pointer to a pointer of type int
int **v;
Accessing the value pointed to in the above integer value is by applying the asterisk operator twice. In the code sample below both the pointer and pointer to that pointer reference the same integer value.
#include <stdio.h> int main(void) { // declare and populate 2d array int value[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int *ptr = &value[0][0]; // set pointer ptr to array value int total_cells = 12, i; // output elements of the array value by using pointer ptr for (i = 0; i < total_cells; i++) { printf("%d ", *(ptr + i)); } return 0; }
Pointers and Multidimensional Arrays
To create a pointer to a multidimensional assign the address of the first element of the array and use the address of the operator as below
int *ptr = &num[0][0];
The multidimensional array num will be saved as a contiguous block in memory. To move between each element the value of ptr will need to be incremented by one
In the following code we are printing the content of the num array using for loop and by incrementing the value of ptr.
#include <stdio.h> int main(void) { // declare and populate 2d array int value[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int *ptr = &value[0][0]; // set pointer ptr to array value int total_cells = 12, i; // output elements of the array value by using pointer ptr for (i = 0; i < total_cells; i++) { printf("%d ", *(ptr + i)); } return 0; }
Array of pointers
An array of pointers is an array that holds memory locations. The following statement declares an array of 5 pointers to type char -
char *str[5];
Each element of the str array acts as an individual pointer to type char. These declarations can be combined initialization statements as below
char *str[5] = { “one”, “two”, “three”,"four","five" };
This code declares an array of 5 pointers to type char and initializes them to point to 5 strings. It then uses a for loop to display each element.
# include <stdio.h> int main( void ) { char *str[5] = { "one", "two", "three", "four","five"}; int count; for (count = 0; count < 5; count++) printf("%s ", str[count]); printf("\n"); return 0; }
Pointers to Functions
A pointer to a function points to the address of the executable code of the function. As with all C variables, it is necessary to declare a pointer to a function before using it. The general form of the declaration is as follows:
type (*function_ptr)(parameter_list);
coded examples of how to declare some functions pointer are listed below
int (*function)(int x);
char (*function)(char *p[]);
void (*functions)();
Parentheses are used around the pointer name because the asterisk operator * has relatively low operator precedence. Without the parenthesis, the function declaration will not be evaluated in the correct order.
Function pointers are useful for implementing callback mechanisms and passing the address of a function to another function. They are also useful for storing an array of functions dynamically.
The following short program demonstrates how to declare and call a function pointer
#include <stdio.h> void function(char arrayvalue[30]);/*function declaration*/ void (*ptrfunc)(char arrayvalue[30]);/* The pointer declaration. */ int main( void ) { ptrfunc = function;/* Initialize ptrfuch to address of function. */ char arrayvalue[30]="outside array"; printf(" %s\n", arrayvalue); ptrfunc(arrayvalue);//call function use *ptrfunc printf(" %s\n", arrayvalue); return 0; } void function(char arrayvalue[30]) { strcpy(arrayvalue, "function return");/*change value of arrayvalue*/ }
- Details
- Category: C category list
- Hits: 100