Saturday, December 10, 2011

C programming Lecture 5


Scope
In the Basic Concepts section, the concept of scope was introduced. It is important to revisit the
distinction between local types and global types, and how to declare variables of each. To declare a
local
 variable, you place the declaration at the beginning (i.e. before any non­declarative statements)
of the block the variable is intended to be local to. To declare a global variable, declare the variable
outside of any block. If a variable is global, it can be read, and written, from anywhere in your
program.
Global variables are not considered good programming practice, and should be avoided whenever
possible. They inhibit code readability, create naming conflicts, waste memory, and can create
difficult
­to­trace bugs. Excessive usage of globals is usually a sign of laziness and/or poor design.
However, if there is a situation where local variables may create more obtuse and unreadable code,
there's no shame in using globals. (Implementing malloc, which is a function discussed later, is one
example of something that is simply too much more difficult to write without at least one global
variable.)
Other Modifiers
Included here, for completeness, are more of the modifiers that standard C provides. For the
beginning programmer, static and extern may be useful. volatile is more of interest to advanced programmers. register and auto are largely deprecated and are generally not of interest to either beginning or advanced programmers.
static is sometimes a useful keyword. It is a common misbelief that the only purpose is to make a variable stay in memory.
When you declare a function or global variable as static it will become internal. You cannot access
the function or variable through the extern (see below) keyword from other files in your project.
When you declare a local variable as static, it is created just like any other variable. However, when
the
 variable goes out of scope (i.e. the block it was local to is finished) the variable stays in memory,
retaining its value. The variable stays in memory until the program ends. While this behaviour
resembles that of global variables, static variables still obey scope rules and therefore cannot be
accessed outside of their scope.
Variables declared static are initialized to zero (or for pointers, NULL) by default.
You can use static in (at least) two different ways. Consider this code, and imagine it is in a file called jfile.c:
static  int  j  =  0;
void  upj(void)
{
static  int  k  =  0;
j++;
}

void  downj(void)
{
j­­;
}





The j var is accessible by both upj and downj and retains its value. the k var also retains its value,
but is only accessible to upj. static vars are a good way to implement encapsulation, a term from the object­oriented way of thinking that effectively means not allowing changes to be made to a variable except through function calls.
extern is used when a file needs to access a variable in another file that it may not have
#included directly. Therefore, extern does not actually carve out space for a new variable, it just provides the compiler with sufficient information to access the remote variable.
volatile is a special type modifier which informs the compiler that the value of the variable may be changed by external entities other than the program itself. This is necessary for certain programs compiled with optimizations ­ if a variable were not defined volatile then the compiler may assume that certain operations involving the variable are safe to optimize away when in fact they aren't. volatile is particularly relevant when working with embedded systems (where a program may not have complete control of a variable) and multi­threaded applications.
auto is a modifier which specifies an "automatic" variable that is automatically created when in
scope and destroyed when out of scope. If you think this sounds like pretty much what you've been
doing all along when you declare a variable, you're right: all declared items within a block are
implicitly
 "automatic". For this reason, the auto keyword is more like the answer to a trivia question
than a useful modifier, and there are lots of very competent programmers that are unaware of its
existence.
register is a hint to the compiler to attempt to optimize the storage of the given variable by
storing it in a register of the computer's CPU when the program is run. Most optimizing compilers do this anyway, so use of this keyword is often unnecessary. In fact, ANSI C states that a compiler can ignore this keyword if it so desires ­­ and many do. Microsoft Visual C++ is an example of an implementation that completely ignores the register keyword.


Concepts
   oncept
   ariable
   ype
   rray

In this section
    variable
    type
    array
Simple Input and Output
When you take time to consider it, a computer would be pretty useless without some way to talk to the people who use it. Just like we need information in order to accomplish tasks, so do computers. And just as we supply information to others so that they can do tasks, so do computers.
These supplies and returns of information to a computer are called input and output. 'Input' is




information supplied to a computer or program. 'Output' is information provided by a computer or program. Frequently, computer programmers will lump the discussion in the more general term input/output or simply, I/O.
In C, there are many different ways for a program to communicate with the user. Amazingly, the
most
 simple methods usually taught to beginning programmers may also be the most powerful. In
the "Hello, World" example at the beginning of this text, we were introduced to a Standard Library
file
 stdio.h, and one of its functions, printf(). Here we discuss more of the functions that stdio.h
gives us.

Output using printf()
Recall from the beginning of this text the demonstration program duplicated below:
#include  <stdio.h>

int  main(void)
{
printf("Hello,  world!\n"); return  0;
}

If you compile and run this program, you will see the sentence below show up on your screen:


Hello,  world!

This amazing accomplishment was achieved by using the function printf(). A function is like a "black box" that does something for you without exposing the internals inside. We can write
functions ourselves in C, but we will cover that later.
You have seen that to use printf() one puts text, surrounded by quotes, in between the brackets. We call the text surrounded by quotes a literal string (or just a string), and we call that string an
argument to printf.
As a note of explanation, it is sometimes convenient to include the open and closing parentheses
after a function name to remind us that it is, indeed, a function. However usually when the name of the function we are talking about is understood, it is not necessary.
As you can see in the example above, using printf() can be as simple as typing in some text, surrounded by double quotes (note that these are double quotes and not two single quotes). So, for example, you can print any string by placing it as an argument to the printf() function:


printf("This  sentence  will  print  out  exactly  as  you  see  it...");

And once it is contained in a proper main() function, it will show:


This  sentence  will  print  out  exactly  as  you  see  it...




Printing numbers and escape sequences

Placeholder codes
The printf function is a powerful function, and is probably the most­used function in C programs.
For example, let us look at a problem. Say we don't know what 1905 + 31214 is. Let's use C to get the answer.
We start writing
#include  <stdio.h>  /*  this  is  important,  since  printf
can't  be  used  without  this  line  */


(For more information about the line above, see The Preprocessor).


int  main(void)
{
printf("1905+31214  is"); return  0;
}

but here we are stuck! printf only prints strings! Thankfully, printf has methods for printing numbers. What we do is put a placeholder format code in the string. We write:
printf("1905+31214  is  %d",  1905+31214);

The placeholder %d literally "holds the place" for the actual number that is the result of adding 1905
to 31214.
These placeholders are called format specifiers. Many other format specifiers work with printf. If we have a floating­point number, we can use %f to print out a floating­point number, decimal point and all. An incomplete list is:






%i ­ int (same as %d) %f ­ float
%lf ­ double
%s ­ string
%x ­ hexadecimal

A more complete list is in the File I/O section.

Tabs and newlines
What if, we want to achieve some output that will look like:
1905
31214 +
­­­­­

printf will not put line breaks in at the end of each statement: we must do this ourselves. But
how?
What we can do is use the newline escape character. An escape character is a special character that
we
 can write but will do something special onscreen, such as make a beep, write a tab, and so on.



To write a newline we write \n. All escape characters start with a backslash. So to achieve the output above, we write
printf("  1905\n31214  +\n­­­­­\n%d",  33119);
or to be a bit clearer, we can break this long printf statement over several lines. So our program will
be:
#include  <stdio.h>
int  main(void)
{
printf("  1905\n");
printf("31214  +\n");
printf("­­­­­\n");
printf("%d",  33119);
return  0;
}
There are other escape characters we can use. Another common one is to use \t to write a tab. You can use \a to ring the computer's bell, but you should not use this very much in your programs, as excessive use of sound is not very friendly to the user.
Other output methods

puts()
The puts() function is a very simple way to send a string to the screen when you have no
placeholders to be concerned about. It works very much like the printf() function we saw the "Hello, World!" example:
puts("Print  this  string.");

will print to the screen:
Print  this  string.

followed by the newline character (as discussed above). (The puts function appends a newline character to its output.) The fputs function is similar:
fputs("Print  this  string  via  fputs",  stdout);

will print to the stdout file (usually the screen):
Print  this  string  via  fputs

without a newline tacked on to the end.
Since puts() and fputs() do not allow the placeholders and the associated formatting that printf() allows, for most programmers learning printf() is sufficient for their needs.




Input using scanf()
The scanf() function is the input method equivalent to the printf() output function ­ simple yet
powerful. In its simplest invocation, the scanf format string holds a single placeholder representing the type of value that will be entered by the user. These placeholders are exactly the same as the printf() function ­ %d for ints, %f for floats, and %lf for doubles.
There is, however, one variation to scanf() as compared to printf(). The scanf() function requires the memory address of the variable to which you want to save the input value. While pointers are
possible here, this is a concept that won't be approached until later in the text. Instead, the simple
technique is to use the address­of operator, &. For now it may be best to consider this "magic"
before we discuss pointers.
A typical application might be like this:
#include  <stdio.h>

int  main(void)
{
int  a;

printf("Please  input  an  integer  value:  "); scanf("%d",  &a);
}


If you are trying to input a string using scanf, you should not include the & operator.
If you were to describe the effect of the scanf() function call above, it might read as: "Read in an integer from the user and store it at the address of variable a ".
Note of caution on inputs: When data is typed at a keyboard, the information does not go straight to the program that is running. It is first stored in what is known as a buffer ­ a small amount of memory reserved for the input source. Sometimes there will be data left in the buffer when the program wants to read from the input source, and the scanf() function will read this data instead of waiting for the user to type something. The function fflush(stdin) may fix this issue on some
computers and with some compilers, by clearing or "flushing" the input buffer. But this isn't
generally considered good practice and may not be portable ­ if you take your code to a different computer with a different compiler, your code may not work properly.
Examples
 Simple Input and Outpu| Further math 

Operators and Assignments
In C, simple math is very easy to handle. The following operators exist: + (addition), ­ (subtraction), * (multiplication), / (division), and % (modulus); You likely know all of them from your math
classes
 ­ except, perhaps, modulus. It returns the remainder of a division (e.g. 5 % 2 = 1).
Care must be taken with the modulus, because it's not the equivalent of the mathematical modulus:
(­5) % 2 is not 1, but ­1. Division of integers will return an integer, and the division of a negative integer by a positive integer will round towards zero instead of rounding down (e.g. (­5) / 3 = ­1 instead of ­2).




There is no inline operator to do the power (e.g. 5 ^ 2 is not 25, and 5 ** 2 is an error), but there is a
power function.
The mathematical order of operations does apply. For example (2 + 3) * 2 = 10 while 2 + 3 * 2 = 8.
The order of precedence in C is BFDMAS: Brackets, Functions, Division or Multiplication (from
left
 to right, whichever comes first), Addition or Subtraction (also from left to right, whichever
comes first).
Assignment in C is simple. You declare the type of variable, the name of the variable and what it's equal to. For example, int x = 0; double y = 0.0; char z = 'a';
#include  <stdio.h>
int  main()
{
int  i  =  0,  j  =  0;

while(  (i  <  5)  &&  (j  <  5)  )  {  /*  while  i  is  less  than  5  AND  j  is  less  than  5, loop  */
++j;  /*  prefix  increment,  increases  by  1  immediately  */
printf("i  equals:  %d\tj  equals:  %d\n",  i,  j);  /*  will  print  current variable  values  */
i++;  /*  postfix  increment,  increases  by  1  next  time  the  variable  is
called,  therefore  i  will  be  equal  to  0  in  the  beginning  */
}

return  0;
}

will display the following:
i  equals:  0            j  equals:  1
i  equals:  1            j  equals:  2
i  equals:  2            j  equals:  3
i  equals:  3            j  equals:  4
i  equals:  4            j  equals:  5

The <math.h> header contains prototypes for several functions that deal with mathematics. In the 1990 version of the ISO standard, only the double versions of the functions were specified; the 1999 version added the float and long  double versions.
The functions can be grouped into the following categories:

Trigonometric functions

The acos and asin functions
The acos functions return the arccosine of their arguments in radians, and the asin functions
return the arcsine of their arguments in radians. All functions expect the argument in the range [­1
,+1].
 The arccosine returns a value in the range [0,π]; the arcsine returns a value in the range [­π
/2,+π/2].
#include  <math.h>
float  asinf(float  x);  /*  C99  */ float  acosf(float  x);  /*  C99  */ double  asin(double  x);





double  acos(double  x);
long  double  asinl(long  double  x);  /*  C99  */
long  double  acosl(long  double  x);  /*  C99  */


The atan and atan2 functions
The atan functions return the arctangent of their arguments in radians, and the atan2 function return the arctangent of y/x in radians. The atan functions return a value in the range [­π/2,+π/ (the reason why ±π/2 are included in the range is because the floating­point value may represen t infinity, and atan(±∞) = ±π/2); theatan2 functions return a value in the range [­π,+π]. Foratan2, a domain error may occur if both arguments are zero.
#include  <math.h>
float  atanf(float  x);  /*  C99  */
float  atan2f(float  y,  float  x);  /*  C99  */ double  atan(double  x);
double  atan2(double  y,  double  x);
long  double  atanl(long  double  x);  /*  C99  */
long  double  atan2l(long  double  y,  long  double  x);  /*  C99  */


The cos, sin, and tan functions
The cos, sin, and tan functions return the cosine, sine, and tangent of the argument, expressed in
radians.
#include  <math.h>
float  cosf(float  x);  /*  C99  */ float  sinf(float  x);  /*  C99  */ float  tanf(float  x);  /*  C99  */ double  cos(double  x);
double  sin(double  x);
double  tan(double  x);
long  double  cosl(long  double  x);  /*  C99  */
long  double  sinl(long  double  x);  /*  C99  */
long  double  tanl(long  double  x);  /*  C99  */


Hyperbolic functions
The cosh, sinh and tanh functions compute the hyperbolic cosine, the hyperbolic sine, and the hyperbolic tangent of the argument respectively. For the hyperbolic sine and cosine functions, a range error occurs if the magnitude of the argument is too large.
#include  <math.h>
float  coshf(float  x);  /*  C99  */ float  sinhf(float  x);  /*  C99  */ float  tanhf(float  x);  /*  C99  */ double  cosh(double  x);
double  sinh(double  x);
double  tanh(double  x);
long  double  coshl(long  double  x);  /*  C99  */
long  double  sinhl(long  double  x);  /*  C99  */
long  double  tanhl(long  double  x);  /*  C99  */





Exponential and logarithmic functions

The exp functions
The exp functions compute the exponential function of x (ex). A range error occurs if the magnitude of x is too large.
#include  <math.h>
float  expf(float  x);  /*  C99  */ double  exp(double  x);
long  double  expl(long  double  x);  /*  C99  */


The frexp, ldexp, and modf functions
The frexp functions break a floating­point number into a normalized fraction and an integer power of 2. It stores the integer in the object pointed to by ex.
The frexp functions return the value x such that x has a magnitude of either [1/2, 1) or zero, and value equals x times 2 to the power *ex. If value is zero, both parts of the result are zero.
The ldexp functions multiply a floating­point number by a integral power of 2 and return the result. A range error may occur.
The modf function breaks the argument value into integer and fraction parts, each of which has the same sign as the argument. They store the integer part in the object pointed to by *iptr and return the fraction part.
#include  <math.h>
float  frexpf(float  value,  int  *ex);  /*  C99  */ double  frexp(double  value,  int  *ex);
long  double  frexpl(long  double  value,  int  *ex);  /*  C99  */ float  ldexpf(float  x,  int  ex);  /*  C99  */
double  ldexp(double  x,  int  ex);
long  double  ldexpl(long  double  x,  int  ex);  /*  C99  */ float  modff(float  value,  float  *iptr);  /*  C99  */
double  modf(double  value,  double  *iptr);
long  double  modfl(long  double  value,  long  double  *iptr);  /*  C99  */


The log and log10 functions
The log functions compute the natural logarithm of the argument and return the result. A domain error occurs if the argument is negative. A range error may occur if the argument is zero.
The log10 functions compute the common (base­10) logarithm of the argument and return the
result. A domain error occurs if the argument is negative. A range error may occur if the argument
is zero.
#include  <math.h>
float  logf(float  x);  /*  C99  */ double  log(double  x);
long  double  logl(long  double  x);  /*  C99  */ float  log10f(float  x);  /*  C99  */





double  log10(double  x);
long  double  log10l(long  double  x);  /*  C99  */


Power functions

The pow functions
The pow functions compute x raised to the power y and return the result. A domain error occurs if x is negative and y is not an integral value. A domain error occurs if the result cannot be
represented when x is zero and y is less than or equal to zero. A range error may occur.
#include  <math.h>
float  powf(float  x,  float  y);  /*  C99  */ double  pow(double  x,  double  y);
long  double  powl(long  double  x,  long  double  y);  /*  C99  */


The sqrt functions
The sqrt functions compute the nonnegative square root of x and return the result. A domain error occurs if the argument is negative.
#include  <math.h>
float  sqrtf(float  x);  /*  C99  */ double  sqrt(double  x);
long  double  sqrtl(long  double  x);  /*  C99  */


Nearest integer, absolute value, and remainder functions

The ceil and floor functions
The ceil functions compute the smallest integral value not less than x and return the result; the floor functions compute the largest integral value not greater than x and return the result.
#include  <math.h>
float  ceilf(float  x);  /*  C99  */ double  ceil(double  x);
long  double  ceill(long  double  x);  /*  C99  */ float  floorf(float  x);  /*  C99  */
double  floor(double  x);
long  double  floorl(long  double  x);  /*  C99  */


The fabs functions
The fabs functions compute the absolute value of a floating­point number x and return the result.
#include  <math.h>
float  fabsf(float  x);  /*  C99  */ double  fabs(double  x);





long  double  fabsl(long  double  x);  /*  C99  */


The fmod functions
The fmod functions compute the floating­point remainder of x/y and return the value x ­ i * y, for some integer i such that, if y is nonzero, the result has the same sign as x and magnitude less than
the magnitude of y. If y is zero, whether a domain error occurs or the fmod functions return zero is implementation­defined.
#include  <math.h>
float  fmodf(float  x,  float  y);  /*  C99  */ double  fmod(double  x,  double  y);
long  double  fmodl(long  double  x,  long  double  y);  /*  C99  */ 

0 comments: