In order to be useful a program must be
able to represent real life quantities or data e.g. a person’s name, age,
height, bank balance, etc. This data will be stored in memory locations called
variables that we will name ourselves. However so that the data may be
represented as aptly as possible the variables will have to be of different
types to suit their data. For example while an integer can represent the age of
a person reasonably well it won’t be able to represent the pounds and pence in
a bank balance or the name of an individual quite so well.
Basic Data Types
There are five basic data types char, int,
float, double, and void. All other data types in C are based on these. Note
that the size of an int depends on the standard size of an integer on a particular operating system.
char
|
1 byte ( 8 bits ) with range -128 to 127
|
int
|
16-bit OS : 2 bytes with range -32768 to
32767
32-bit OS : 4 bytes with range
-2,147,483,648 to 2,147,483,647
|
float
|
4 bytes with range 10-38 to 1038 with 7 digits of precision
|
double
|
8 bytes with range 10-308 to 10308 with 15 digits of precision
|
void
|
generic pointer, used to indicate no
function parameters etc.
|
Modifying Basic Types
Except for type void the meaning of the
above basic types may be altered when combined with the following keywords.
signed
unsigned
long
short
The signed and unsigned
modifiers may be applied to types char and int and will simply change the range
of possible values. For example an unsigned
char has a range of 0 to 255, all positive, as
opposed to a signed char which has a range of -128 to 127. An unsigned integer on a 16-bit system has
a range of 0 to 65535 as opposed to a signed
int which has a range of -32768 to 32767.
Note however
that the default for type int or char is signed so that the type signed char is always equivalent to type char and the type signed int is always equivalent to int.
The long modifier may be applied to type int and double only. A long
int will require 4 bytes of storage no matter what
operating system is in use and has a range of -2,147,483,648 to 2,147,483,647.
A long double will require 10
bytes of storage and will be able to maintain up to 19 digits of precision.
The short modifier may be applied only to type int and will give a 2 byte integer
independent of the operating system in use.
NB :
Note that the keyword int may be omitted without error so that the type unsigned is the same as type
unsigned int, the type long is equivalent to the type long int, and the type short is equivalent to the type short int.
Variables
A variable is a named piece of memory which
is used to hold a value which may be modified by the program. A variable thus
has three attributes that are of interest to us : its type, its value and its address.
The variable’s type informs us what type
and range of values it can represent and how much memory is used to store that
value. The variable’s address informs us where in memory the variable is
located (which will become increasingly important when we discuss pointers
later on).
All C variables must be declared as follows
:-
type variable-list ;
For Example :-
int i ;
char a, b, ch ;
Variables are declared in three general
areas in a C program.
When declared inside functions as follows
they are termed local variables and
are visible (or accessible) within the function ( or code block ) only.
void main()
{
int i, j ;
...
}
A local variable is created i.e. allocated
memory for storage upon entry into the code block in which it is declared and
is destroyed i.e. its memory is released on exit. This means that values cannot
be stored in these variables for use in any subsequent calls to the function .
When declared outside functions they are
termed global variables and are
visible throughout the file or have file scope. These variables are created at
program start-up and can be used for the lifetime of the program.
int
i ;
void
main()
{
...
}
When declared within the braces of a
function they are termed the formal parameters of the function as we will see
later on.
int func1( int a, char b ) ;
Variable Names
Names of variables and functions in C are
called identifiers and are case sensitive. The first character of an identifier
must be either a letter or an underscore while the remaining characters may be
letters, numbers, or underscores. Identifiers in C can be up to 31 characters
in length.
Initialising Variables
When variables are declared in a program it
just means that an appropriate amount of memory is allocated to them for their
exclusive use. This memory however is not
initialised to zero or to any other value automatically and so will contain
random values unless specifically initialised before use.
Syntax :- type var-name =
constant ;
For Example :-
char ch = 'a' ;
double d = 12.2323 ;
int i, j = 20 ; /* note in this case i is not initialised */
Storage Classes
There are four storage class modifiers used
in C which determine an identifier’s storage duration and scope.
auto
static
register
extern
An identifier’s storage duration is the
period during which that identifier exists in memory. Some identifiers exist
for a short time only, some are repeatedly created and destroyed and some exist
for the entire duration of the program. An identifier’s scope specifies what
sections of code it is accessible from.
The auto storage class is implicitly the
default storage class used and simply specifies a normal local variable which
is visible within its own code block only and which is created and destroyed
automatically upon entry and exit respectively from the code block.
The register
storage class also specifies a normal local variable but it also requests that
the compiler store a variable so that it may be accessed as quickly as
possible, possibly from a CPU register.
The static
storage class causes a local variable to become permanent within its own code
block i.e. it retains its memory space and hence its value between function
calls.
When applied to global variables the static
modifier causes them to be visible only within the physical source file that
contains them i.e. to have file scope. Whereas the extern modifier which is the
implicit default for global variables enables them to be accessed in more than
one source file.
For example in
the case where there are two C source code files to be compiled together to
give one executable and where one specific global variable needs to be used by
both the extern class allows the programmer to inform the compiler of the
existence of this global variable in both files.
Constants
Constants are fixed values that cannot be
altered by the program and can be numbers, characters or strings.
Some Examples :-
char : 'a', '$', '7'
int :
10, 100, -100
unsigned : 0, 255
float : 12.23456, -1.573765e10, 1.347654E-13
double : 1433.34534545454, 1.35456456456456E-200
long : 65536, 2222222
string : “Hello World\n”
NB :
Floating point constants default to type double.
For example the following code segment will cause the compiler to issue a
warning pertaining to floating point conversion in the case of f_val but
not in the case of d_val..
float f_val ;
double d_val ;
f_val = 123.345 ;
d_val = 123.345 ;
However the value may be coerced to type
float by the use of a modifier as follows :-
f = 123.345F ;
Integer constants may also be forced to be
a certain type as follows :-
100U --- unsigned
100L --- long
Integer constants may be represented as
either decimal which is the default, as hexadecimal when preceded by "0x", e.g. 0x2A, or as octal when
preceded by "O", e.g. O27.
Character constants are normally
represented between single quotes, e.g. 'a', 'b', etc. However they may also be
represented using their ASCII (or decimal) values e.g. 97 is the ASCII value
for the letter 'a', and so the following two statements are equivalent. (See
Appendix A for a listing of the first 128 ASCII codes.)
char ch = 97 ;
char
ch = 'a' ;
There are also a number of special
character constants sometimes called Escape
Sequences, which are preceded by the backslash character '\', and have
special meanings in C.
\n
|
newline
|
\t
|
tab
|
\b
|
backspace
|
\'
|
single quote
|
\"
|
double quote
|
\0
|
null character
|
\xdd
|
represent as hexadecimal constant
|
Console Input / Output
This section introduces some of the more
common input and output functions provided in the C standard library.
printf()
The printf() function is used for formatted
output and uses a control string which is made up of a series of format
specifiers to govern how it prints out the values of the variables or constants
required. The more common format specifiers are given below
%c character
|
%f floating point
|
%d signed integer
|
%lf double floating point
|
%i signed integer
|
%e exponential notation
|
%u unsigned integer
|
%s string
|
%ld signed long
|
%x unsigned hexadecimal
|
%lu unsigned long
|
%o unsigned octal
|
|
%% prints a % sign
|
For Example :-
int i ;
printf( "%d", i ) ;
The printf() function
takes a variable number of arguments. In the above example two arguments are
required, the format string and the variable
i. The value of i is substituted
for the format specifier %d which simply specifies how the value is to be
displayed, in this case as a signed integer.
Some further examples :-
int i =
10, j = 20 ;
char ch =
'a' ;
double f
= 23421.2345 ;
printf( "%d
+ %d", i, j ) ; /* values are
substituted from
the variable list in order as required */
printf(
"%c", ch ) ;
printf(
"%s", "Hello World\n" ) ;
printf(
"The value of f is : %lf", f ) ;/*Output as : 23421.2345 */
printf(
"f in exponential form : %e", f ) ; /*
Output as : 2.34212345e+4
Field Width Specifiers
Field width specifiers are used in the
control string to format the numbers or characters output appropriately .
Syntax :- %[total width printed][.decimal places
printed]format specifier
where square braces indicate optional
arguments.
For Example :-
int i =
15 ;
float f =
13.3576 ;
printf(
"%3d", i ) ; /* prints "_15
" where _ indicates a space
character */
printf(
"%6.2f", f ) ; /* prints "_13.36" which has a total width
of 6 and displays 2 decimal places
*/
printf(
“%*.*f”, 6,2,f ) ; /* prints "_13.36" as above. Here * is used
as replacement character for field widths
*/
There are also a number of flags that can
be used in conjunction with field width specifiers to modify the output format.
These are placed directly after the % sign. A - (minus sign) causes the output
to be left-justified within the specified field, a + (plus sign) displays a
plus sign preceding positive values and a minus preceding negative values, and
a 0 (zero) causes a field to be padded using zeros rather than space
characters.
scanf()
This
function is similar to the printf function except that it is used for formatted
input. The format specifiers have the same meaning as for printf()
and the space character or the newline character are normally used as
delimiters between different inputs.
For Example :-
int i, d
;
char c ;
float f ;
scanf(
"%d", &i ) ;
scanf(
"%d %c %f", &d, &c, &f ) ; /* e.g. type "10_x_1.234ret"
*/
scanf( "%d:%c",
&i, &c ) ; /* e.g.
type "10:xret" */
The & character is the address of operator in C, it returns the address in
memory of the variable it acts on. (Aside : This is because C functions are nominally
call--by--value. Thus in order to change the value of a calling parameter we
must tell the function exactly where the variable resides in memory and so
allow the function to alter it directly rather than to uselessly alter a copy
of it. )
Note that while the space and newline
characters are normally used as delimiters between input fields the actual
delimiters specified in the format string of the scanf statement must be
reproduced at the keyboard faithfully as in the case of the last sample call.
If this is not done the program can produce somewhat erratic results!
The scanf function has a return value which
represents the number of fields it was able to convert successfully.
For Example :-
num = scanf( “%c %d”, &ch,
&i );
This scanf call requires two fields, a
character and an integer, to be read in so the value placed in num
after the call should be 2 if this was successful. However if the input was “a
bc” then the first character field will be read correctly as ‘a’ but the
integer field will not be converted correctly as the function cannot reconcile
“bc” as an integer. Thus the function will return 1 indicating that one field
was successfully converted. Thus to be safe the return value of the scanf
function should be checked always and some appropriate action taken if the
value is incorrect.
getchar() and putchar()
These functions are used to input and
output single characters. The getchar()
function reads the ASCII value of a character input at the keyboard and
displays the character while putchar()
displays a character on the standard output device i.e. the screen.
For Example :-
char ch1, ch2 ;
ch1 = getchar() ;
ch2 = 'a' ;
putchar( ch2 ) ;
NB
: The input
functions described above, scanf()
and getchar() are termed buffered input functions. This means that whatever the user
types at the keyboard is first stored in a data buffer and is not actually read
into the program until either the buffer fills up and has to be flushed or
until the user flushes the buffer by hitting ret whereupon the
required data is read into the program. The important thing to remember with
buffered input is that no matter how much data is taken into the buffer when it
is flushed the program just reads as much data as it needs from the start of
the buffer allowing whatever else that may be in the buffer to be discarded.
For Example :-
char ch1, ch2;
printf( "Enter two characters : "
) ;
ch1 = getchar() ;
ch2 = getchar() ;
printf( "\n The characters are %c and
%c\n", ch1, ch2 ) ;
In the above code segment if the input is
"abcdefret" the first two characters are read into the
variables all the others being discarded, but control does not return to the
program until the ret is hit and the buffer flushed.
If the input was "aret" then a would be placed in
ch1 and ret
in ch2.
_flushall()
The _flushall function
writes the contents of all output buffers to the screen and clears the contents
of all input buffers. The next input operation (if there is one) then reads new
data from the input device into the buffers.
This function should be used always in
conjunction with the buffered input functions to clear out unwanted characters
from the buffer after each
input call.
getch() and getche()
These functions perform the same operation
as getchar() except that they are unbuffered input functions i.e. it is not
necessary to type ret to cause the values to be read
into the program they are read in immediately the key is pressed. getche()
echoes the character hit to the screen while getch() does not.
For example :-
char ch ;
ch = getch() ;
Operators
One of the most important features of C is
that it has a very rich set of built in operators including arithmetic,
relational, logical, and bitwise operators.
Assignment Operator
int x ;
x = 20 ;
Some common notation :- lvalue
-- left hand side of an
assignment operation
rvalue
-- right hand side of an assignment operation
Type Conversions :- the value of the right hand side of an assignment
is converted to the type of the lvalue. This may sometimes yield compiler
warnings if information is lost in the conversion.
For Example :-
int x ;
char ch ;
float f ;
ch = x ; /* ch is assigned lower 8 bits of x, the
remaining bits are discarded so we have a possible information loss */
x = f ; /* x is assigned non fractional part of
f only within int range, information loss possible */
f = x ; /* value of x is converted to floating
point */
Multiple assignments are possible to any
degree in C, the assignment operator has right to left associativity which
means that the rightmost expression is evaluated first.
For Example :-
x = y = z = 100 ;
In this case the expression z = 100 is
carried out first. This causes the value 100 to be placed in z with the value
of the whole expression being 100 also. This expression value is then taken and
assigned by the next assignment operator on the left i.e. x = y = ( z = 100 ) ;
Arithmetic Operators
+
- * /
--- same rules as mathematics
with * and / being evaluated before + and -.
%
-- modulus / remainder operator
For Example :-
int a =
5, b = 2, x ;
float c =
5.0, d = 2.0, f ;
x = a / b
; //
integer division, x = 2.
f = c /
d ; // floating point division, f = 2.5.
x = 5 % 2
; //
remainder operator, x = 1.
x = 7 + 3
* 6 / 2 - 1 ;// x=15,* and / evaluated ahead of + and -.
Note that parentheses may be used to
clarify or modify the evaluation of expressions of any type in C in the same
way as in normal arithmetic.
x = 7 + (
3 * 6 / 2 ) - 1 ; // clarifies order
of evaluation without penalty
x = ( 7 +
3 ) * 6 / ( 2 - 1 ) ; // changes order of
evaluation, x = 60 now.
Increment and Decrement Operators
There are two special unary operators in
C, Increment ++, and Decrement -- , which cause the variable they act on to
be incremented or decremented by 1 respectively.
For Example :-
x++ ; /*
equivalent to x = x + 1 ; */
++ and -- can be used in prefix or postfix
notation. In prefix notation the value of the variable is either incremented or
decremented and is then read while in postfix notation the value of the variable
is read first and is then incremented or
decremented.
For Example :-
int
i, j = 2 ;
i = ++
j ; /*
prefix :- i has value 3, j has value 3 */
i = j++ ; /* postfix
:- i has value 3, j has value 4 */
Special Assignment Operators
Many C operators can be combined with the
assignment operator as shorthand notation
For Example :-
x = x + 10 ;
can be replaced by
x += 10 ;
Similarly for -=, *=, /=, %=, etc.
These shorthand operators improve the speed
of execution as they require the expression, the variable x in the above
example, to be evaluated once rather than twice.
Relational Operators
The full set of relational operators are
provided in shorthand notation
> >= < <= == !=
For Example :-
if ( x == 2 )
printf( “x is equal to 2\n” ) ;
Logical Operators
&& -- Logical AND
|
| -- Logical OR
! -- Logical
NOT
For Example :-
if ( x >= 0 && x < 10 )
printf( “ x is greater than or equal to zero
and less than ten.\n” ) ;
NB : There is no Boolean type in C so TRUE and FALSE are deemed to have
the following meanings.
FALSE --
value zero
TRUE --
any non-zero value but 1 in the case of in-built relational operations
For Example :-
2
> 1 -- TRUE so expression has value 1
2
> 3 -- FALSE so
expression has value 0
i
= 2 > 1 ; -- relation is TRUE --
has value 1, i is assigned value 1
NB :
Every C expression has a value. Typically we regard
expressions like 2 + 3 as the only expressions with actual numeric values.
However the relation 2 > 1 is an expression which evaluates to TRUE so it
has a value 1 in C. Likewise if we have an expression x = 10 this has a value
which in this case is 10 the value actually assigned.
NB :
Beware of the following common source of error. If
we want to test if a variable has a particular value we would write for example
if ( x == 10 ) …
But if this is inadvertently written as
if ( x = 10 ) …
this will give no compilation error to warn
us but will compile and assign a value 10 to x when the condition is tested. As
this value is non-zero the if condition is deemed true no matter what value x
had originally. Obviously this is possibly a serious logical flaw in a program.
Bitwise Operators
These are special operators that act on char or int arguments only. They allow
the programmer to get closer to the machine level by operating at bit-level in
their arguments.
&
Bitwise AND | Bitwise
OR
^ Bitwise XOR ~ Ones
Complement
>> Shift Right << Shift
left
Recall that type char is one byte in size.
This means it is made up of 8 distinct bits or binary digits normally
designated as illustrated below with Bit 0 being the Least Significant Bit
(LSB) and Bit 7 being the Most Significant Bit (MSB). The value represented
below is 13 in decimal.
Bit
7
|
Bit
6
|
Bit
5
|
Bit
4
|
Bit
3
|
Bit
2
|
Bit
1
|
Bit
0
|
0
|
0
|
0
|
0
|
1
|
1
|
0
|
1
|
An integer on a 16 bit OS is two bytes in
size and so Bit 15 will be the MSB while on a 32 bit system the integer is four
bytes in size with Bit 31 as the MSB.
Bitwise
AND, &
RULE
: If any two bits in the same bit position are set
then the resultant bit in that position is set otherwise it is zero.
For Example :-
1011 0010 (178)
& 0011 1111 (63)
= 0011 0010 (50)
Bitwise
OR, |
RULE
: If either bit in corresponding positions are set
the resultant bit in that position is set.
For Example :-
1011
0010 (178)
| 0000 1000 (63)
= 1011 1010 (186)
Bitwise
XOR, ^
RULE
: If the bits in corresponding positions are
different then the resultant bit is set.
For Example :-
1011 0010 (178)
^ 0011 1100 (63)
= 1000
1110 (142)
Shift
Operators, << and >>
RULE
: These move all bits in the operand left or right
by a specified number of places.
Syntax : variable <<
number of places
variable
>> number of places
For Example :-
2 << 2 = 8
i.e.
0000
0010 becomes
0000 1000
NB : shift left by one place
multiplies by 2
shift
right by one place divides by 2
Ones
Complement
RULE
: Reverses the state of each bit.
For Example :-
1101
0011 becomes 0010
1100
NB :
With all of the above bitwise operators we must
work with decimal, octal, or hexadecimal values as binary is not supported
directly in C.
The bitwise operators are most commonly
used in system level programming where individual bits of an integer will
represent certain real life entities which are either on or off, one or zero.
The programmer will need to be able to manipulate individual bits directly in
these situations.
A mask variable which allows us to ignore
certain bit positions and concentrate the operation only on those of specific
interest to us is almost always used in these situations. The value given to
the mask variable depends on the operator being used and the result required.
For Example :- To clear bit 7 of a char
variable.
char ch = 89 ; // any value
char mask = 127 ; // 0111 1111
ch = ch & mask ; // or ch &= mask ;
For Example :- To set bit 1 of an integer
variable.
int i = 234 ; // any value
int mask = 2 ; // a 1 in bit position 2
i |= mask ;
Implicit & Explicit Type Conversions
Normally in mixed type expressions all
operands are converted temporarily
up to the type of the largest operand in the expression.
Normally this
automatic or implicit casting of operands follows the following guidelines in
ascending order.
long double
|
double
|
float
|
unsigned long
|
long
|
unsigned int
|
signed int
|
For Example :-
int i ;
float f1, f2 ;
f1 = f2 + i ;
Since f2 is a floating point variable the
value contained in the integer variable is temporarily converted or cast
to a floating point variable also to standardise the addition operation
in this case. However it is important to realise that no permanent modification
is made to the integer variable.
Explicit casting coerces the
expression to be of specific type and is
carried out by means of the cast
operator which has the following syntax.
Syntax : ( type ) expression
For Example if we have an integer x, and we
wish to use floating point division in the expression x/2 we might do the
following
( float ) x / 2
which causes x to be temporarily cast to a
floating point value and then implicit casting causes the whole operation to be
floating point division.
The same results could be achieved by
stating the operation as
x
/ 2.0
which essentially does the same thing but
the former is more obvious and descriptive of what is happening.
NB :
It should be noted that all of these casting
operations, both implicit and explicit, require processor time. Therefore for
optimum efficiency the number of conversions should be kept to a minimum.
Sizeof Operator
The sizeof operator gives the amount of
storage, in bytes, associated with a variable or a type (including aggregate
types as we will see later on).
The expression is either an identifier or a
type-cast expression (a type specifier enclosed in parentheses).
Syntax : sizeof ( expression )
For Example :-
int x ,
size ;
size =
sizeof ( x ) ;
printf(“The
integer x requires %d bytes on this machine”, size);
printf(
“Doubles take up %d bytes on this machine”, sizeof ( double ) ) ;
Precedence of Operators
When several operations are combined into
one C expression the compiler has to rely on a strict set of precedence rules
to decide which operation will take preference. The precedence of C operators is given below.
Precedence
|
Operator
|
Associativity
|
Highest
|
(
) [ ]
-> .
|
left
to right
|
|
!
~ ++ --
+(unary) -(unary) (type) *
& sizeof
|
right
to left
|
|
*
/ %
|
left
to right
|
|
+
-
|
left
to right
|
|
<<
>>
|
left
to right
|
|
<
<= > >=
|
left
to right
|
|
==
!=
|
left
to right
|
|
&
|
left
to right
|
|
^
|
left
to right
|
|
|
|
left
to right
|
|
&&
|
left
to right
|
|
||
|
left
to right
|
|
? :
|
right
to left
|
|
=
+= -= *=
/= %= &=
^= |= <<=
>>=
|
right
to left
|
Lowest
|
,
|
left
to right
|
Operators at the top of the table have
highest precedence and when combined with other operators at the same
expression level will be evaluated first.
For example take the expression
2 +
10 * 5 ;
Here * and + are being applied at the same
level in the expression but which comes first ? The answer lies in the
precedence table where the * is at a higher level than the + and so will be
applied first.
When two operators with the same precedence
level are applied at the same expression level the associativity of the
operators comes into play.
For example in the expression
2 +
3 - 4 ;
the + and - operators are at the same
precedence level but associate from left to right and so the addition will be
performed first. However in the expression
x
= y = 2 ;
as we have noted already the assignment
operator associates from right to left and so the rightmost assignment is first
performed.
NB : As we have seen already parentheses
can be used to supersede the precedence rules and force evaluation along the
lines we require. For example to force the addition in 2 + 10 * 5 ; to be carried out first we would write it as (2 + 10) * 5;
Type Overflow & Underflow
When the value to be stored in a variable
of a particular type is larger than the range of values that type can hold we
have what is termed type overflow. Likewise when the value is smaller than the
range of values the type can hold we have type underflow.
Overflow and underflow are only a problem
when dealing with integer arithmetic. This is because C simply ignores the
situation and continues on as if nothing had happened. With signed integer
arithmetic adding two large positive numbers, the result of which will be
larger than the largest positive signed int, will lead to a negative value
being returned as the sign bit will be overwritten with data.
The situation is
not quite so bad with unsigned integer arithmetic. Here all values are forced
to be within range which will of course cause problems if you don’t expect
overflow to occur. Adding 1 to the largest unsigned integer will give 0.
The unfortunate aspect of the matter
however is that we cannot check for overflow until it has occurred. There are a
number of ways to do this. For example when performing integer addition you
might check the result by subtracting one of the operands from the result to
see if you get the other. On the other hand you might subtract one operand from
the largest integer to see if the result is greater than the second operand. If
it is you know your operation will succeed. However the major flaw with these
methods is that we are reducing the overall efficiency of the program with
extra operations.
In general the optimum method for dealing
with situations where overflow or underflow is possible is to use type long
over the other integer types and inspect the results. Operations using long
operands are in general slower than those using int operands but if overflow is
a problem it is still a better solution than those mentioned above.
Floating point overflow is not a problem as
the system itself is informed when it occurs which causes your program to
terminate with a run-time error. If this happens you need to promote the
variables involved in the offending operation to the largest possible and try
again.
NB :
The C standard library includes a number of exception
handling functions to allow you to intercept these situations in your program.
Exercises
1. Write a program to check the sizes of the main C data types on your
machine.
2. Write a program to illustrate whether the printf() standard library
function truncates or rounds when printing out a floating point number.
3. Write a program to check what the following code segment outputs and
explain the results.
char c ;
printf("sizeof( c ) =
%d\n", sizeof( c ) ) ;
printf("sizeof( 'a' ) = %d\n",
sizeof( 'a' ) ) ;
printf("sizeof( c = 'a' ) =
%d\n", sizeof( c='a' ) ) ;
4. Write a program which reads a character from the keyboard and writes
out its ASCII representation.
Now write a program which reads in an
integer from the keyboard and print out its character representation. Make
certain you carry out appropriate bounds / error checking.
5. Use the getchar() function to read in a single character and output
it to the screen e.g.
puts("Enter a
character");
c = getchar() ;
printf("The character was
%c\n",c);
Add another c = getchar() statement
immediately after the existing one and explain what happens.
Repeat the above using the getch()
function in place of getchar().
6. Describe the output from each
of the following statements.
i. printf( “%-10d\n”, 10000 ) ;
ii. printf( “%8.3f\n”, 23.234 ) ;
iii.printf( “%+*.*lf\n”, 10, 3,
1234.234 ) ;
iv. printf( “%x\n”, 16 ) ;
v. printf( “%10.3E”, 234.65343 ) ;
7. Write down appropriate C
statements to do the following.
i.
Print a long int, 400000L, left
justified in a 10 digit field padding it out with zeros if possible.
ii. Read a time of the form hh:mm:ss
storing the parts of the time in integer variables hour, minute, and second. Skip the colons in the input
field.
iii. Print out the following sequence of characters “%, \ and " require special treatment” .
iv. Read the value 123456789.012345456789e+5 into a floating point, a
double and a long double variable and print all three out again with the
maximum precision possible.
8. What value does x contain
after each of the following where x is of type float.
i. x = 7 + 3 * 6 / 2 - 1 ;
ii. x = 2 % 2 + 2 * 2 - 2 / 2 ;
iii.x = ( 3 * 9 * ( 3 + ( 4 * 5 / 3 ) ) ) ;
iv. x = 12.0 + 2 / 5 * 10.0 ;
v. x = 2 / 5 + 10.0 * 3 - 2.5 ;
vi. x = 15 > 10 && 5 <
2 ;
9. Write a program to read
Fahrenheit temperatures and print them in Celsius. The formula is
°C
= (5/9)(°F - 32). Use variables of type double in your program.
10. Write a program that reads in the radius of a circle and prints the
circle’s diameter, circumference and area. Use the value 3.14159 for “pi”.