Consider the function definition:
def mapp(fun,first,*second): (A function that is defined to implement the properties of the 'map' function
Here the function 'mapp' consists of three arguments passed to it. Out of this ,the third argument (second) is the arbitrary argument list. The argument is itself optional and can be passed with different lists or tuples ranging from zero to any number of lists.
The length of the arbitrary listed argument would be zero if no arguments are passed to it.(len(second)=0).
The call to the above function would be as follows:
mapp(sqr,a)
OR
mapp(add,a,b,c)
OR
mapp(mul,a,b)
where a,b,c are any lists.
and 'sqr','add','mul' are functions.
Suppose the call to the function be
mapp(mul,a,b,c)
The lists b,c are passed as arguments to the function 'mapp' via the formal parameter 'second' (arbitrary listed argument).
Now second[0]=b
second[1]=c.
Monday, 30 August 2010
C vs Python : A Comparison
Coming from C ,a programming language where you might come across lot of un-expectencies while coding, python might be termed as 'lot easier' to deal with for a beginner especially. For those who have programmed in C,python provides you with the great advantage of 'not' having to get into the system specifications such as 'memory and bit' manipulations. Ask those C programmers who would always say that the biggest challenge they have come across in C as a beginner is while they have dealt with pointers as if they are being taunted . Luckily ,specially for the starters ,python doesn't require you to get into the memory allocation details and other stuff. All you need to do is to write your efficient code and wait for the result and most of the time the output you get wont give you a shock.
You could create a long list of points that might attract you to do a bit of coding in Python although C obviously has its own standouts. Some of them may be noted.
Python follows the Object oriented Programming paradigm whereas C follows Imperative programming paradigm.
Python has got a really large library as compared to C and a huge number of really powerful and useful built in functions.
Python code ,at first sight looks a lot more tidy than C because of its compulsory indentation requirement. You might know that this is not a necessity in C.
Python codes can be slower than corresponding C codes. Because python performs an 'out-of-range' checking for each iteration while looping ,the code becomes a lot more slower. This check has its own advantage though. Programmers in C would no that trying to access a location outside the allocation of an array would cause disastrous results.Python also performs the process of garbage collection which again decreases the execution speed.
The use of 'for loop' in Python is entirely different from that in C. The variable used is auto incremented and its important not to try and modify the loop variable of the 'for' loop.
There are no type declarations in python as is necessary in C.
Python does not support in-line assignment as in C. Therefore there is no chance of accidently assigning the value to a variable that you thought you were comparing.i.e 'if a=5' would just produce an error in Python whereas in C this would make the value of a equal to 5.
One of the major differences between python and C is that you wont get to play with pointers in python. Memory manipulation by the programmer is not required in Python as in C. Almost all the such activities done in C with the use of pointers can be done with sequences and associative arrays in python.
The variables used in python would result in an error without making an appropriate assignment. This proves really beneficial because unassigned variables can trouble you leading even up to segmentation faults in C.
Implementation of the 'stack' data structure becomes a lot more easier in python than in C. The implementation of 'queue' also becomes relatively easier. The python built-ins ;insert','append' etc helps in the purpose.
Another important feature of python is the use of sequences 'lists' , 'tuples',strings' and the use of Associative arrays. and their different manipulations. This helps programmers to do almost anything that can imagine of with the data stored.
Most importantly, python code is a lot more short than its corresponding C code. Programs that may take up to a few lines in a normal C code would give you the result in about 1-2 lines of coding in Python.
You could create a long list of points that might attract you to do a bit of coding in Python although C obviously has its own standouts. Some of them may be noted.
Python follows the Object oriented Programming paradigm whereas C follows Imperative programming paradigm.
Python has got a really large library as compared to C and a huge number of really powerful and useful built in functions.
Python code ,at first sight looks a lot more tidy than C because of its compulsory indentation requirement. You might know that this is not a necessity in C.
Python codes can be slower than corresponding C codes. Because python performs an 'out-of-range' checking for each iteration while looping ,the code becomes a lot more slower. This check has its own advantage though. Programmers in C would no that trying to access a location outside the allocation of an array would cause disastrous results.Python also performs the process of garbage collection which again decreases the execution speed.
The use of 'for loop' in Python is entirely different from that in C. The variable used is auto incremented and its important not to try and modify the loop variable of the 'for' loop.
There are no type declarations in python as is necessary in C.
Python does not support in-line assignment as in C. Therefore there is no chance of accidently assigning the value to a variable that you thought you were comparing.i.e 'if a=5' would just produce an error in Python whereas in C this would make the value of a equal to 5.
One of the major differences between python and C is that you wont get to play with pointers in python. Memory manipulation by the programmer is not required in Python as in C. Almost all the such activities done in C with the use of pointers can be done with sequences and associative arrays in python.
The variables used in python would result in an error without making an appropriate assignment. This proves really beneficial because unassigned variables can trouble you leading even up to segmentation faults in C.
Implementation of the 'stack' data structure becomes a lot more easier in python than in C. The implementation of 'queue' also becomes relatively easier. The python built-ins ;insert','append' etc helps in the purpose.
Another important feature of python is the use of sequences 'lists' , 'tuples',strings' and the use of Associative arrays. and their different manipulations. This helps programmers to do almost anything that can imagine of with the data stored.
Most importantly, python code is a lot more short than its corresponding C code. Programs that may take up to a few lines in a normal C code would give you the result in about 1-2 lines of coding in Python.
Thursday, 26 August 2010
An introduction to python
Here is a small introduction to the python programming language provided by considering some of its most important features.
a=[1,2,3]
The above statement assigns 'a' to a list which is [1,2,3]
b=(1,2,3)
The statement assigns 'b' to a tuple which is (1,2,3)
Lists and tuples are one of the most important features of python. They both are collection of values separated by 'commas'(,). The difference between lists and tuples is that tuples are immutable(cannot be modified) whereas the value stored in a list can be changed and modified.
Lets see that with an example:
a[0]=10
'a' now becomes [10,2,3].
The above operation( I.e modification )cannot be performed with tuples).
b[0]=10 would produce an error message.
Lists can be manipulated in a number of interesting ways and the working of lists is also quite interesting.
.a=[1,2,3].
.b=a would now make 'b' [1,2,3]
Now any changes made to b, suppose
b[1]=20
would also result in 'a[1]' being changed to '20'. This is a really important concept that has to be understood in python.
When b=a is done ,the statement makes 'b' point to the same address where 'a' points. Hence the changes applied to list 'b' are reflected in 'a' as well.
If the above case is to be avoided, there are basically two ways:
1)Pass the list 'a' as a tuple to 'b' so that it cannot be modified.
A list can be converted into a tuple using the 'tuple' command: 'tuple(list)'
2)Pass a clone of 'a' to 'b'. This can be done as b=a[:]. Here only a clone of 'a' is passed to 'b' thereby any changes made to 'b' doesn't affect 'a'.
Manipulation of lists may be as:
a=[1,2,3,4,5]
a[1:3]
would give as [2,3]
a[1:]
would give [2,3,4,5]
a[:1]
the result would be [1]
There are a number of commands that can be applied on lists:They include the following:
'append'
a.append([10,2]) would give you 'a' as [1,2,3,4,5[10,2]]
'extend'
a.extend([8,9]) would give us 'a' as [1,2,3,4,5,[10,2],8,9]
'pop'
a.pop(4) would delete and return the element at the 4rth position.
'insert'
a.insert(2,10) would insert '10' at the 2nd position of the list..
a=[1,2,3]
The above statement assigns 'a' to a list which is [1,2,3]
b=(1,2,3)
The statement assigns 'b' to a tuple which is (1,2,3)
Lists and tuples are one of the most important features of python. They both are collection of values separated by 'commas'(,). The difference between lists and tuples is that tuples are immutable(cannot be modified) whereas the value stored in a list can be changed and modified.
Lets see that with an example:
a[0]=10
'a' now becomes [10,2,3].
The above operation( I.e modification )cannot be performed with tuples).
b[0]=10 would produce an error message.
Lists can be manipulated in a number of interesting ways and the working of lists is also quite interesting.
.a=[1,2,3].
.b=a would now make 'b' [1,2,3]
Now any changes made to b, suppose
b[1]=20
would also result in 'a[1]' being changed to '20'. This is a really important concept that has to be understood in python.
When b=a is done ,the statement makes 'b' point to the same address where 'a' points. Hence the changes applied to list 'b' are reflected in 'a' as well.
If the above case is to be avoided, there are basically two ways:
1)Pass the list 'a' as a tuple to 'b' so that it cannot be modified.
A list can be converted into a tuple using the 'tuple' command: 'tuple(list)'
2)Pass a clone of 'a' to 'b'. This can be done as b=a[:]. Here only a clone of 'a' is passed to 'b' thereby any changes made to 'b' doesn't affect 'a'.
Manipulation of lists may be as:
a=[1,2,3,4,5]
a[1:3]
would give as [2,3]
a[1:]
would give [2,3,4,5]
a[:1]
the result would be [1]
There are a number of commands that can be applied on lists:They include the following:
'append'
a.append([10,2]) would give you 'a' as [1,2,3,4,5[10,2]]
'extend'
a.extend([8,9]) would give us 'a' as [1,2,3,4,5,[10,2],8,9]
'pop'
a.pop(4) would delete and return the element at the 4rth position.
'insert'
a.insert(2,10) would insert '10' at the 2nd position of the list..
Tuesday, 17 August 2010
Increment and Decrement operators
Consider the statements:
int c=5;
printf("\n%d\n",c++);
printf("\n%d\n",++c)
The result as we except would be :
5
7
Again consider the statement
printf("\n%d %d:\n",c++,++c);
Here the result wouldn't be as we thought and as is correct in the earlier example. When I executed this I obtained the result as:
6 7:
This is an undefined behaviour:Therefore its an important thing to keep in mind while using the increment/decrement operators:Its important 'not to' increment/decrement the same object more than once in a statement.
If an object appears more than once in an expression ,then modifying the object in the expression without the previous value of the object taking part in the modification process will lead to undefined behaviour. Thats whats done in the example just above. The value of c is modified in the expression for the second time(there fore 'c' appearing twice) without the previous value participating in the process. So if at all an object has to be modified in an expression where it appears more than once ,then it should be something like as follows:
c=c+1;
Here c appears twice , c is modified but the previous value of 'c' takes part in the process..
int c=5;
printf("\n%d\n",c++);
printf("\n%d\n",++c)
The result as we except would be :
5
7
Again consider the statement
printf("\n%d %d:\n",c++,++c);
Here the result wouldn't be as we thought and as is correct in the earlier example. When I executed this I obtained the result as:
6 7:
This is an undefined behaviour:Therefore its an important thing to keep in mind while using the increment/decrement operators:Its important 'not to' increment/decrement the same object more than once in a statement.
If an object appears more than once in an expression ,then modifying the object in the expression without the previous value of the object taking part in the modification process will lead to undefined behaviour. Thats whats done in the example just above. The value of c is modified in the expression for the second time(there fore 'c' appearing twice) without the previous value participating in the process. So if at all an object has to be modified in an expression where it appears more than once ,then it should be something like as follows:
c=c+1;
Here c appears twice , c is modified but the previous value of 'c' takes part in the process..
Pointers ,Arrays and Pointer to pointers.
Consider the following statement:
char *lineptr[]={"hello","hai","how"};
Here 'lineptr' is an array that consists of pointers to characters.
1) Now this array is passed on to another function with a call as follows:
str(lineptr);
The function 'str' would have a declaration as follows:
void str(char *lineptr[]);
2) The same thing can be done in a different way as follows:
str((char **) lineptr);
The definition of 'str' can be the same as the above or it could well be:
void str(char **lineptr);(the declaration of the function could have been the same when the call was
str(lineptr); as well.
This is an example of a pointer to a pointer.
Here in our function call :str((char **)lineptr); we pass a pointer to a pointer (that points to characters).
And that we have as (char**)lineptr.
This shows the thick relation between arrays and pointers in C. Any operation that can be done array subscripting can also be done with pointers.
.char s[]=”hello”;
could be done using pointers as
.char *s=”hello”.
The parenthesis and the type specification (char) that we have is extremely important.
Without the parenthesis and the type,it would be as follows:
**lineptr : dereferencing the dereferenced value of lineptr ,i.e,&lineptr[0] which would result in 'h' as the answer.
In both cases
for(i=0;i<3;i++)
printf(“%s”,*lineptr++);
would print out the contents of the array 'lineptr' (.i.e (hellohaihow)).
.lineptr++ increments lineptr by a value of 4 since it points to pointers.
Now consider another case ,
The function call being
str((char**)lineptr) or str(lineptr)
The declaration being
void str(char *ptr);
Through the function call, we pass a pointer to pointer(that points to characters).But the declaration consists of a pointer that points to characters. Therefore the variable 'ptr' in the function 'str' would take up the base address of the array 'lineptr' as its value. Now since this a pointer that points to characters , ptr++ would increment 'ptr' by a value of only 1.And since this points to some unknown characters, undefined results would be produced.
char *lineptr[]={"hello","hai","how"};
Here 'lineptr' is an array that consists of pointers to characters.
1) Now this array is passed on to another function with a call as follows:
str(lineptr);
The function 'str' would have a declaration as follows:
void str(char *lineptr[]);
2) The same thing can be done in a different way as follows:
str((char **) lineptr);
The definition of 'str' can be the same as the above or it could well be:
void str(char **lineptr);(the declaration of the function could have been the same when the call was
str(lineptr); as well.
This is an example of a pointer to a pointer.
Here in our function call :str((char **)lineptr); we pass a pointer to a pointer (that points to characters).
And that we have as (char**)lineptr.
This shows the thick relation between arrays and pointers in C. Any operation that can be done array subscripting can also be done with pointers.
.char s[]=”hello”;
could be done using pointers as
.char *s=”hello”.
The parenthesis and the type specification (char) that we have is extremely important.
Without the parenthesis and the type,it would be as follows:
**lineptr : dereferencing the dereferenced value of lineptr ,i.e,&lineptr[0] which would result in 'h' as the answer.
In both cases
for(i=0;i<3;i++)
printf(“%s”,*lineptr++);
would print out the contents of the array 'lineptr' (.i.e (hellohaihow)).
.lineptr++ increments lineptr by a value of 4 since it points to pointers.
Now consider another case ,
The function call being
str((char**)lineptr) or str(lineptr)
The declaration being
void str(char *ptr);
Through the function call, we pass a pointer to pointer(that points to characters).But the declaration consists of a pointer that points to characters. Therefore the variable 'ptr' in the function 'str' would take up the base address of the array 'lineptr' as its value. Now since this a pointer that points to characters , ptr++ would increment 'ptr' by a value of only 1.And since this points to some unknown characters, undefined results would be produced.
Saturday, 14 August 2010
Pointers and Arrays in C.
Pointers as we know are used to store addresses. There is a strong relation between pointers and arrays in C.
Consider the following:
int *p;
int a[100];
p=NULL;
p=a;
Here p is initialized to the starting address of the array a[].This is equivalent to doing
p=&a[0];
the statement p=a clearly shows the relation between pointers and arrays in C. Pointers and arrays can be used instead of each other in C although there are some differences that needs to be considered. We will find out the basics in comparing an array and a pointer.
Below a[] is an array and p is a pointer that has been initialized to the base address of the array.
a[i] is equivalent to doing *(p+i)
&a[i] is equivalent to (p+i)-address of the i-th location of the array.
p=a as we saw just above is valid, whereas a=p is illegal.
Pointers are considered as normal variables and can be the increment operators, p++, whereas a++ is illegal.
Now consider the case of characters. Again let the variables have the same meaning,'a[]' for an array and 'p' for a pointer.
Consider
char a[size]=”hello”; This can be written using pointers as
char *p=”hello”;
Here p is initialized to the starting address of the string “hello”(to the character 'h').
Now obviously the difference comes here while printing.
printf(“%s”,a) would result in printing of the string whereas printf(“%s”,*p) would result in a segfault (obviously not due to uninitialized dereferencing) but because of the fact that the pointer points to the starting of the string(a character).
Hence it should be printed using
printf(“%c”,*p) -would print the character .
This will be have to be looped if the entire string is to printed.
Consider the following:
int *p;
int a[100];
p=NULL;
p=a;
Here p is initialized to the starting address of the array a[].This is equivalent to doing
p=&a[0];
the statement p=a clearly shows the relation between pointers and arrays in C. Pointers and arrays can be used instead of each other in C although there are some differences that needs to be considered. We will find out the basics in comparing an array and a pointer.
Below a[] is an array and p is a pointer that has been initialized to the base address of the array.
a[i] is equivalent to doing *(p+i)
&a[i] is equivalent to (p+i)-address of the i-th location of the array.
p=a as we saw just above is valid, whereas a=p is illegal.
Pointers are considered as normal variables and can be the increment operators, p++, whereas a++ is illegal.
Now consider the case of characters. Again let the variables have the same meaning,'a[]' for an array and 'p' for a pointer.
Consider
char a[size]=”hello”; This can be written using pointers as
char *p=”hello”;
Here p is initialized to the starting address of the string “hello”(to the character 'h').
Now obviously the difference comes here while printing.
printf(“%s”,a) would result in printing of the string whereas printf(“%s”,*p) would result in a segfault (obviously not due to uninitialized dereferencing) but because of the fact that the pointer points to the starting of the string(a character).
Hence it should be printed using
printf(“%c”,*p) -would print the character .
This will be have to be looped if the entire string is to printed.
Use of pointer arrays.
What will we do if we need to store more than one string in an array.?
Double dimensional would be an option. For eg.
char array[][10]={"hello","hai","how"}; But here the the length of each string is be limited up to 10..Specifying the 'column' is a must in case of 2dimensional arrays. Even during the definition of a function.
Another option and perhaps a better one would be the use of pointers arrays .for e.g
char *p[]={"hello","how","hai"};
This is an example of pointer arrays. Each element of the array is used to keep pointers that point to some characters. This method would be better in sense that the strings can be of variable lengths and obviously working with it can be a lot easier.
It will be interesting to find out the working of pointer arrays.
Consider a pointer 'p1' such that :
char *p1=”hello”
Now this particular pointer can be entered into the pointer array like the following:
p[0]=p1; The pointer to string “hello” is entered into the 0th position of the pointer array.
Similarly the pointer array can be filled with pointers to characters.
Now in order to print a particular string whose pointer is stored in the 0th location of the pointer array we need to do.
'printf(“%s”,p[0]); or printf(“”%s”,*(p+0));. Both of them would give the result as hello'.
printf(“%d”,p[0]); would give the pointer that is stored in the 0-th location of the array.
for(i=0;i<3;i++)
printf(“%d\n”,p+i); would show you the addresses of the array locations.
Pointer arrays would be very useful when playing with strings. Suppose if you want to sort different words according to their length. All you need to do if you have stored the pointers to those words in a pointer array is to exchange the positions of the pointers.
That is , if the string whose pointer at position '0' is greater than that of the string at position '1', then
temp=a[0];
a[0]=a[1];
a[1]=temp;
Thats it..the pointers have exchanged their positions..Now on printing, the string whose pointer is stored at location '0' of the array 'a[]' will be printed first.
Double dimensional would be an option. For eg.
char array[][10]={"hello","hai","how"}; But here the the length of each string is be limited up to 10..Specifying the 'column' is a must in case of 2dimensional arrays. Even during the definition of a function.
Another option and perhaps a better one would be the use of pointers arrays .for e.g
char *p[]={"hello","how","hai"};
This is an example of pointer arrays. Each element of the array is used to keep pointers that point to some characters. This method would be better in sense that the strings can be of variable lengths and obviously working with it can be a lot easier.
It will be interesting to find out the working of pointer arrays.
Consider a pointer 'p1' such that :
char *p1=”hello”
Now this particular pointer can be entered into the pointer array like the following:
p[0]=p1; The pointer to string “hello” is entered into the 0th position of the pointer array.
Similarly the pointer array can be filled with pointers to characters.
Now in order to print a particular string whose pointer is stored in the 0th location of the pointer array we need to do.
'printf(“%s”,p[0]); or printf(“”%s”,*(p+0));. Both of them would give the result as hello'.
printf(“%d”,p[0]); would give the pointer that is stored in the 0-th location of the array.
for(i=0;i<3;i++)
printf(“%d\n”,p+i); would show you the addresses of the array locations.
Pointer arrays would be very useful when playing with strings. Suppose if you want to sort different words according to their length. All you need to do if you have stored the pointers to those words in a pointer array is to exchange the positions of the pointers.
That is , if the string whose pointer at position '0' is greater than that of the string at position '1', then
temp=a[0];
a[0]=a[1];
a[1]=temp;
Thats it..the pointers have exchanged their positions..Now on printing, the string whose pointer is stored at location '0' of the array 'a[]' will be printed first.
Multidimensional arrays and pointers.
Consider a two dimensional array
int a[][15]={{0,2,4,6,8,}
{1,3,5,7,9,}};
This shows a 2dimensional array with 2 rows and 5 columns.. The value '4' could be accessed by
a[0][2].
In C, a 2D array can be dealt with the same way as a 1d array. The elements are stored by rows and hence the columns change fastest when it comes to sequential access. There are some important points though that we need to care about while using 2D arrays.
Its not necessary to mention the row size, but its important to mention the column size always, during declarations and definitions. If the array 'a' is used to be used in functions the declaration could be as follows:
int funct( int array[2][5]);
int funct( int array[][5]);
or it could even be the following:
int funct(int (*array)[5]); ---passes a pointer to the array with 5 integers.
The parenthesis is important because without it , it would be appear as int *array[5] which means that its an array of 5 pointers .
Now when pointers are used instead of normal array indexing, it would appear as follows:
int *p=array[1];
which has now set the pointer to the starting of the the 2nd row of the array. The following elements in the 2nd row(columns) could now be accessed as normally done in an array. I.e ,*p.
int a[][15]={{0,2,4,6,8,}
{1,3,5,7,9,}};
This shows a 2dimensional array with 2 rows and 5 columns.. The value '4' could be accessed by
a[0][2].
In C, a 2D array can be dealt with the same way as a 1d array. The elements are stored by rows and hence the columns change fastest when it comes to sequential access. There are some important points though that we need to care about while using 2D arrays.
Its not necessary to mention the row size, but its important to mention the column size always, during declarations and definitions. If the array 'a' is used to be used in functions the declaration could be as follows:
int funct( int array[2][5]);
int funct( int array[][5]);
or it could even be the following:
int funct(int (*array)[5]); ---passes a pointer to the array with 5 integers.
The parenthesis is important because without it , it would be appear as int *array[5] which means that its an array of 5 pointers .
Now when pointers are used instead of normal array indexing, it would appear as follows:
int *p=array[1];
which has now set the pointer to the starting of the the 2nd row of the array. The following elements in the 2nd row(columns) could now be accessed as normally done in an array. I.e ,*p.
Wednesday, 11 August 2010
Aliasing to avoid making mistakes
It might have happened to that you that you unintentionally deleted some files in your directory. The deleted files may be not recovered back. So its better that you take some precautionary measures to avoid making such mistakes. Setting up proper aliases is one such way to so so. Aliases are short names for certain commands.
In order to set up your alias ,create a .bashrc file in your own home directory.
$ vi .bashrc
Set up your own aliases there.
Aliases for not making mistakes while using the cp,mv and rm commands are follows.
14 alias rm='rm -i'
15 alias cp='cp -i'
16 alias mv='mv -i'
These three statements ensure that whenever you the commands cp,mv or rm ,the system asks you to double check your decision just to make sure that is exactly what you wanted to do. This could help you against overwriting a file,or deleting a file unintentionally.
In order to set up your alias ,create a .bashrc file in your own home directory.
$ vi .bashrc
Set up your own aliases there.
Aliases for not making mistakes while using the cp,mv and rm commands are follows.
14 alias rm='rm -i'
15 alias cp='cp -i'
16 alias mv='mv -i'
These three statements ensure that whenever you the commands cp,mv or rm ,the system asks you to double check your decision just to make sure that is exactly what you wanted to do. This could help you against overwriting a file,or deleting a file unintentionally.
Creating new commands and passing arguments in UNIX...
When a particular sequence of commands is repeated time after ,it might be better if we create a shorter command of our own. These command creation mentioned may not be suitable for public use but would be helpful for private use.
Consider suppose that we intend to count the number of users quite frequently:
$ who|wc -l
We can make a small command of ours named 'count' that does the same work.
So we do
$echo 'who|wc -l'>count (A file named 'count' is created).
Now we run the shell program with its input coming from the file 'count'.
$ sh<count
this is same as
$ sh count
Now to type sh all the time wouldn't be such a great thing. So we make the file 'count' executable by
$ chmod +x count
Now the result of doing 'who|wc -l' can be produced by doing 'count'.
$ count
Install count ,place it in the /usr/bin directory. Set the path appropriately and start using the command
created.
Now again when we begin to create executable commands of our own, we will have to make it executable . So it would be better if we create a shorter command for chmod +x filename.
The problem here would be that the filename that is passed to 'chmod' may change every time.
Therefore we do
$ echo 'chmod +x $1'>cx (cx would be the file created).
Here $1-indicates that only 1 argument can be passed to the command at a time
$2 would make it 2 and $9 would make it 9.
So to enable any number of arguments we do
$ echo 'chmod +x $*'>cx
Now we need to make cx executable.
This can be done either by doing
$ chmod +x cx or else
$ sh cx cx because sh cx is equivalent to doing chmod +x $*.
Now test it by creating a test command 'test' ,install it and run the command. 'Permission denied' will be the message. Now do
$ cx test
$ test
The command 'test' will run and the result will be produced.
Now suppose we have a file 'class' consisting of some information about the students of our class and consider a case where we need information about certain students and we need it quite frequently. This can be done with the help of the 'grep' command.
$ echo 'grep $* /root/new/class'> find
install the command.
$ cx find /* makes the file executable
$ find
Now a possible would arise when the following case is given as the argument:
$ find sunil kumar
This is because the words sunil and kumar will be seen as two different arguments.
Hence do
$ echo 'grep “$*” /root/new/class'> find
This would solve the problem.
Consider suppose that we intend to count the number of users quite frequently:
$ who|wc -l
We can make a small command of ours named 'count' that does the same work.
So we do
$echo 'who|wc -l'>count (A file named 'count' is created).
Now we run the shell program with its input coming from the file 'count'.
$ sh<count
this is same as
$ sh count
Now to type sh all the time wouldn't be such a great thing. So we make the file 'count' executable by
$ chmod +x count
Now the result of doing 'who|wc -l' can be produced by doing 'count'.
$ count
Install count ,place it in the /usr/bin directory. Set the path appropriately and start using the command
created.
Now again when we begin to create executable commands of our own, we will have to make it executable . So it would be better if we create a shorter command for chmod +x filename.
The problem here would be that the filename that is passed to 'chmod' may change every time.
Therefore we do
$ echo 'chmod +x $1'>cx (cx would be the file created).
Here $1-indicates that only 1 argument can be passed to the command at a time
$2 would make it 2 and $9 would make it 9.
So to enable any number of arguments we do
$ echo 'chmod +x $*'>cx
Now we need to make cx executable.
This can be done either by doing
$ chmod +x cx or else
$ sh cx cx because sh cx is equivalent to doing chmod +x $*.
Now test it by creating a test command 'test' ,install it and run the command. 'Permission denied' will be the message. Now do
$ cx test
$ test
The command 'test' will run and the result will be produced.
Now suppose we have a file 'class' consisting of some information about the students of our class and consider a case where we need information about certain students and we need it quite frequently. This can be done with the help of the 'grep' command.
$ echo 'grep $* /root/new/class'> find
install the command.
$ cx find /* makes the file executable
$ find
Now a possible would arise when the following case is given as the argument:
$ find sunil kumar
This is because the words sunil and kumar will be seen as two different arguments.
Hence do
$ echo 'grep “$*” /root/new/class'> find
This would solve the problem.
Setting up the vim configuration.
While writing C programs using the 'vi' editor ,you might find a frustrating task of handling with line numbers ,setting up the indentation properly and of course you might never mind if some indications are given about the keywords using colors. There fore we set up the vim configuration and automate the above said tasks by doing the following.
Create a file .exrc in your home directory..
vi .exrc ....filename ending with rc indicates that you can configure them the way you want it to be.
Now type the following:
set nu /*to set up line numbers properly*/
set cindent /*to set up the indentation(for the better clarity of the program)*/
syntax on /*this sets the coloring 'on' for the program according to the C syntax */
Now save the file and start writing your programs more comfortably.
Create a file .exrc in your home directory..
vi .exrc ....filename ending with rc indicates that you can configure them the way you want it to be.
Now type the following:
set nu /*to set up line numbers properly*/
set cindent /*to set up the indentation(for the better clarity of the program)*/
syntax on /*this sets the coloring 'on' for the program according to the C syntax */
Now save the file and start writing your programs more comfortably.
Tuesday, 10 August 2010
Segmentation faults with pointers in C...
Segmentation fault occurs when an attempt is made to access unallocated memory.
Segmentation faults with pointers might prove to be a task to deal with .This is mainly because of the fact that the actual area of the fault has to be identified and then the fault cleared. This might sometimes leave you in a pondering state. If the reasons that cause the segmentation faults are known , then it might help us to get rid of it quite quickly...
The major reasons for the segmentation fault to occur while using pointers might be the following..
Dereferencing NULL
and dereferencing an uninitialized pointer.
Both these cases would result in segmentation fault.
Whenever a segmentation fault occurs-the best way to deal with it is to find out the point of occurrence at first and then find out exactly why it happened..
The best way to spot a segmentation fault is to install gdb on your system.
This would enable you to find out the point of occurrence of the fault and the fault can be cleared.
The best practice while using pointers is always to initialize the pointer to NULL at first. Therefore when using the gdb you can see the null value( as 0x0 in systems)
/* consider a section of the debugging process*/
51 *dayofmonth=yearday;
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0804862f in year_day (year=12, yearday=15, dayofmonth=0x0, month=0x0) at pmonthday.c:51
51 *dayofmonth=yearday;
*/
Here my pointers are 'dayofmonth' and 'month'..Hence from the debugging process its clear that the pointers have been set to NULL which indicates that we have not initialized the pointer to a legal memory address.
Again there are other methods identify the problem. Print all the values of pointers used in the program and see if any value differs from the others by a far long distance. If yes,this address space might be illegal. But theres no guarantee that this would be a solution.
Of course it may happen that sometimes you might get lucky with uninitialized pointers and there might be no segmentation fault, but its better not to make a habit of that because you might a segfault anytime. Hence its always better to initialize the pointer to NULL at first and then to a legal address.
A segmentation fault could be cleared by just setting the pointer to some legal address.
For an eg..
'p' is the uninitialized pointer that has caused the fault, just set it to the base address of an array as
char array[1000];
char *p=array;
Segmentation faults with pointers might prove to be a task to deal with .This is mainly because of the fact that the actual area of the fault has to be identified and then the fault cleared. This might sometimes leave you in a pondering state. If the reasons that cause the segmentation faults are known , then it might help us to get rid of it quite quickly...
The major reasons for the segmentation fault to occur while using pointers might be the following..
Dereferencing NULL
and dereferencing an uninitialized pointer.
Both these cases would result in segmentation fault.
Whenever a segmentation fault occurs-the best way to deal with it is to find out the point of occurrence at first and then find out exactly why it happened..
The best way to spot a segmentation fault is to install gdb on your system.
This would enable you to find out the point of occurrence of the fault and the fault can be cleared.
The best practice while using pointers is always to initialize the pointer to NULL at first. Therefore when using the gdb you can see the null value( as 0x0 in systems)
/* consider a section of the debugging process*/
51 *dayofmonth=yearday;
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0804862f in year_day (year=12, yearday=15, dayofmonth=0x0, month=0x0) at pmonthday.c:51
51 *dayofmonth=yearday;
*/
Here my pointers are 'dayofmonth' and 'month'..Hence from the debugging process its clear that the pointers have been set to NULL which indicates that we have not initialized the pointer to a legal memory address.
Again there are other methods identify the problem. Print all the values of pointers used in the program and see if any value differs from the others by a far long distance. If yes,this address space might be illegal. But theres no guarantee that this would be a solution.
Of course it may happen that sometimes you might get lucky with uninitialized pointers and there might be no segmentation fault, but its better not to make a habit of that because you might a segfault anytime. Hence its always better to initialize the pointer to NULL at first and then to a legal address.
A segmentation fault could be cleared by just setting the pointer to some legal address.
For an eg..
'p' is the uninitialized pointer that has caused the fault, just set it to the base address of an array as
char array[1000];
char *p=array;
Static variables and declarations...
The static declaration can be applied to both external and internal variables. The static declaration if applied to external variables limits the scope of that particular variable to the rest of the source file being compiled. Static declaration if applied to the internal variables ensures that the variables returns its previous value after the control has been transferred out and in of the particular function...i.e it provides permanent storage for the variable rather than temporary storage which is the case with normal internal variables.
Lets see how static works with internal variables...
Consider the program code...
char yes(void)
{
static int lastc=0;
lastc=lastc+1;
return lastc;
}
The variable lastc has been declared static:
Hence the value of lastc remains intact even after the function 'yes()' has terminted...lastc will get back its older value when the next call to the function 'yes()'arrives.
Therefore if the return values where to be printed...it would be as following:
1
2
3
...
...
This obviously wouldn't have been the case if the static declaration was not provided.
Now consider the case:
char yes(void)
{
static int lastc;
lastc=0;
lastc=lastc+1;
return lastc;
}
Here the initial value of the variable has been assigned after the static declaration is performed.
This would result in a normal execution. Obviously the variable would be static and has permanent storage but its that just the assignment operation after the static declaration takes its effect. Therefore its highly important to initialize the value of the variable declared 'static' along with declaration.
Lets see how static works with internal variables...
Consider the program code...
char yes(void)
{
static int lastc=0;
lastc=lastc+1;
return lastc;
}
The variable lastc has been declared static:
Hence the value of lastc remains intact even after the function 'yes()' has terminted...lastc will get back its older value when the next call to the function 'yes()'arrives.
Therefore if the return values where to be printed...it would be as following:
1
2
3
...
...
This obviously wouldn't have been the case if the static declaration was not provided.
Now consider the case:
char yes(void)
{
static int lastc;
lastc=0;
lastc=lastc+1;
return lastc;
}
Here the initial value of the variable has been assigned after the static declaration is performed.
This would result in a normal execution. Obviously the variable would be static and has permanent storage but its that just the assignment operation after the static declaration takes its effect. Therefore its highly important to initialize the value of the variable declared 'static' along with declaration.
Sunday, 8 August 2010
Debugging with the GDB
GNU debugger(GDB) allows you to view the step by step execution of the program code. This proves of great help in executing complex programs(specially the ones involving recursion) to see the exact flow of control. How to debug using the gdb and a few options used are worth notable:
To debug a program with gdb , steps followed are
'cc -g file.c'
gdb a.out. ....'a.out is your executable...'
You will see messages about the gdb version displayed on the terminal....
Now set the break point by
'break main'
Use the 'run' command to start running the program.
The 3 commonly used options are 's' ,'n' ,'q' with the gdb are…
's' moves to the next line of code-it enters functions as well.
'n' moves to the next line of code as well but does not enter functions.
'q' is used to quit from the process.
A debugging process would be like this...
sunil:~/new# cc -g quicksort.c
sunil:~/new# gdb a.out
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) break main
Breakpoint 1 at 0x80483e5: file quicksort.c, line 7.
(gdb) run
Starting program: /root/new/a.out
Breakpoint 1, main () at quicksort.c:7
7 int left=0,right=4,i;
(gdb) s
8 int array[]={4,8,1,9,3};
.../*
...continue the process...
.../*
(gdb) q
Quits from the debugger
To debug a program with gdb , steps followed are
'cc -g file.c'
gdb a.out. ....'a.out is your executable...'
You will see messages about the gdb version displayed on the terminal....
Now set the break point by
'break main'
Use the 'run' command to start running the program.
The 3 commonly used options are 's' ,'n' ,'q' with the gdb are…
's' moves to the next line of code-it enters functions as well.
'n' moves to the next line of code as well but does not enter functions.
'q' is used to quit from the process.
A debugging process would be like this...
sunil:~/new# cc -g quicksort.c
sunil:~/new# gdb a.out
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) break main
Breakpoint 1 at 0x80483e5: file quicksort.c, line 7.
(gdb) run
Starting program: /root/new/a.out
Breakpoint 1, main () at quicksort.c:7
7 int left=0,right=4,i;
(gdb) s
8 int array[]={4,8,1,9,3};
.../*
...continue the process...
.../*
(gdb) q
Quits from the debugger
Recursion in C..
Recursion may be used in C programs, where one function may be called within itself. The method of recursion will be simpler to understand with a small program code. The code is as follows.
#include
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}
The program is used to convert an integer decimal into its character digits.i.e 123 will be converted into 1
2
3
....the digits of the integer.
Lets see how the code works.
Consider the initial value of n as 123.
printd(123) //level 1
123/10 is true:Hence
printd(123/10);
printd(12) //level 2
12/10 is true:Hence
printd(12/10);
printd(1) //level 3
1/10 is not true;
hence putchar(1%10+'0'); //1 is printed
}
Now the call to the completed function printd(1) came from the function printd(12/10)(level 2) and the control returns to the end of the function printd(12/10) (n being 12)
The next statement is
hence putchar(12%10+'0'); // 2 is printed
Again the call to the completed function .i.e (printd(12)) is not from the main, but its from the function printd(123/10)(level 3) and hence the control is returned to the end of the function(n being 123).
The next statement is
hence putchar(123%10+'0'); // 3 is printed
Now the call to completed function(printd(123)) came from the main() and the control is returned there and the program proceeds.
Hope this gives a basic idea of the working of recursive functions. The function used in quick sort algorithm for sorting would be a good way to understand the working of recursion in a better way.
#include
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}
The program is used to convert an integer decimal into its character digits.i.e 123 will be converted into 1
2
3
....the digits of the integer.
Lets see how the code works.
Consider the initial value of n as 123.
printd(123) //level 1
123/10 is true:Hence
printd(123/10);
printd(12) //level 2
12/10 is true:Hence
printd(12/10);
printd(1) //level 3
1/10 is not true;
hence putchar(1%10+'0'); //1 is printed
}
Now the call to the completed function printd(1) came from the function printd(12/10)(level 2) and the control returns to the end of the function printd(12/10) (n being 12)
The next statement is
hence putchar(12%10+'0'); // 2 is printed
Again the call to the completed function .i.e (printd(12)) is not from the main, but its from the function printd(123/10)(level 3) and hence the control is returned to the end of the function(n being 123).
The next statement is
hence putchar(123%10+'0'); // 3 is printed
Now the call to completed function(printd(123)) came from the main() and the control is returned there and the program proceeds.
Hope this gives a basic idea of the working of recursive functions. The function used in quick sort algorithm for sorting would be a good way to understand the working of recursion in a better way.
Saturday, 7 August 2010
A bit about bitwise operators....
Before we get a view of the bitwise operators , its important to have an idea of sizes of different types that are used in C.
Since most of the values that are entered by us can be accommodated by the ‘type float’ we consider the int , short and char types.
The data type char occupies a space of minimum of 8 bits(1 byte).The maximum value that can be placed in an unsigned char without the problem of truncation is 255. In case of unsigned char, this value moves to 127.The minimum value in signed char is -128.
The type int stores a maximum value of 65,635 for unsigned type and a maximum of 32767 for the signed type(these are the minimum values offered by any system, the actual limits may change on different systems). The minimum for the signed type would be -32768.The minimum number of bits required for storage would be 16. These values are the same for the type ‘short’.
These were some of the basics that were needed to get an idea about the bitwise operators. Obviously playing with the bits is a bit more difficult task than the higher level.
The bitwise operators are
&-bitwise AND
|-bitwise OR
<>-right shift
^-exclusive or
~-bitwise complement.
<<-left shift operators would be the best way to get an idea about the bitwise operators.
Consider doing the following
255<<2….the result would be 1020….255<<3 would give you 2040…255<<4….would give you 4080….and so….
Lets see how this works….doing 255<<2 is equivalent to doing 255*2^2(here the ^ symbol stands for the ‘raise to’ operator….Similarly 255<<3 is equivalent to doing 255*2^3….
A smaller number would help in understanding this.
Left shift operator shifts each bit of the character 2 places to the left. In the case 1<<2…would give 4 as the answer…
1(00000001)<<2=00000100(4)….This is how you obtain 4 as the answer.
Now the importance of the knowing the bit size of different types comes in here…
Suppose that the character 255 has been stored using variable of the type ‘char’…Now it is obvious that after shifting it to left, the result cannot be held by the type ‘char’ because the maximum value that can be stored in ‘type char’ is 255..Therefore it will have to be stored in the type whose size is greater then that of ‘char’.
.unsigned char s=255;
.s=s<<2; wouldn't be correct.
We use the type 'int' to store the result...
.unsigned char s=255;
.int i=s<<2; is the right way to do it..
Similarly its also important to consider the limits of the signed and unsigned values when using the shift operators.
The attempt to shift more bits than is allotted would produce in a message as ‘>=width of the type’.
The other bitwise operators work on the bits as follows….
>>p --- shifts the bits p positions to the right…equivalent to dividing with 2^p.
'&' ---result is 1 when any of the bits are 1…
^,|,~ all work in their own way….
Since most of the values that are entered by us can be accommodated by the ‘type float’ we consider the int , short and char types.
The data type char occupies a space of minimum of 8 bits(1 byte).The maximum value that can be placed in an unsigned char without the problem of truncation is 255. In case of unsigned char, this value moves to 127.The minimum value in signed char is -128.
The type int stores a maximum value of 65,635 for unsigned type and a maximum of 32767 for the signed type(these are the minimum values offered by any system, the actual limits may change on different systems). The minimum for the signed type would be -32768.The minimum number of bits required for storage would be 16. These values are the same for the type ‘short’.
These were some of the basics that were needed to get an idea about the bitwise operators. Obviously playing with the bits is a bit more difficult task than the higher level.
The bitwise operators are
&-bitwise AND
|-bitwise OR
<>-right shift
^-exclusive or
~-bitwise complement.
<<-left shift operators would be the best way to get an idea about the bitwise operators.
Consider doing the following
255<<2….the result would be 1020….255<<3 would give you 2040…255<<4….would give you 4080….and so….
Lets see how this works….doing 255<<2 is equivalent to doing 255*2^2(here the ^ symbol stands for the ‘raise to’ operator….Similarly 255<<3 is equivalent to doing 255*2^3….
A smaller number would help in understanding this.
Left shift operator shifts each bit of the character 2 places to the left. In the case 1<<2…would give 4 as the answer…
1(00000001)<<2=00000100(4)….This is how you obtain 4 as the answer.
Now the importance of the knowing the bit size of different types comes in here…
Suppose that the character 255 has been stored using variable of the type ‘char’…Now it is obvious that after shifting it to left, the result cannot be held by the type ‘char’ because the maximum value that can be stored in ‘type char’ is 255..Therefore it will have to be stored in the type whose size is greater then that of ‘char’.
.unsigned char s=255;
.s=s<<2; wouldn't be correct.
We use the type 'int' to store the result...
.unsigned char s=255;
.int i=s<<2; is the right way to do it..
Similarly its also important to consider the limits of the signed and unsigned values when using the shift operators.
The attempt to shift more bits than is allotted would produce in a message as ‘>=width of the type’.
The other bitwise operators work on the bits as follows….
>>p --- shifts the bits p positions to the right…equivalent to dividing with 2^p.
'&' ---result is 1 when any of the bits are 1…
^,|,~ all work in their own way….
The 'lm' option.
It may sometimes happen that when you use commands like sin,cos,pow etc....you get a warning message like 'undefined reference' .This may happen even when you have included the header file .This happens because your program has not been linked with the system library properly...
A solution to the situation would be to use the option 'lm' when you compile the file.This would fix the problem and the call would be referred to the function definitions in the system's library.
The syntax would be as follows....
'gcc -lm filename.c'
A solution to the situation would be to use the option 'lm' when you compile the file.This would fix the problem and the call would be referred to the function definitions in the system's library.
The syntax would be as follows....
'gcc -lm filename.c'
Tuesday, 3 August 2010
Files in the Unix file system and their permissions...
A file is a sequence of characters. A few commands and knowledge that may help in dealing with files and directories in UNIX are the following.
The 'ls' commands and its variations :
The 'du' command and its variations
The command used to change the permissions – 'chmod'.
A look into these commands
ls command gives a listing of all the files that are present in the current directory.
The 'ls -l' is used to provide a detailed listing of the files that are present.
For eg. If you type the command 'ls -l' the results be will produced as
-rw-r--r-- 1 root root 856 2010-08-03 20:15 delete.c
-rw-r--r-- 1 root root 868 2010-08-03 08:19 line.c
where line.c and delete.c are the two files present in the directory.
The other variations of the command include ls-u,ls-t etc
The 'du' (disk usage)provides information about the usage of the disk.
The command 'du -a' is used to provide disk informations about even the files of subdirectories.
The 'du-a|grep line.c'
provides the details about the file 'line.c'.
'chmod' is the command that is used to change permissions. The permissions can be changed by the superuser.
Consider the following permissions:
-rwxrwxrwx - indicates that the owner,the group and the other users of the system can all read(r),write(w)and execute(x) the file of which the permission has be shown.
Inorder to change the permission , the 'chmod' command is used.
For eg. 'chmod 666 file'
indicates that the file can be read and written by all the three categories of users mentioned above.
The octal values have their meanings as
4-indicates that the file can be read
2-file can be written
1-file can be executed
therefore 'chmod 444 file' would set the permissions of the file to read only for all the categories of users.
6 6 6 indicates(4+2 4+2 4+2) for the three users.)
Now do 'ls -l' and you will see the permissions as
-r--r--r--.
'+' is used to turn a permission on and '-' to turn it off.
The command 'chmod +w file' enables write permissions for the file
and 'chmod -x file' turns off the execute permissions for the file.
The permissions of the file can be viewed using the 'ls -l' command stated before. The permissions of the directory cab also be set and viewed using the 'ls -ld' command.
The 'ln','cp','mv' commands are used in UNIX for slightly different uses.
The 'ln command creates a link to the file. Therefore the same file can be accessed using the two file names. The syntax is as follows:
'ln filename filename1'
You would obtain another link to the file named 'filename' by the name of 'filename1':
The change made to original file would reflect in the other as well. You could see that with help of the 'ls -i' (command that indicates the 'i-number' of the file)that the two files that are linked are having the same i-number.
'cp' command is used to make the copy and the 'mv' command is used to move or rename files.
The command 'mv filename1 filenname2...... destination directory' is used to move several files together to the destination directory.
The 'ls' commands and its variations :
The 'du' command and its variations
The command used to change the permissions – 'chmod'.
A look into these commands
ls command gives a listing of all the files that are present in the current directory.
The 'ls -l' is used to provide a detailed listing of the files that are present.
For eg. If you type the command 'ls -l' the results be will produced as
-rw-r--r-- 1 root root 856 2010-08-03 20:15 delete.c
-rw-r--r-- 1 root root 868 2010-08-03 08:19 line.c
where line.c and delete.c are the two files present in the directory.
The other variations of the command include ls-u,ls-t etc
The 'du' (disk usage)provides information about the usage of the disk.
The command 'du -a' is used to provide disk informations about even the files of subdirectories.
The 'du-a|grep line.c'
provides the details about the file 'line.c'.
'chmod' is the command that is used to change permissions. The permissions can be changed by the superuser.
Consider the following permissions:
-rwxrwxrwx - indicates that the owner,the group and the other users of the system can all read(r),write(w)and execute(x) the file of which the permission has be shown.
Inorder to change the permission , the 'chmod' command is used.
For eg. 'chmod 666 file'
indicates that the file can be read and written by all the three categories of users mentioned above.
The octal values have their meanings as
4-indicates that the file can be read
2-file can be written
1-file can be executed
therefore 'chmod 444 file' would set the permissions of the file to read only for all the categories of users.
6 6 6 indicates(4+2 4+2 4+2) for the three users.)
Now do 'ls -l' and you will see the permissions as
-r--r--r--.
'+' is used to turn a permission on and '-' to turn it off.
The command 'chmod +w file' enables write permissions for the file
and 'chmod -x file' turns off the execute permissions for the file.
The permissions of the file can be viewed using the 'ls -l' command stated before. The permissions of the directory cab also be set and viewed using the 'ls -ld' command.
The 'ln','cp','mv' commands are used in UNIX for slightly different uses.
The 'ln command creates a link to the file. Therefore the same file can be accessed using the two file names. The syntax is as follows:
'ln filename filename1'
You would obtain another link to the file named 'filename' by the name of 'filename1':
The change made to original file would reflect in the other as well. You could see that with help of the 'ls -i' (command that indicates the 'i-number' of the file)that the two files that are linked are having the same i-number.
'cp' command is used to make the copy and the 'mv' command is used to move or rename files.
The command 'mv filename1 filenname2...... destination directory' is used to move several files together to the destination directory.
Characters , Integers and arrays.
Consider the statement
char c='5'
printf(“%d”,c);
The result that will be printed is 53, which is the integer value of the character constant '5' ,stored in the machine.
Now if we need to get 5 as the output,we need to use “%c” in 'printf'.
Character constants are integers written as one character within single quotes.
Now consider :
int c=getchar();
printf(“%d”,c);
The result would be the integer value representation of the entered character.
“%c” in 'printf' would print the character in the terminal.
Now consider the case of a character array
char array[]={5,6,7}.
If we print array[0],using “%d”, then '5' would be printed. Nothing would be printed if “%c” is used in the printf statement.
Here 5 itself is a constant. Now if we need to enter alphabets into a character and print it we need to do the following:
char array[]={'a','b','c'};
Now print it using “%c”.The alphabets would be printed.
If printed using “%d”, then the integer representations would be printed(97,98,99).The characters that entered into a character array are stored as integers inside the array.
If we do
char array[]={a,b,c}
The result would be an error as such:
'a' undeclared....'c' undeclared...etc..
char c='5'
printf(“%d”,c);
The result that will be printed is 53, which is the integer value of the character constant '5' ,stored in the machine.
Now if we need to get 5 as the output,we need to use “%c” in 'printf'.
Character constants are integers written as one character within single quotes.
Now consider :
int c=getchar();
printf(“%d”,c);
The result would be the integer value representation of the entered character.
“%c” in 'printf' would print the character in the terminal.
Now consider the case of a character array
char array[]={5,6,7}.
If we print array[0],using “%d”, then '5' would be printed. Nothing would be printed if “%c” is used in the printf statement.
Here 5 itself is a constant. Now if we need to enter alphabets into a character and print it we need to do the following:
char array[]={'a','b','c'};
Now print it using “%c”.The alphabets would be printed.
If printed using “%d”, then the integer representations would be printed(97,98,99).The characters that entered into a character array are stored as integers inside the array.
If we do
char array[]={a,b,c}
The result would be an error as such:
'a' undeclared....'c' undeclared...etc..
Ensuring the correct data types while using Functions
Some of the most common errors that are produced in a program are caused due to the lack of interest ensuring that the data types used are correct. Some of these errors will be displayed while some will not and its up to the user to search the program and find out whats wrong with it. Therefore the user must be very careful while using the type of the functions, the variables that are used etc...An example below shows the use of the data type of the functions and variables...
Consider a program which is used perform the functions of a calculator: The functions that are used in the program are the follows:
push(),pop(),getop(),atof(),main()(These are just the function names)
Now each of these functions have got a specific task.
The 'getop' function is used to get the character that is entered by the user. The value that will be returned by the function would be of an integer type:
hence 'Int getop( char []);' (A string is passed as the parameter)
'push' is used to enter a value into the stack. The value would be of type 'double'. Hence the argument that is passed to the function 'push' would be of type 'double'. Nothing is returned by 'push'.
Hence 'void push(double);'
'pop' returns a double value and nothing is passed to the 'pop' as an argument because it just takes up the value from the array(array[] ,declared externally).
Hence 'double pop(void)'
'atof' takes the string as the argument and returns a double value:
hence 'double atof(char[]);'
The data type of 'array[]' should again be double because it handles 'double' values.
Now the program looks like this:
#include
#define MAX 50
int getop(char s[]);
double atof(char s[]);
void push(double);
double pop(void);
double arr[MAX];
int top=0;
main()
Now if the data types of any of the above declarations are not according to the problem you wouldn't get the expected results.
For example if the data type of array[] is not double(say integer) , you would get the result as some meaningless value. Same is the case with all of the above functions and variables declared.
For the purpose of add,subtract,multiply and divide the use of 'double' values is good(infact a necessity if you want the exact output).
But when the '%'(modulus) operator is used ,then the problem arises. If the modulus operator is used with two double values the resulting error would be as follows:
error: invalid operands to binary % (have ‘double’ and ‘double’) :
Hence the values needs to be converted to type 'int'.
Int op=pop();
push((int)pop()%op);
The type is converted from double into int. Now since pop returns a double value, this will again be converted back to a double value.
A note on External variables: Here array[] and top are declared as external variables and so can be accessed by the functions that are mentioned. Hence these values need not be passed as an argument to the functions. The fact that is to be taken into account that is that when external variables are used , the variable names cannot be changed within a function as is the case while passing arguments.
Consider a program which is used perform the functions of a calculator: The functions that are used in the program are the follows:
push(),pop(),getop(),atof(),main()(These are just the function names)
Now each of these functions have got a specific task.
The 'getop' function is used to get the character that is entered by the user. The value that will be returned by the function would be of an integer type:
hence 'Int getop( char []);' (A string is passed as the parameter)
'push' is used to enter a value into the stack. The value would be of type 'double'. Hence the argument that is passed to the function 'push' would be of type 'double'. Nothing is returned by 'push'.
Hence 'void push(double);'
'pop' returns a double value and nothing is passed to the 'pop' as an argument because it just takes up the value from the array(array[] ,declared externally).
Hence 'double pop(void)'
'atof' takes the string as the argument and returns a double value:
hence 'double atof(char[]);'
The data type of 'array[]' should again be double because it handles 'double' values.
Now the program looks like this:
#include
#define MAX 50
int getop(char s[]);
double atof(char s[]);
void push(double);
double pop(void);
double arr[MAX];
int top=0;
main()
Now if the data types of any of the above declarations are not according to the problem you wouldn't get the expected results.
For example if the data type of array[] is not double(say integer) , you would get the result as some meaningless value. Same is the case with all of the above functions and variables declared.
For the purpose of add,subtract,multiply and divide the use of 'double' values is good(infact a necessity if you want the exact output).
But when the '%'(modulus) operator is used ,then the problem arises. If the modulus operator is used with two double values the resulting error would be as follows:
error: invalid operands to binary % (have ‘double’ and ‘double’) :
Hence the values needs to be converted to type 'int'.
Int op=pop();
push((int)pop()%op);
The type is converted from double into int. Now since pop returns a double value, this will again be converted back to a double value.
A note on External variables: Here array[] and top are declared as external variables and so can be accessed by the functions that are mentioned. Hence these values need not be passed as an argument to the functions. The fact that is to be taken into account that is that when external variables are used , the variable names cannot be changed within a function as is the case while passing arguments.
Errors,warnings and unexpected results...
While compiling C programs we might often come across errors,messages and unexpected results as our output.. The following shows a few of those :
Sometimes u might get certain unexpected values like -1098763408 as your result.
This might be due to the fact that u may not have initialized the variable used in the expression producing the result to a starting value(say i=0).
The same doing (i.e a variable not set to its initial value) might produce a 'segmentation fault' in the program. Segmentation fault may also be produced due to the fact that the alloted size for the particular string array is less than what you have just tried to fill in.
For eg. If
#define MAX 10
char string[MAX];
The size is 10.Now if u try to fill in more than 10 characters a case of segmentation fault might occur.
Another case exists where you might get an error as the following one:
error: conflicting types for ‘some_function_name’
This might be because of the fact that the function name that you have used is the name of the function that is already present in one of the header files.
For common functions like 'strlen' ,'strcat' etc this might not occur because we wont use them as our function names. But this might occur sometimes for certain function names that we may not be familiar with.
For eg. The error message would be displayed when you use function names as
'index' or 'remove' etc...even if your declaration,definition and the call might be correct.
Don't keep pondering over it,you just need to change your function name to another one that does not exist in the system's headers. For eg..change 'the name index' to 'ind' or something else.
Another common case where you may not obtain the result might be because of an error in the 'printf' statement. For eg you may have used “%d” to print a float value even though “%f”should have been be used.
It is important to check that the type of 1)the called function and 2) the variable that is used in the calling function in order to receive the value returned from the called function has to be same .If this is not the case ,an error would be produced (that would happen only if both the functions are in the same source file. But if the functions are in different source files, then the case becomes more complicated because the error would not be displayed.
In case you find that the output you obtain has got some definite value but is meaningless according to the problem, then a solution might to have a look through all the data types used in the program and see if its appropriate and matching. Such cases might occur in programs involving many functions
Sometimes u might get certain unexpected values like -1098763408 as your result.
This might be due to the fact that u may not have initialized the variable used in the expression producing the result to a starting value(say i=0).
The same doing (i.e a variable not set to its initial value) might produce a 'segmentation fault' in the program. Segmentation fault may also be produced due to the fact that the alloted size for the particular string array is less than what you have just tried to fill in.
For eg. If
#define MAX 10
char string[MAX];
The size is 10.Now if u try to fill in more than 10 characters a case of segmentation fault might occur.
Another case exists where you might get an error as the following one:
error: conflicting types for ‘some_function_name’
This might be because of the fact that the function name that you have used is the name of the function that is already present in one of the header files.
For common functions like 'strlen' ,'strcat' etc this might not occur because we wont use them as our function names. But this might occur sometimes for certain function names that we may not be familiar with.
For eg. The error message would be displayed when you use function names as
'index' or 'remove' etc...even if your declaration,definition and the call might be correct.
Don't keep pondering over it,you just need to change your function name to another one that does not exist in the system's headers. For eg..change 'the name index' to 'ind' or something else.
Another common case where you may not obtain the result might be because of an error in the 'printf' statement. For eg you may have used “%d” to print a float value even though “%f”should have been be used.
It is important to check that the type of 1)the called function and 2) the variable that is used in the calling function in order to receive the value returned from the called function has to be same .If this is not the case ,an error would be produced (that would happen only if both the functions are in the same source file. But if the functions are in different source files, then the case becomes more complicated because the error would not be displayed.
In case you find that the output you obtain has got some definite value but is meaningless according to the problem, then a solution might to have a look through all the data types used in the program and see if its appropriate and matching. Such cases might occur in programs involving many functions
Sunday, 1 August 2010
Local and External variables
Local variables are variables that come into existence only when the function is called and disappears thereafter whereas external variables are accessible to all functions of the program.
To illustrate the difference between these two kinds of variables ,consider a function ‘getline()’
At first we consider the case where local variables are used. The call and the function definition in this case would be as follows:
Function call:
getline(line,MAXLENGTH);
Function definition:
int getline(char s[],int lim)
{
}
Here there is a requirement to pass the arguments from the caller function to the called function through the parenthesis as the variables used are local to the function. The value of the variable 'line' is internal to the caller function.
Whereas when we consider the case of external variables ,the situation changes. Consider the case of declaring variables externally:
#include
#define MAXLINE 100
char line[MAXLINE]; /*external variable declaration/*
The variables line has been declared externally.
Hence the call and definition of the function ‘getline()’ could be modified as follows:
Function call:
getline()
Function definition:
int getline(void)
{
}
The modified values of the variables would be available to all the functions.
To illustrate the difference between these two kinds of variables ,consider a function ‘getline()’
At first we consider the case where local variables are used. The call and the function definition in this case would be as follows:
Function call:
getline(line,MAXLENGTH);
Function definition:
int getline(char s[],int lim)
{
}
Here there is a requirement to pass the arguments from the caller function to the called function through the parenthesis as the variables used are local to the function. The value of the variable 'line' is internal to the caller function.
Whereas when we consider the case of external variables ,the situation changes. Consider the case of declaring variables externally:
#include
#define MAXLINE 100
char line[MAXLINE]; /*external variable declaration/*
The variables line has been declared externally.
Hence the call and definition of the function ‘getline()’ could be modified as follows:
Function call:
getline()
Function definition:
int getline(void)
{
}
The modified values of the variables would be available to all the functions.
Functions in C
C provides a lot of built in functions. Apart from that users define their own functions knows as user-defines functions. The function has got three parts
The declaration,the call and the definition.
Consider a function 'getline' which is used to obtain each line from the input.
The three parts of the function would be as follows:
Declaration:returntype getline(parameters);
call:getline(arguments);
definition:returntype getline(parameters)
{
declarations;
statements;
}
The function definition may well contain a 'return' statement to transfer the control back to the caller function. In such cases the return type of the function must not be 'void'.
The declaration,the call and the definition.
Consider a function 'getline' which is used to obtain each line from the input.
The three parts of the function would be as follows:
Declaration:returntype getline(parameters);
call:getline(arguments);
definition:returntype getline(parameters)
{
declarations;
statements;
}
The function definition may well contain a 'return' statement to transfer the control back to the caller function. In such cases the return type of the function must not be 'void'.
Input,output and type conversion.
Certain basic features of the C programming language are written here.
A text stream is a sequence of characters.
The getchar() statement in C is used so to obtain the next character from a text stream that is inputted by the user.
c=getchar()
assigns the input character to c
The type of c is declared to be int(when EOF case is used).
putchar(c)
prints the character ,that has been inputted, on the terminal.
Now consider what happens when we enter a statement
putchar(c-'0')
where c=getchar() and the character inputted is 'r'.
The result is B.The reason for the result being obtained is the the automatic type conversion that is performed in C.
The type of '0' is char and is converted to int,which is the type of 'c'.Hence the integer value of '0' is subtracted from the integer value of 'r' (i.e 114-48=65)which is equal to the integer value of 'B'.Hence we obtain the result as B.
Similar type conversions can be seen in C in different examples.
If an operator has one float and one integer as its operands ,then the integer will be automatically converted to float.
We express the decimal number 16 as a floating point constant as 16.0.The same number would be represented as an integer as 16.
If we perform 16.0-16,the integer operand (i.e 16)would automatically be converted into floating point.
The generalization of this is that a narrower operand is converted into a wider operand.
For eg int->float,float->double,double->long double etc....
Now we again move onto the input/output portion.
Consider a limit for the input is up to the EOF(end of file)
read input upto end of file is reached.
We set the condition as
(c=getchar())!=EOF) .This implies that the characters are fetched onto 'c' until the End of file is reached. EOF is an integer defined in as -1.
The paranthesis in (c=getchar())!=EOF is quite important. Without the paranthesis c would obtain values '0' or '1' depending upon the character not being EOF .This is because the precedence of != is greater than that of the assignment operator(=).
A text stream is a sequence of characters.
The getchar() statement in C is used so to obtain the next character from a text stream that is inputted by the user.
c=getchar()
assigns the input character to c
The type of c is declared to be int(when EOF case is used).
putchar(c)
prints the character ,that has been inputted, on the terminal.
Now consider what happens when we enter a statement
putchar(c-'0')
where c=getchar() and the character inputted is 'r'.
The result is B.The reason for the result being obtained is the the automatic type conversion that is performed in C.
The type of '0' is char and is converted to int,which is the type of 'c'.Hence the integer value of '0' is subtracted from the integer value of 'r' (i.e 114-48=65)which is equal to the integer value of 'B'.Hence we obtain the result as B.
Similar type conversions can be seen in C in different examples.
If an operator has one float and one integer as its operands ,then the integer will be automatically converted to float.
We express the decimal number 16 as a floating point constant as 16.0.The same number would be represented as an integer as 16.
If we perform 16.0-16,the integer operand (i.e 16)would automatically be converted into floating point.
The generalization of this is that a narrower operand is converted into a wider operand.
For eg int->float,float->double,double->long double etc....
Now we again move onto the input/output portion.
Consider a limit for the input is up to the EOF(end of file)
read input upto end of file is reached.
We set the condition as
(c=getchar())!=EOF) .This implies that the characters are fetched onto 'c' until the End of file is reached. EOF is an integer defined in as -1.
The paranthesis in (c=getchar())!=EOF is quite important. Without the paranthesis c would obtain values '0' or '1' depending upon the character not being EOF .This is because the precedence of != is greater than that of the assignment operator(=).
TATA DOCOMO INTERNET
Inorder to set up an internet connection using TATA DOCOMO in debian using USB ,u need to do the following steps:
Install 'wvdial' ----U will need Debian 5.0 -1 & 2 DVDs to do so.
Install it using
apt-get install wvdial
Once u have finished installing wvdial create a file 'wvdial.conf' in the /etc directory.Edit the settings for your TATA DOCOMO connection in the file 'wvdial.conf' .
The settings for the connection would be as follows:
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Password = MYPASSWORD
Phone = MYISPPHONENUM
Modem Type = USB Modem
Stupid Mode = yes
Baud = 460800
Dial Command = ATDT
Modem = /dev/ttyACM0
ISDN = 0
Username = MYUSERNAME
Carrier Check = yes
Auto Reconnect = yes
[Dialer Docomo]
Stupid Mode = yes
Password = Docomo
Auto Reconnect = yes
Username = Docomo
Phone = *99***1#
Save the file after editing,dial using
wvdial docomo
Certain messages will displayed in the terminal and you will obtain your
primary DNS address :
secondary DNS address:
Now open 'resolv.conf' in the /etc directory and edit the file and place your DNS addresses in the file as
nameserver:primary DNS address
nameserver:secondary DNS address
Now save the file and do wvdial docomo and you will obtain your internet connection.
Install 'wvdial' ----U will need Debian 5.0 -1 & 2 DVDs to do so.
Install it using
apt-get install wvdial
Once u have finished installing wvdial create a file 'wvdial.conf' in the /etc directory.Edit the settings for your TATA DOCOMO connection in the file 'wvdial.conf' .
The settings for the connection would be as follows:
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Password = MYPASSWORD
Phone = MYISPPHONENUM
Modem Type = USB Modem
Stupid Mode = yes
Baud = 460800
Dial Command = ATDT
Modem = /dev/ttyACM0
ISDN = 0
Username = MYUSERNAME
Carrier Check = yes
Auto Reconnect = yes
[Dialer Docomo]
Stupid Mode = yes
Password = Docomo
Auto Reconnect = yes
Username = Docomo
Phone = *99***1#
Save the file after editing,dial using
wvdial docomo
Certain messages will displayed in the terminal and you will obtain your
primary DNS address :
secondary DNS address:
Now open 'resolv.conf' in the /etc directory and edit the file and place your DNS addresses in the file as
nameserver:primary DNS address
nameserver:secondary DNS address
Now save the file and do wvdial docomo and you will obtain your internet connection.
Subscribe to:
Posts (Atom)