Sei sulla pagina 1di 77

4.

variables and constants


1. Variable declaration
Variables are data objects which keep values in the memory. A variable
is declared by using the following syntax.
dataType variableNameList;
o Each variable must have a data type and have an unique name,
i.e., you can not define different variables with the same name.
o A variable must be declared before it is used.
o Variables can only be declared at the beginning of any block.
o In a single declaration statement, there can be more than one
variable name which are separated by commas. But you can only
define the variables of the same data type in a single declaration
statement.
o When you define a variable, its value is garbage (its value can not
be predicted), but there are exceptions. But it is also possible to
initialize the value of a variable when you define it. Note that
initializer must be constant value.
o For printf() and scanf() functions, the type of variable should
match up with the corresponding conversion specifier, otherwise
an undefined behavior occurs.
o x 'x' "x"
x: it is the name of a variable.
'x': it is a character x.
"x": it is a string x.
o 9 '9' "9"
9: it is the integer constant 9.
'9': it is a character 9, and it has the value of 57 in ASCII code.
"9": it is a string 9.

FILE:variables.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-
256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)


1

2

#include<stdio.h>

int main(){
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE

3

4

5

6

7

8

9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
int num1 = 0, num2, sum;
float Num1;
long double tax = 4.3;
double second;
long factorial = 40L;
char myName = 'a', t;
char first = '\n';
double no1 = 3.4, no2 = 5.6, no3, no4 = -132;
float last;

scanf("%d%lf%ld%c",&num1,&second,&factorial,&f
irst);
scanf("%f",&Num1);
printf("Different numbers:
%d\t%ld\t%Lf\n",num2,factorial,tax);
printf("More than this, %c %c",myName,first);

anykey();
return 0;
}

2. Rules for variable names
These rules are also valid for identifier names, e.g., variable names,
function names, symbolic constant names, etc.
1. They must consist of letters and digits (The underscore character
is counted as a letter). The names of variables do not need to be
meaningful.
2. The names of variables must begin letters. It is also possible to
begin with the underscore character, but it is not recommended
since library routines often use such names.
3. Do not forget that C is a case sensitive, i.e., x and X are
different.
4. At least 31 characters of an internal name are significant (it
depends on a compiler).
5. Keywords like int, main, float, return, long, unsigned, const, if,
etc are reserved and can not be used as identifier names.
Here are some valid identifier names:
My_Name8
number_
_number
CMPE
fdjkfhdg34ffs
x9875424
And some invalid identifier names are listed as follows:
8Name_4
4563
number+
data\%
return
3. Constants
They are values defined as constants, you can not change their values in
the execution of the program. We can define constants by two different
ways.
0. By using reserved word const. It must be defined in the
declaration part, note that a memory location is allocated for the
constant.
const type name var name = constant value;
const double PI = 3.14;
1. By using define. Actually it is a substitution and no memory place
is allocated.
#define PI 3.14
If you want to define PI as long double use
#define PI 3.14L
Note that we can use define for other purposes (look at subject
macros).
4. Enumeration constants
It is for defining a list of constant integer values, remember that
character constant values are actually small integer values. It is
alternative to multiple #define's.
enum Month{JAN = 1, FEB, MAR};
enum BOOLEAN{no, yes};
enum my_numbers{three = 3, one, FOUR = 2, five};
enum specialCharacters{TAB = '\t', NEWLINE = '\n', BACKSLASH =
'\\'};
o They behave like integers.
o Unless it is specified, the values of enumeration constants begins
with 0. The other unspecified ones continues from the last
specified one.
o Names in different enumerations must be distinct.
o Values do not need to be distinct in the same or different
enumeration.
enum boolean{FALSE,TRUE};
int main (){
int a;
a = FALSE;
}
enum boolean{FALSE,TRUE};
int main (){
enum boolean b;
b = 9; /* it gives warning */
b = TRUE;
}
int main(){
enum boolean{FALSE,TRUE};
int a;
enum boolean b;
a = FALSE;
b = 9; /* it gives warning */
b = TRUE;
}
5. Assignment and type conversions
When a narrower type is assigned to a wider one, the value is assigned
without losing information. When a wider type is assigned to a narrower
one, we may lose some information.
int a;
float b;
char c;
a=3.14; /* a = 3 */
b=8; /* b = 8.0 */
c='0'; /* c = '0' */
b=9.2; /* b = 9.2 */
a=b; /* a = 9 */
b=a; /* b = 9.0 */
a=c; /* a = 48, since ASCII code of '0' is 48 */
b=c; /* b = 48.0 */
c=49; /* c = '1', since ASCII code of '1' is 49 */
c=50.2; /* c = '2' */
2. Introduction To C
2.1. Hello World Example
2.2. Summation Of Two Integers
2.3. Subtraction Multiplication Division Mod

2.1. Hello World Example
A program that writes hello world on the screen:
FILE:introduction_to_c__hello_world_example__hello_world.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include<stdio.h>

int X,Y,Z, sum{



scanf("d")





anykey();

return 0;
}

2.2. Summation Of Two Integers
A program that reads 2 integers, calculates the sum of them, then prints the sum:

FILE:introduction_to_c__summation_of_two_integers__sum2num.
c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9

#include<stdio.h>

int main(){


anykey();
return 0;
}
Exercise:Modify above program so it sums 3 integers
2.3. Subtraction Multiplication Division Mod
A program that reads 2 numbers, then calculates and prints
sum
subtraction
multiplication
division
mod
of 2 numbers

FILE:introduction_to_c__subtraction_multiplication_division_
mod__example.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPIL
E
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautif
y();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
3. Data Types
3.1. Integers
3.2. Floating Point Numbers
3.3. Characters

3.1. Integers
We have already studied integer data type (int).
For integer type modifiers (short, long, signed, unsigned) please refer to "Advanced Topics in
C"section.
3.2. Floating Point Numbers
Floating point numbers are the real numbers, i.e., the numbers with fractional parts (e.g.: 1.54).
Just like integers being input and output using %d, floats are input and output using %f.
Example:
A program that reads two floats from the user and calculates the sum:
FILE:data_types__floating_point_numbers__sum2float.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE

1
2
3
4

#include<stdio.h>

(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
5
6
7
8
9
10
11
12
13
14
15
16
int main(){

float X, Y;
int Div;

scanf("%f%f",&X,&Y);

Div = X / Y;

printf("%d\n",Div);
anykey();
return 0;
}
Another method for declaring a real number is using double, which can store real numbers with
higher precision.
%lf is used for reading and writing doubles.
Example:
A program that reads two doubles from the user and calculates the sum:
FILE:data_types__floating_point_numbers__sum2double.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9

#include<stdio.h>

int main(){


anykey();
return 0;
}
For other float types (e.g. long double), please refer to "Advanced Topics in C" section.
3.3. Characters

FILE:data_types__characters__char_define.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT

1
2
3
4
5
6
7
8
9
10
11

#include<stdio.h>

int main(){


char ch=0;


printf("%c:%d\n",ch,ch);
anykey();
CODE
12
13
return 0;
}
Example:
A program that reads a character variable from the user, then prints the character read and its ASCII
code (integer value corresponding to that character) on screen:
FILE:data_types__characters__char.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
4. Variables And Constants
4.1. Variable Declaration
4.2. Rules For Variable Names
4.3. Constants
4.4. Assignment And Type Conversions

4.1. Variable Declaration
Below is an example of various variable declarations. Please note that you are only responsible for
int, float, double, char
data types. Other types are used just for reference.

FILE:variables_and_constants__variable_declaration__declare
.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE


1

2

3

4

5

6

7

8

#include<stdio.h>

int main(){
int num1 = 0, num2, sum;
float Num1;
long double tax = 4.3;
double second;
long factorial = 40L;
char myName = 'a', t;
char first = '\n';
double no1 = 3.4, no2 = 5.6, no3, no4 = -132;
float last;

scanf("%d%lf%ld%c",&num1,&second,&factorial,&first);
scanf("%f",&Num1);

9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
printf("Different numbers:
%d\t%ld\t%Lf\n",num2,factorial,tax);
printf("More than this, %c %c",myName,first);

anykey();
return 0;
}

4.2. Rules For Variable Names

These rules are also valid for identifier names, e.g., variable names, function names, symbolic
constant names, etc.
1. They must consist of letters and digits (The underscore character '_' is considered as a
letter).
2. The names of variables must begin with letters. It is also possible to begin with the
underscore character, but it is not recommended since library routines often use such
names.
3. Do not forget that C is a case sensitive language, i.e., x and X are different.
4. At least first 31 characters of an internal name are significant (it depends on a compiler).
5. Keywords like int, main, float, return, long, unsigned, const, if, etc. are reserved and can not
be used as identifier names.
The language does not require that variable names are meaningful, but it is STRONGLY
recommended that you use meaningful names.
Here are some valid identifier names:
My_Name8
number_
_number
CMPE
fdjkfhdg34ffs
x9875424
And some invalid identifier names are listed as follows:
8Name_4
4563
number+
data\%
return

4.3. Constants
They are identifiers defined as constants. You are not allowed to change their values during the
execution of the program. For example:
#define PI 3.14
Note that, by convention, only CAPITAL LETTERS and _ character are used within constant names.

Example:
A program which reads the radius of a circle and then calculates circumference and area (utilizing a
defined PI):
FILE:variables_and_constants__constants__circle.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include<stdio.h>
#define PI 3.14


int main(){
int r;
float circ,area;

scanf("%d",&r);
circ = 2*r*PI;
area = r*r*PI;

printf("circ is: %.2f\nArea is:
%.2f\n",circ,area);

anykey();
return 0;
}
For other constant types such as use of const directive or enum data type, please refer to "advanced
C topics" section
4.4. Assignment And Type Conversions
When a narrower type is assigned to a wider one, the value is assigned without losing information.
When a wider type is assigned to a narrower one, you may lose some information.

FILE:variables_and_constants__assignment_and_type_conversions
__float_int_conversion.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPI
LE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beauti
fy();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#include<stdio.h>

int main(){
int a;
float b;
char c;
a=3.14; /* a = 3 */
b=8; /* b = 8.0 */
c='0'; /* c = '0' */
printf("a:%d b:%f c:%c\n",a,b,c);
anykey();
b=9.2; /* b = 9.2 */
printf("b:%f\n",b);
anykey();
a=b; /* a = 9 */
printf("a:%d\n",a);
anykey();
b=a; /* b = 9.0 */
printf("b:%f\n",b);
anykey();
a=c; /* a = 48, since ASCII code of '0' is 48 */
printf("a:%d\n",a);
anykey();
b=c; /* b = 48.0 */
printf("b:%f\n",b);
anykey();
c=49; /* c = '1', since ASCII code of '1' is 49
*/
printf("c:%c\n",c);
anykey();
c=50.2; /* c = '2' */
printf("c:%c\n",c);
anykey();
anykey();
return 0;
}
5. Operators
5.1. Assignment Operator
5.2. Arithmetic Operators
5.3. Increment And Decrement Operators

5.1. Assignment Operator

x = a + y;
x += y; // short notation for x = x + y; (does the same thing)
x *= y + 1; // short notation for x = x * (y + 1); (does the same
thing)

5.2. Arithmetic Operators

+, , *, / Can be applied to all data types (including character data type).
% modulus operator. Can be applied only to integer class.
/ integer division (truncates any fraction part) if both operands are integers.
When an operator has operands of different types, the narrower operand is converted to the
wider one.

FILE:operators__arithmetic_operators__float_int_interaction
.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include<stdio.h>

int main(){
float x;
int a, b;
x=5/2; /* x=2.0 */
printf("x:%f\n",x);
anykey();
x=5.0/2; /* x = 2.5 */
printf("x:%f\n",x);
anykey();
a=5.0/2; /* a = 2 */
printf("a:%d\n",a);
anykey();
a=5/2+3/2; /* a=3 */
printf("a:%d\n",a);
anykey();
b=5/2.0+3/2; /* b=3 */
printf("b:%d\n",b);
anykey();
b=5/2.0+3.0/2; /* b=4 */
printf("b:%d\n",b);
anykey();
x=a/b; /* x=0.0 */
printf("x:%f\n",x);
anykey();
b=b+a; /* b=7 */
printf("b:%d\n",b);
anykey();
return 0;
}

FILE:operators__arithmetic_operators__char_int_interaction.
c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)


1

2

#include<stdio.h>

int main(){
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE

3

4

5

6

7

8

9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
int a=5002;
char ch='0'; /* ASCII code of '0' is 48 */
printf("ch:%c ascii of ch:%d\n",ch,ch);
anykey();
ch=ch+3; /* ch = '3', ASCII code becomes 51
*/
printf("ch:%c ascii of ch:%d\n",ch,ch);
anykey();
a+=ch; /* a = 5053 */
printf("a:%d\n",a);
anykey();
ch+=a; /* ch = ?, overflow and undefined
behavior occurs */
printf("ch:%c ascii of ch:%d\n",ch,ch);
anykey();
return 0;
}

FILE:operators__arithmetic_operators__char_int_interaction2
.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include<stdio.h>

int main(){
int a;
char b='A';
a='9'-'2'; /* a=7 */
printf("a:%d\n",a);
anykey();
a='Z'-b; /* a=25 */
printf("a:%d\n",a);
anykey();
b='c'+4; /* b='g' */
printf("b:%c\n",b);
anykey();
return 0;
}
Casting: Explicit type conversion can be enforced.
(type name) conversion
Suppose you have two integers and you want to compute their average and the ratio of them.
FILE:operators__arithmetic_operators__typeCasting.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#include<stdio.h>

int main(){
int x=5, y=4;
float avg, ratio;
avg = (x + y)/2; /* avg = 4.0 */
printf("avg:%f\n",avg);
anykey();
avg = (x + y)/2.0; /* avg = 4.5 */
printf("avg:%f\n",avg);
anykey();
avg = ((float)x + y)/2; /* avg = 4.5 */
printf("avg:%f\n",avg);
anykey();
avg = (float)(x + y)/2; /* avg = 4.5 */
printf("avg:%f\n",avg);
anykey();
avg = (float)((x + y)/2); /* avg = 4.0 */
printf("avg:%f\n",avg);
anykey();

ratio = x/y; /* ratio = 1.0 */
printf("ratio:%f\n",ratio);
anykey();
ratio = (float)(x/y); /* ratio = 1.0 */
printf("ratio:%f\n",ratio);
anykey();
ratio = (float)x/y; /* ratio = 1.25, the
value of x will not change */
printf("ratio:%f\n",ratio);
anykey();
ratio = (x+0.0)/y; /* ratio = 1.25 */
printf("ratio:%f\n",ratio);
anykey();
return 0;
}

5.3. Increment And Decrement Operators

++ and -- are the increment and the decrement operators respectively. ++ adds 1 to its operand and -
- subtracts 1 from its operand. They are used either prefix or postfix operators.
n++; (First use the value of n, then increment the value of n by 1)
n--; (First use the value of n, then decrement the value of n by 1)
++n; (First increment the value of n by 1, then use the value of n)
--n; (First decrement the value of n by 1, then use the value of n)

FILE:operators__increment_and_decrement_operators__post_incr
ement.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include<stdio.h>

int main(){
int n = 5,x;
n++; /* n = 6 */
printf("n:%d\n",n);
anykey();
x=n++; /* n = 7, x = 6 */
printf("x:%d n:%d\n",x,n);
anykey();
x=n--; /* n = 6, x = 7 */
printf("x:%d n:%d\n",x,n);
anykey();
return 0;
}

FILE:operators__increment_and_decrement_operators__pre_incr
ement.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include<stdio.h>

int main(){

int n = 5,x;
++n; /* n = 6 */
printf("n:%d\n",n);
anykey();
x=++n; /* n = 7, x = 7 */
printf("x:%d n:%d\n",x,n);
anykey();
x=--n; /* n = 6, x = 6 */
printf("x:%d n:%d\n",x,n);
anykey();
return 0;
18 }

6. Control Structures
6.1. If Statement
6.2. If Else
6.3. Not Operator
6.4. Nested If
6.5. Switch

6.1. If Statement
So far, a program consists of a number of statements that are executed in sequence (sequential
statements), i.e., they are executed once in all conditions.

What if we want to execute some portion of the code based on a condition?

Below is a program, which reads the grade of the student. Then, if the grade of the student is
greater than or equal to 60, it prints "You passed"

If the grade is not greater than or equal to 60, program does not print anything:


FILE:control_structures__if_statement__grade60.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include<stdio.h>

int main(){
int grade;
printf("Enter your grade:\n");
scanf("%d",&grade);




anykey();
return 0;
}

Primary comparison operators are:
< :(less than)
> :(greater than)
<= :(less than or equal to: )
>= :(greater than or equal to: )
!= :(not equal to: )
== :(equal to: important! writing = instead of == is a common
mistake)

6.2. If Else
Now suppose that, we also want to inform the student if (s)he failed (if grade < 60). Then, we use the
optional else.


FILE:control_structures__if_else__ifelsegrade60.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13

#include<stdio.h>

int main(){
int grade;
printf("Enter your grade:\n");
scanf("%d",&grade);



anykey();
return 0;
}

A program that reads 3 integers from the user. Then, it calculates and prints

the average (as a float)
the maximum
the minimum
the median (the one in the middle)
of these 3 integers:
FILE:control_structures__if_else__avg_max_min_med.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Book Solution: Help
6.3. Not Operator
! is used as a logical not operator

For example,
if(!(x==3)){
printf("x is not equal to 3")
}
IMPORTANT: do not forget parenthesis!
6.4. Nested If
The if-else structure is actually a single statement. Therefore, you can use it as one of the statements
in the statement block.
We use nested if's to encode multiway decisions. Suppose we want to classify the students into three
groups according to their grades (above 60, between 50 and 60, and below 50) and display a
message accordingly.
FILE:control_structures__nested_if__nested_if.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}


Exercise: How do you match else's with if's?
if (n > 0) if (n > 0){
if (a > b) if (a > b)
n = a; n = a;
else }
n = b; else
else n = b;
if (a < 0)
b = 1;
else if (b == 0)
b = n;


Write a program that assigns the letter grade of the score as follows: 90-100 A, 80-89 B, 70-79
C, 60-69 D, and 0-59 F.
FILE:control_structures__nested_if__letter_grade.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO

1
2
3
4
5
6

#include<stdio.h>

int main(){

(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
7
8
9
10


anykey();
return 0;
}


Example: Write a program that computes and displays the real roots of the quadratic equation
(ax
2
+bx+c=0) whose equations are taken from the user. The real roots are computes as the following
equation:
x
1,2
=
-b b
2
-4ac
2a
Let = b
2
-4ac. If <0, there are no real roots. If =0, there is only one real root. If >0, there are two
real roots.



FILE:control_structures__nested_if__quadratic_equation_solv
er.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Book Solution: Help

Example: Write a program that converts the uppercase letter to its lowercase and converts the
lowercase letter to its uppercase acccording to the case of the letter. You must display a message, if
the character is not a letter:
FILE:control_structures__nested_if__upper_lower.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)

1
2
3
4
5

#include<stdio.h>

int main(){
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
6
7
8
9
10



anykey();
return 0;
}

6.5. Switch
Consider the program reading a month and printing the days in that month:
FILE:control_structures__switch__month_if.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include<stdio.h>

int main(){
int mon,days;
printf("Enter the month: ");
scanf("%d",&mon);

if (mon == 4 || mon == 6 || mon == 9 || mon ==11)
days = 30;
else if (mon == 2)
days = 28;
else
days = 31;

printf("days:%dn",days);

anykey();
return 0;
}
Switch equivalent is:
FILE:control_structures__switch__month_switch.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}


Example: Take two decimal numbers and one character from the user (in the from of no1 character
no2) and design a simple calculator. If the character is +, -, *, or /, your program will be perform the
corresponding operation and display the results, otherwise your program will give a warning
message to the user:
FILE:control_structures__switch__calculator.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Switch statement is a special case of if statement where there are multiple cases with == checks.
ANYTHING CAN BE DONE WITH SWITCH CAN BE DONE WITH IF, however switch statement can shrink
code dramatically for certain situations.

Enter at first suitable "case", leave at first "break": Check following code for switch-break
behaviour:
FILE:control_structures__switch__break.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include<stdio.h>

int main(){
int num;
printf("Enter the number: ");
scanf("%d",&num);

switch (num){
case 1: printf("one "); break;
case 2: printf("two" );
case 3: printf("three ");
case 4: printf("four "); break;
case 5: printf("five ");
case 6: printf("six ");
default: printf("else");
}

anykey();
return 0;
21 }
7. Repetition Statements
7.1. While
7.2. For
7.3. Nested Loops
7.4. Break
7.5. Continue
So far, we have seen sequential and control statements. But suppose the following problems:
1. Writing a program which prints the line numbers at the beginning of each line (suppose we
have 100 lines).
2. Computing the average of the exam grades of 1000 students.
3. Taking a text from the user and converting its lowercase letters to their corresponding
uppercases until a new line character is pressed.
4. Computing the factorial of the number which is given by the user.
In cases 1 and 2, it is possible to write the programs by using sequential statements, however this is
not practical. For cases 3 and 4, you cannot write the necessary codes by only using sequential
statements since you do not know in advance how many times statements are to be executed, e.g.,
you cannot know when the user enters a new line character before the execution of the program. So
we need structures to execute the statements repeatedly. A loop is a group of instructions that the
compiler executes repeatedly while some conditions are satisfied.
7.1. While
Suppose printing 100 lines with their line numbers:
FILE:repetition_statements__while__100_lines.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Compute the average of n numbers entered by the user. You must take the numbers until a negative
value is entered:
FILE:repetition_statements__while__average_until_negative.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO

1
2
3
4
5

#include<stdio.h>

int main(){

(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
6
7
8
9
10


anykey();
return 0;
}
Example: Suppose the user enters the sequence of characters. Write a program that counts the
lowercase letters in this sequence until * is met:
FILE:repetition_statements__while__count_lowercase.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}


Example (read integer char-by-char): You want to take a single integer from the user. Using %d for
reading is not allowed: only %c is allowed. Input ends when a non-number character is entered.
FILE:repetition_statements__while__read_int_char_by_char.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}

7.2. For
Printing 100 lines with their numbers using for:
FILE:repetition_statements__for__100_lines.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Compute the average of n numbers entered by the user where n is also specified by the
user at the beginning of the program:
FILE:repetition_statements__for__average_n.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Suppose we want to compute the factorial of given number n:
FILE:repetition_statements__for__factorial.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Write a program that controls whether the number entered by the user is perfect or not.
Perfect number is the positive number whose sum of its positive divisors except itself is equal to
itself. For example 6 and 28 are perfect numbers (6 = 1 + 2 + 3):
FILE:repetition_statements__for__is_perfect.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}

7.3. Nested Loops
We can have two or more loops inside each other (like nested if' s or switch' s).
Example: Draw the isosceles triangle using *, where line number is also specified by the user.
FILE:repetition_statements__nested_loops__triangle.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Write a program which reads the input as a sequence of characters terminated by '! '. Your
program should detect the longest sequence of the lowercase letter repeated. Display which letter it
is and the number of its occurrences.

FILE:repetition_statements__nested_loops__longest_lowercase_
sequence.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPIL
E
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
();
}LOAD
DEFAULT
CODE

7.4. Break
It provides an early exit from for and while just as switch. It causes the innermost enclosing loop or
switch to be exited immediately. Example: Suppose the effect of the gravity on a free falling object.
Write a program that displays the height of the object falling from a tower on the screen for every
second until it hits the ground. You must also display a message when the object hits the ground (use
break to exit the loop when you detect crash). The height of the tower h0 is specified by the user and
the height h at time t is: h=h
0
-1/2gt
2
:
FILE:repetition_statements__while__free_fall.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}

7.5. Continue
It causes the next iteration of the enclosing for, while, do-while to begin. It cannot be used with
switch' s. For while and do-while loops, the test part is executed immediately. In for loops, the
control passes to the modification step.

Suppose you have the following loops, and the input of the program is: 5 -4 3 2 -5 8 9 1.

While loop version:
FILE:repetition_statements__continue__while.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){




/* sum becomes 28 */
DEFAULT
CODE
11
12
13
14
printf("sum:%d\n",sum);

anykey();
return 0;
}
For loop version:
FILE:repetition_statements__continue__for.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include<stdio.h>

int main(){




/* sum becomes 18 */
printf("sum:%d\n",sum);

anykey();
return 0;
}
8. Functions
8.1. Boolean Functions
8.2. Void Functions

Why are functions necessary?
1. Real-world problems are much larger than the ones we examined so far. Thus we need to
break up the problem into the smaller subproblems. Given a problem, we start its abstract
formulation first and work down to more detailed subproblems.
2. Functions enables us to reuse the codes written before. For example there are standard
functions defined in stdio.h (printf,scanf), in math.h (sqrt, pow, sin, cos), and we use them for
our purposes. Or consider computing the permutation of two numbers, P(n,k)=n!/(n-k)!. In
this example we must compute the factorial twice, i.e., we must write its code twice. Instead
of that, just define a function for this purpose and use if it is necessary. So we have compact
codes.
We want to write a function:
int square(int num)
which calculates square of a given value:
FILE:functions__square.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2
3

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
4
5
6
7
8
9
10

int main(){



anykey();
return 0;
}
Convert the above function (and program) for floats:
float square(float num)


Example: Write a function that computes n
k
. Assume k is an integer.
float power(float n,int k)


FILE:functions__power.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Write functions that compute the factorial f(n)=n!, permutation, P(n,k)=n!/(n-k)!, and the
combinatorial, C(n,k)=n!/(n-k)! k!, of two numbers n and k, where n>0, k>0, and n k.
FILE:functions__permutation_combination.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
CODE

8.1. Boolean Functions
C does not support boolean functions directly, however, they can be simulated via integer functions.

Example:

1. Write a function:
int isLower(char ch)
Which returns 1 if ch is a lowercase letter, 0 otherwise.
2. Write another function:
char toUpper(char ch)
Which assumes that the given ch is a lowercase character, and returns its uppercase
equivalent (e.g. if ch is 'b', your function must return 'B')
3. Write main function which reads a character from user, checks whether it is lowercase via
isLower function you wrote above:
if(isLower(ch)==1){
then if it is, prints its uppercase equivalent via toUpper function:
printf("%c",toUpper(ch));
FILE:functions__boolean_functions__isLower_toUpper.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}

8.2. Void Functions
Not all functions must return a value. Consider the following function printing 2x2 square on screen:
void printSquare()
FILE:functions__void_functions__2x2_square.c
Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
9. Pointers And Pointer Arithmetic
9.1. Pointer Operators
A pointer is a variable that is capable to hold a memory address in it. Suppose the declaration of the
integer pointer p:
int *p;
p keeps an address in it. At this address, an integer is stored since it is an integer pointer. In case of
float pointer a,
float *a;
a keeps an address at which a floating number is held. Note that a pointer is a variable too, thus it is
kept in some memory place, i.e., it has some memory address, which is not the same with its value.
Every pointer points to a specific data type except void pointers. Pointer to void is used to hold any
type of pointer.
9.1. Pointer Operators

1. & (address operator): It is a unary operator, and it gives the address of its operand. It can be
applied to objects in memory, it cannot be applied to expressions, constants or register
variables. Suppose the following statements:
2. int *p, c
p = &c;
In the first line we declare two variables, one is an integer, the other is an integer pointer. In
the second line, we assign the address of c as the value of variable p.
3. * (indirection(dereferencing) operator): It is also a unary operator and can be applied to
pointers. By this operator, we can access the variable whose address is kept in the pointer.
You should only access to addresses which was previously allocated, otherwise you may have
some problem. For example:
4. int *p;
*p = 3;
You define an integer pointer p, which has garbage value in it, so in its address there can be
any address. And when you try to access to the address, which is the value of p, you may
probably access an unallocated address.
Example:

FILE:pointers_and_pointer_arithmetic__pointer_operators__sta
r_addresof_use.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPIL
E
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautif
y();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11

#include<stdio.h>

int main(){
int a = 3, b = 2, *ptr, *x, *y;



anykey();
return 0;
}


Book Solution: Help 10. Pointers And Function Arguments
Suppose we have a function, and we want to change two values in it and return them to the caller
part. But only a single value can be returned and there is no direct way to alter a parameter in C
programming language. The way to obtain this effect is to pass pointers to the functions. Suppose
the example of swaping two values which are sent as the parameters.

This is an example where parameters are sent via call-by-value, thus does not work:
FILE:pointers_and_function_arguments__swap_false.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
This is an example where parameters are sent via call-by-reference, thus works:
FILE:pointers_and_function_arguments__swap_true.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE

1

(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
2
3
4
5
6
7
8
9
10
#include<stdio.h>

int main(){



anykey();
return 0;
}

Example: Consider the program, which finds the real roots of a given quadratic equation. At this
time, we want to rewrite it by using a function:
int solve(float a,float b,float c,float *root1, float *root2)
Your function will return the number of real roots (0 if no real roots, 1 if roots are equal, 2 if 2 distinct
real roots)


FILE:pointers_and_function_arguments__quadratic_equation_so
lver.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
11. Arrays
Suppose we want to take N integers, x
i
, from the user and
We want to compute the average of these numbers, where

avg=

N
x
i

i=1
N


FILE:arrays__average.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include<stdio.h>
#define N 5

int main(){
float avg = 0,i;
int no;
for (i = 0; i < N; i++){
scanf("%d",&no);
avg += no;
}
avg /= N;
printf("average:%f\n",avg);
anykey();
return 0;
}



We want to compute the variance of the numbers x
i
, where variance is

var=

N
(x
i
-avg)
2

i=1
N-1
For this time, we need to keep x
i
values since first we need to compute the average value, then use
this value in the variance computation. One way is to keep each number in distinc variables. For
example if N=100, then we need to declare 100 variables. But it is not feasible. The next alternative
way is to group these variables under the same name, where each of them has an unique index.
An array is a group of memory locations. These locations are related by the fact that they have all the
same name and same type. To refer (access) to a particular location, i.e., an element within the array,
specify the name of the array and the position number (index) of the variable in square brackets.


FILE:arrays__variance.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
CODE
We must declare arrays before using them.
int X[100];
float Y[90], Array[10];
float Y[90]; tells the compiler to reserve 90 elements for float array Y, i.e., to allocate 90
memory locations, each of which is capable of storing a float value.
Arrays (their elements) occupy space in the memory, so you must specify the number of
allocations, e.g., 90 for the array Y. You need constant expressions for these numbers. For
example, the following definition is valid:
#define b 3
const int mySize = 2;
int y[a*b+2];
We can use its elements like variables, such as:
float A[10];
A[3] = 2; /* assign 2 to the third element of the
array A */
A[4] = A[3] * 2; /* get the value of the third element
of the array A,
multiply it by 2, then assign the
result into the
fourth element of the array A
*/
A[3]++; /* increment the value of the third
element by 1 */
The index of the first element of the array is zero, i.e., arrays begin with 0
th
element. And the
index of the last element is N-1, where N is the size of the array.
Indices can only be either an integer or an integer expression.
int k[5], i;
for (i = 0; i < 5; i++)
k[i] = i * 2;
k[2*2 - 1] = 3;
k[k[4] / k[1]] = 2;
k[1.5] = 3; /* error occurs */
Elements of the array can be considered as variables, however array name is not a variable.
Suppose we define double NewArray[5];, we have variables NewArray[0], NewArray[1], etc.
But there is no variable with the name of NewArray.
Do not try to access the elements extending the size of an array. Suppose you define an array
as int k[5];, then you should not try to access k[-45], k[-1], k[5], k[22], etc. Note that that is
permitted, but you may have some problems if these are not allocated memory cells.
It is also possible to initialize arrays at the declarations, give the values of elements in a comma
separated list.
int n[4] = {1,2,3,4};
int n[4] = {1,2,3,4,5}; /* too many values (greater than the
size of
the array), it gives compile time
error */
int n[4] = {2,3}; /* fewer initializers, remaining
elements are
initialized by zero
*/
int n[] = {1,2,5,3,7,7,0}; /* it works, the compiler will
create an array
whose size equals to the number
of the
initializers, in this case with
size 7 */
int n[]; /* it gives compile time error*/
Arrays are static structures, which means you set the size of the array in your code and cannot
change its size anymore. In summary you should either specify the array size or initialize the array.


Example: Suppose you have 100 elements with integer data type. You want to control whether these
numbers are symmetric or not. Consider elements are given in a sequence by the user.


FILE:arrays__is_symmetric.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: User enters a sequence of characters. You want to count the lowercase and the uppercase
letters in this sequence. The sequence is finished when % is entered. You should ignore all other
characters.


FILE:arrays__count_uppercase_lowercase.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
3
4
5
6
7
8
9
10

int main(){



anykey();
return 0;
}
Arrays have one important drawback: They cannot be created or used dynamically. For example,
consider the user enters a sequence of decimal numbers but we do not know the size of this
sequence at the beginning of the program (suppose size is also given by the user or the numbers are
taken until the user enters a sentinel value). We can solve this problem by defining very large arrays
and hope the user not to enter the size such that it extends the limit. Suppose the following
examples:
FILE:arrays__size_limit.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
If user enters the size smaller than or equal to 100000, the above code works. If he enters the size
100500, the indices exceeds the ranges, so you may have some problems. Now suppose the user
enters 5 as the size of the arry, then 99995 locations are allocated unnecessarily. Not that defining
arrays with very large sizes is inefficient. So we need dynamic structures. For dynamic arrays, please
refer to Advanced C Topics -> relationship between arrays and pointers dynamic memory
allocation with malloc calloc and realloc

Example: Suppose you want to write a program that takes two polynomials from the user. Perform
addition and multiplication operations on them:
FILE:arrays__polynom_addition_multiplication.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {

1
2
3
4
5
6
7
8

#include<stdio.h>

int main(){



beautify();
}LOAD
DEFAULT
CODE
9
10
anykey();
return 0;
}
12. Passing Arrays To Functions
12.1. Sort
12.2. Binary Search

1. When an array name is passed to a function, what is passed is the address of the initial
element of an array.
2. When a pointer is passed, the address value is passed.
3. Arrays and pointers can be used interchangebly in defining parameters of functions. We do
not need to specify the size of the array in the parameter list unless it is a multidimensional
array.
4. If an address parameter is passed to a function, you can modify the values pointed by this
address and the modifications can be seen after the termination of the function. If you try to
change the value of the parameter, it won' t be seen by the caller part.
5. Functions can also return to pointers, but not arrays! .
Example: You have integers with size n. You want to change all elements which are equal to the
given integer value with another given integer. Write a function that performs this operation, and
returns to the number of the changed numbers
FILE:passing_arrays_to_functions__change_array_values.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}

12.1. Sort
Example: Write a function that sorts a given array:

FILE:passing_arrays_to_functions__sort.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdlib.h>

#define MAX_SIZE 100

void printArray(int arr[], int size){
int i;
for(i=0;i<size;i++){
printf("%d ",arr[i]);
}
printf("n");
}

void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}




int main(){
int array[MAX_SIZE], size, i;
printf("Enter the size of the array:n");
scanf("%d",&size);
if(size<=0 || size > MAX_SIZE){
printf("Error: invalid size. Size must be between
0 and %dn",MAX_SIZE);
return -1;
}
srand(NULL);//initialize random seed
for (i = 0; i < size; i++){
array[i] = rand()%10;
}
printf("array before sort:n");
printArray(array,size);

sort_array(array,size);

printf("array after sort:n");
printArray(array,size);

anykey();
return 0;
}



12.2. Binary Search
Example: Suppose we have a sorted array with size N. Write a function that finds a given number in
this array, and returns the index of its location. If the number is not found, your function should
return -1. Perform search by using binary search algorithm:

FILE:passing_arrays_to_functions__binary_search.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#include <stdlib.h>
#include <stdio.h>

#define MAX_SIZE 100

void printArray(int arr[], int size){
int i;
for(i=0;i<size;i++){
printf("%d ",arr[i]);
}
printf("n");
}

void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}

void sort_array(int arr[], int size){
int i, j;
for (i = 0; i < size; i++)
for (j = i + 1; j < size; j++)
if (arr[i] > arr[j])
swap(&arr[i],&arr[j]);
}






int main(){
int array[MAX_SIZE], size, i,
searchedNumber,searchedNumberIndex;
printf("Enter the size of the array:n");
scanf("%d",&size);

if(size<=0 || size > MAX_SIZE){
printf("Error: invalid size. Size must be between
1 and %dn",MAX_SIZE);
anykey();
return -1;
}

for (i = 0; i < size; i++){
array[i] = rand()%10;
}

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
printf("array before sort:n");
printArray(array,size);

sort_array(array,size);

printf("array after sort:n");
printArray(array,size);

printf("Enter a number for searching within the
array:n");
scanf("%d",&searchedNumber);

searchedNumberIndex =
binary_search(array,size,searchedNumber);

if(searchedNumberIndex==-1){
printf("value not foundn");
}
else{
printf("value found at index
%dn",searchedNumberIndex);
}

anykey();
return 0;
}
12. Passing Arrays To Functions
12.1. Sort
12.2. Binary Search

1. When an array name is passed to a function, what is passed is the address of the initial
element of an array.
2. When a pointer is passed, the address value is passed.
3. Arrays and pointers can be used interchangebly in defining parameters of functions. We do
not need to specify the size of the array in the parameter list unless it is a multidimensional
array.
4. If an address parameter is passed to a function, you can modify the values pointed by this
address and the modifications can be seen after the termination of the function. If you try to
change the value of the parameter, it won' t be seen by the caller part.
5. Functions can also return to pointers, but not arrays! .
Example: You have integers with size n. You want to change all elements which are equal to the
given integer value with another given integer. Write a function that performs this operation, and
returns to the number of the changed numbers
FILE:passing_arrays_to_functions__change_array_values.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
3
4
5
6
7
8
9
10

int main(){



anykey();
return 0;
}

12.1. Sort
Example: Write a function that sorts a given array:

FILE:passing_arrays_to_functions__sort.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#include<stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

void printArray(int arr[], int size){
int i;
for(i=0;i<size;i++){
printf("%d ",arr[i]);
}
printf("n");
}

void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}




int main(){
int array[MAX_SIZE], size, i;
printf("Enter the size of the array:n");
scanf("%d",&size);
if(size<=0 || size > MAX_SIZE){
printf("Error: invalid size. Size must be between
0 and %dn",MAX_SIZE);
return -1;
}
srand(NULL);//initialize random seed
for (i = 0; i < size; i++){
array[i] = rand()%10;
37
38
39
40
41
42
43
44
45
46
47
48
49
}
printf("array before sort:n");
printArray(array,size);

sort_array(array,size);

printf("array after sort:n");
printArray(array,size);

anykey();
return 0;
}



12.2. Binary Search
Example: Suppose we have a sorted array with size N. Write a function that finds a given number in
this array, and returns the index of its location. If the number is not found, your function should
return -1. Perform search by using binary search algorithm:

FILE:passing_arrays_to_functions__binary_search.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#include <stdlib.h>
#include <stdio.h>

#define MAX_SIZE 100

void printArray(int arr[], int size){
int i;
for(i=0;i<size;i++){
printf("%d ",arr[i]);
}
printf("n");
}

void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}

void sort_array(int arr[], int size){
int i, j;
for (i = 0; i < size; i++)
for (j = i + 1; j < size; j++)
if (arr[i] > arr[j])
swap(&arr[i],&arr[j]);
}

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72





int main(){
int array[MAX_SIZE], size, i,
searchedNumber,searchedNumberIndex;
printf("Enter the size of the array:n");
scanf("%d",&size);

if(size<=0 || size > MAX_SIZE){
printf("Error: invalid size. Size must be between
1 and %dn",MAX_SIZE);
anykey();
return -1;
}

for (i = 0; i < size; i++){
array[i] = rand()%10;
}

printf("array before sort:n");
printArray(array,size);

sort_array(array,size);

printf("array after sort:n");
printArray(array,size);

printf("Enter a number for searching within the
array:n");
scanf("%d",&searchedNumber);

searchedNumberIndex =
binary_search(array,size,searchedNumber);

if(searchedNumberIndex==-1){
printf("value not foundn");
}
else{
printf("value found at index
%dn",searchedNumberIndex);
}

anykey();
return 0;
}
14. Multidimensional Arrays
We can define multidimensional arrays. In the two dimension, multidimensional arrays provide us to
think of the memory locations as a table. Actually it is not possible to keep a table format for
memory locations and two dimensional array is an one dimensioanl array, whose elements are
sorted. In the declaration, we specify all dimensions of the multidimensional array. Suppose the
following two dimensional array declarations:
int a[3][4]; /* You can think of array a with
3 rows
and 4 columns, but actually 12
consecutive
locations are allocated for
the elements
of a */
int b[3][5] = {{0,1,2,3,4},{3}}; /* It is also possible to
initialize the
multidimensional arrays, all
uninitialized
locations are set to zero as
in the single
dimensional arrays */
int c[][5] = {{1,2,3,3,2},{3,4,4,3,2}}; /* First dimension is
set to 2 in this case */
int d[][] = {{1,2},{3,4},{5,6}}; /* It is illegal, only the first
dimension
can be free, i.e., unspecified
*/
int e[3][4][5]; /* It is a three dimensional
array, actually
it consists of 60 consecutive
int-sized
locations*/
If a two dimensional array is to be passed to a function, what is passed is a pointer to an array of
rows. The parameter declaration in the function must include the size of dimensions except that of
the first one. Suppose the following function declarations and function calls.
void func1(int a[][]){} /* it is invalid, you need to
specify at least
the second dimension*/
void func2(int a[3][4]){} /* valid */
void func3(int a[][4]){} /* valid */
-------------------------------------------------------
int a[3][7], b[5][4], c[3][4];
func3(a); /* will not cause a syntax error,
*/
/* but will do something
completely different */
func3(b); /* valid */
func3(c); /* valid */
Example: Consider a block of 10 apartment houses, each of which contains 6 apartment flats. First,
we want to keep the number of people in each flat, and then we want to compute the average
number of people that live in each apartment house.


FILE:multidimensional_arrays__apartment_block.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Example: Consider we have 5 classes, each of which has 30 students. These 30 students takes 10
course (all students in different classes take the same courses).
1. Write a function that takes grades of each student from the user.
2. Write a function that computes the average of 10 courses.
3. Write a function that assigns letter grades to the given grades of the students (90 - 100: A, 80
- 89: B, 70 - 79: C, 60 - 69: D, 0 - 59: F, and assume all grades are given between 0 and 100).
FILE:multidimensional_arrays__grades.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
Remember arrays have a major drawback: They cannot be created and used dynamically. Please
refer to advanced c topics section for dynamic multidimensional arrays.

Example: We have two two-dimensional matrices whose dimensions are 2x4. Write a function for
computing the sum of these two matrices. Write another function to compute the transpose of a give
matrix:


FILE:multidimensional_arrays__matrix_sum_transpose.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
3
4
5
6
7
8
9
10

int main(){



anykey();
return 0;
}
15. Structures
15.1. Valid Operators
15.2. Array Of Structures And Structure Pointers
15.3. Typedef
15.4. Structure And Functions
A structure is a collection of one or more variables, whose data types can be different, under a single
name. They are derived data types.
Example: Suppose you want to keep lines in your program. To this end, you want to create a line by
taking its two endpoints. You also want to perform the swapping operations on some points and you
want to calculate the length of a given line.
FILE:structures__point_line.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}



It is also possible to nest the structures as you can see above. Consider also the following examples:
struct point{
int x;
int y;
};
struct line{
struct point p1;
struct point p2;
};
struct circle{
struct point center;
float radius;
};

15.1. Valid Operators

1. You can access the members of a structure. To access a member:
structure_name.member_name
For example:
struct point{
float x;
float y;
};
struct point p, *p_ptr, p_arr[10];

p_ptr=&p;
p.x = 4;
(*p_ptr).y=5;
p_ptr->y=5; // this is the same as above statement.
*p_ptr.y=5; // illegal. You must use one of the above two

p_arr[2].x=12;
p_arr[0].y=4.5;
2. It is valid to copy the structure variables of the same data type. The following copying
operations are all valid.
3. struct point{
4. int X, Y;
5. };
6. struct line{
7. struct point P1, P2;
8. };
9.
10. struct line L, K;
11. struct point p1;
12.
13. L.P1.X = 3;
14. L.P1.Y = 4;
15. p1.X = 5;
16. p1.Y = 7;
17. L.P2 = p1;
18. K = L;
L.P2 = K.P1;
19. Taking the address of a structure variable is valid

15.2. Array Of Structures And Structure Pointers
As you recall from the point example above, struct pointer and array of structures is valid
15.3. Typedef
p>It creates new data types. For example:
typedef int length;
makes the name of length a synonym for int. And both declarations of a variable with the integer
data type are valid.
int len1;
length len2;
But typedef is usually necessary for complicated types.
struct polynom{
int degree;
float coeff[100];
};

typedef struct polynom poly;
/* from now on
for declaring a polynom variable,
you can both use:
struct polynom p;
or
poly p;
*/

15.4. Structure And Functions

1. You pass the entire structures or members (call by value).
2. You pass the address of the structure (call by reference).
3. Your function can return a structure or pointer to structure.
4. Structure arrays are possible
Example: You are going to write a program which reads name, surname and age of a number of
employees. Your program sorts employees in ascending order according to their age and prints them.
1. Define struct employee consisting of name (string), surname (string) and age (int)
2. Use typedef to define type Employee as struct employee
3. Write functions:
1. Employee readEmployee(): reads an employee from the user and returns it
2. void printEmployee(Employee e): prints the given employee on screen
3. void sortEmployees(Employee employees[], int numEmployees): sorts given
employees
4. void swapEmployees(Employee *a, Employee *b): swaps employees (used within
sort function)
5. main function: defines Employee employees[50] array, reads number of employees,
reads employees to array one by one via utilizing readEmployee function, calls
sortEmployees function and prints them one by one via printEmployee function.
6. after finishing this code, write a second version of readEmployee:
void readEmployee(Employee *eptr)
which takes an employee pointer and reads its parameters from the user (as
(*eptr).age, you can use eptr->age)
FILE:structures__structure_and_functions__employees.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>

int main(){



anykey();
return 0;
}
16. Advanced Topics In C
16.1. Additional Variable Types
16.2. Macro Substitution
16.3. Additional Constants
16.4. Bitwise Operators
16.5. If Integers As Booleans
16.6. If Advanced Not Operator
16.7. For Infinite Loop
16.8. For Double Counter
16.9. Do While
16.10. Function Scopes
16.11. Pointer Addition Subtraction
16.12. Pointers And Dynamic Arrays Malloc Calloc Realloc
16.13. Advanced String Functions
16.14. Array Of Pointers
16.15. Pointers To Pointers
16.16. When Do You Use Multidimensional Arrays Array Of Pointers And Pointers Of Pointers
16.17. File Operations

16.1. Additional Variable Types
for further reference: http://en.wikipedia.org/wiki/Scanf
FILE:advanced_c_topics__additional_variable_types.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {

1
2
3
4
5
6
7

#include<stdio.h>

int main(){
/* type bytes bits min value
max value memory address capability
short int 2 16 -32,768 -
beautify();
}LOAD
DEFAULT
CODE
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
> +32,767 (32kb)
unsigned short int 2 16 0 -
> +65,535 (64Kb)
unsigned int 4 32 0 -
> +4,294,967,295 ( 4Gb)
int 4 32 -2,147,483,648 -
> +2,147,483,647 ( 2Gb)
long int 4 32 -2,147,483,648 -
> +2,147,483,647 ( 2Gb)
signed char 1 8 -128 -
> +127
unsigned char 1 8 0 -
> +255
float 4 32 3.4 * (10^-38) -
> 3.4 * (10^+38) and -3.4 * (10^-38) -> -3.4 *
(10^+38) (excludes exact 0)
double 8 64 1.7 * (10^-308) -
> 1.7 * (10^+308) and -1.7 * (10^-308) -> -1.7 *
(10^+308) (excludes exact 0)
long double 12 96 3.4 * (10^-4932) -
> 1.1 * (10^+4932) and -3.4 * (10^-4932) -> -1.1 *
(10^+4932) (excludes exact 0)
*/

short s;
int i;
long l;
unsigned int ui;
double d;
long double lod;

printf("Enter a short integer between -32,768 ->
+32,767\n");
scanf("%d",&s);
printf("short: %d\n",s);

printf("Enter an integer between -2,147,483,648 ->
+2,147,483,647\n");
scanf("%d",&i);
printf("int: %d\n",i);
printf("int octal: %o\n",i);
printf("int hexadecimal: %x\n",i);

printf("Enter a long integer between -2,147,483,648
-> +2,147,483,647\n");
scanf("%ld",&l);
printf("long: %ld\n",l);

printf("Enter an unsigned integer between 0 ->
+4,294,967,295\n");
scanf("%u",&ui);
printf("unsigned int: %u\n",ui);

printf("Enter a double (float with bigger range)
between 1.7*10^-308 to 1.7*10^308 or -1.7*10^-308 to -
1.7*10^308 (cannot give exact 0 similar to float)\n");
scanf("%lf",&d);
printf("double: %lf\n",d);

printf("Enter a long double (float with even bigger
range than double) 3.4*10^-4932 to 3.4*10^4932 or -
3.4*10^-4932 to -3.4*10^4932 (cannot give exact 0 similar
to float and double)\n");
scanf("%Lf",&lod);
printf("long double: %Lf\n",lod);

anykey();
return 0;
}

16.2. Macro Substitution
Remember
#define PI 3.14
in the compile time all PI' s are substituted with 3.14. We can use it to replace a token by an arbitrary
sequence of characters. We call them macro and the general format is as follows:
#define name replacement_text
where name has the form of the identifier name. It is also possible to define macros with arguments.
To compute the square of a given number, you can define a macro:
#define square(x) (x)*(x)
In this example parentheses are important to prevent the misinterpretations. In your program you
use this macro as:
a = square(3);
b = square(a + 3 * b);
Or you can define a maximum operation, which finds the maximum of given two numbers as:
#define max(A,B) (((A) > (B)) ? (A) : (B))
In your program, it can be used as z=max(p+q,r+s); Do not forget that it is just a text substitution,
which is performed at the compile time.
16.3. Additional Constants

FILE:advanced_c_topics__additional_constants__const.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13

#include<stdio.h>

int main(){
// value of variable pi cannot be altered later:
const float pi = 3.141592653589793;

// following will give error:
pi=4.2;

anykey();
return 0;
}
FILE:advanced_c_topics__additional_constants__enum.c
Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include<stdio.h>

// values are assigned starting from 0 (0,1 in this
case):
enum boolean{FALSE,TRUE};

int main(){
enum boolean b,b2;;
b=FALSE; // b becomes 0
b2=TRUE; // b2 becomes 1

anykey();
return 0;
}
FILE:advanced_c_topics__additional_constants__enum2.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMP
ILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-
Y) {
beaut
ify();
}LOAD
DEFAUL
T
CODE


1

2

3

4

5

6

7

8

9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1

#include<stdio.h>

// here values are assigned starting from 1:
enum
month{JANUARY=1,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEP
TEMBER,OCTOBER,NOVEMBER,DECEMBER};

int main(){
enum month m;
int k;
m=FEBRUARY;
printf("m: %d\n",m);
m=JUNE;
printf("m: %d\n",m);

// enums can be used with integers also
k=MARCH;
printf("k: %d\n",k);

anykey();
return 0;
}
7
1
8
1
9
2
0
2
1

16.4. Bitwise Operators

Table 3: Bitwise operators
& bitwise and
| bitwise or
^ bitwise exclusive or
<< bitwise left shift
>> bitwise right shift
~ bitwise one's complement (unary operator)
FILE:advanced_c_topics__bitwise_operators__examples.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include<stdio.h>

int main(){
int a, b, c;
a = 10; /* a = 1010*/
b = 86; /* b = 1010110*/

c = a & b; /*c = 0000010 = 2*/
printf("c:%d\n",c);
c = a | b; /*c = 1011110 = 94*/
printf("c:%d\n",c);
c = a ^ b; /*c = 1011100 = 92*/
printf("c:%d\n",c);
c = b << 1; /*c = 10101100 = 172, it is same
as b*2*/
printf("c:%d\n",c);
c = b << 2; /*c = 101011000 = 344, it is same
as b*2^2*/
printf("c:%d\n",c);
c = b >> 1; /*c = 101011 = 43, it is same as
b/2*/
printf("c:%d\n",c);
25
26
27
28
c = b >> 2; /*c = 10101 = 21, it is same as
b/2^2*/
printf("c:%d\n",c);
c = ~b; /*c = -87*/
printf("c:%d\n",c);

anykey();
return 0;
}

16.5. If Integers As Booleans
A boolean variable is a variable which takes logic values, namely true or false. However, C language
does not have boolean variable support.

C language uses integers as boolean variables. An integer with value 0 is assumed to be false, and an
integer with any value except 0 is assumed to be true

check the following code:
FILE:control_structures__integers_as_booleans__boolfun.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include<stdio.h>

int main(){
int x;
if(1){
printf("This text will always be printed
(1)n");
}
if(0){
printf("This text will never be printed
(0)n");
}
if(5){
printf("This text will always be printed
(5)n");
}
if(-45){
printf("This text will always be printed (-
45)n");
}
x=0;
if(x){
printf("This text will not be printed
(x=0)n");
}
x=1;
if(x){
printf("This text will be printed (x=1)n");
}
printf("Enter x:n");
32
33
34
35
36
scanf("%d",&x);

if(x){
printf("This text will be printed if x is
NOT 0, x:%dn",x);
}

anykey();
return 0;
}

In other words,
if(x!=0){
printf("x is not zeron");
}
or
if(x){
printf("x is not zeron");
}
are exactly the same.
16.6. If Advanced Not Operator
Not operator can be used with the boolean mechanism:
if(!x){
printf("x is zero");
}
Some additional tricks: Guess what the following program will print:
FILE:control_structures__not_operator__fun.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12

#include<stdio.h>

int main(){

int x=1,y=0,z=5;

printf("!x:%d !y:%d !z:%dn",!x,!y,!z);

anykey();
return 0;
}

16.7. For Infinite Loop
In the for loop, all expressions are optional, but semicolon must be used. But the following loop
causes an infinite loop which means the loop is executed forever (avoid infinite loops):
FILE:repetition_statements__for__infinite_loop.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13

#include<stdio.h>

int main(){
int i;

for ( ; ; ){
printf("This will be printed infinitely. Close
the window to terminaten");
}

anykey();
return 0;
}

16.8. For Double Counter
Double counter example:
FILE:repetition_statements__for__double_counter.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13

#include<stdio.h>

int main(){
int i,j;

for (i = 1, j = 100; i <= 100; i++, j--){
printf("i:%d j:%dn",i,j);
}

anykey();
return 0;
}

16.9. Do While
While and for loops test the termination condition at the top, whereas do-while tests it at the
bottom after a pass through the loop body. The body of the do-while loop is always executed at least
once (break statement works for do-while also). Example: Write a program that computes the area
of the square. At the end of each computation, your program should ask the user whether he wants
to continue or not, and exits if the user presses q/Q key. Otherwise it continues to process.
FILE:repetition_statements__do_while__square_area.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO

1
2
3
4
5

#include<stdio.h>

int main(){

(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
6
7
8
9
10


anykey();
return 0;
}

16.10. Function Scopes

A variable has a scope such that this variable is only defined in this scope. There are three different
scopes:
1. Block Scope: Any block contain variable declarations, which must be defined at the beginning
of a block. You can use these variables only in the block, where they are defined. Some
examples:
2. Function Scope: The variables defined at the beginning of a function has function scope.
These variables are called local variables. They can be used anywhere in the function where
they appear, and cnnot be used outside the function body.
3. File Scope: The variables declared outside any function has file scope. They can be used in all
functions from the point at which the variable is declared until the end of file. These are
called global variables. But unless it is necessary, avoid using global variables in your
program.
4. double G; /* G is the global variable */
5. int function1(){
6. int a; /* a is the local variable */
7. if (a < 0){
8. float b; /* b has block scope, and can be used
only in this if */
9. }
10. for (a = 1; a < 100; a++){
11. char c; /* c has block scope, and can be used
only in this for */
12. }
}
If a variable is used in a code, it is searched as the following order: 1) In its block, 2) Among the local
variables, 3) Among the global variables. Note that variables with block or function scope have
garbage value when they are declared, unless they are initialized. On the other hand, global variables
are initialized with zero in the absence of initializations.
Example: What is the output of the program?


FILE:functions__scope_example.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-

1
2

#include<stdio.h>
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44


int a = 5, b = 3;
float c = 10;

first(float a, float b, int ch){
printf("first #1 a = %f, b = %f, c = %f, ch =
%dn",(float)a,b,c,ch);
a = b + ch;
c--;
return (a + b--);
}
float second(int a, float c){
int ch = 2;
printf("second #1 a = %f, b = %d, c = %f, ch =
%dn",(float)a,b,c,ch);
b = first(b,c,ch);
printf("second #2 a = %f, b = %d, c = %f, ch =
%dn",(float)a,b,c,ch);
return (b * c);
}
main(){
float b = 5.99, ch = 1.2;
printf("main #1 a = %f, b = %f, c = %f, ch =
%dn",(float)a,b,c,(int)ch);
a = first(ch,c,b);
printf("main #2 a = %f, b = %f, c = %f, ch =
%dn",(float)a,b,c,(int)ch);
ch = second(c,b);
printf("main #3 a = %f, b = %f, c = %f, ch =
%dn",(float)a,b,c,(int)ch);
return 0;
}

/*
Output is:
main #1 a = 5.00, b = 5.99, c = 10.00, ch = 1
first #1 a = 1.20, b = 10.00, c = 10.00, ch = 5
main #2 a = 25.00, b = 5.99, c = 9.00, ch = 1
second #1 a = 9.00, b = 3, c = 5.99, ch = 2
first #1 a = 3.00, b = 5.99, c = 9.00, ch = 2
second #2 a = 9.00, b = 13, c = 5.99, ch = 2
main #3 a = 25.00, b = 5.99, c = 8.00, ch = 77
*/





16.11. Pointer Addition Subtraction
We can also use addition and subtraction operator with pointers.

FILE:pointers_and_pointer_arithmetic__pointer_operators__addi
tion_subtraction.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPI
LE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautif
y();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11

#include<stdio.h>

int main(){
int a = 3, *x, *y;



anykey();
return 0;
}
Book Solution: Help
16.12. Pointers And Dynamic Arrays Malloc Calloc Realloc

When we declare int a[10];, a block consists of 10 consecutive places, each is capable of storing an
integer, is allocated. After this declaration, we cannot change the size of the allocated block, i.e. we
can neither expand the block nor shrink it. Our aim is to allocate a block in the memory such that its
size can be changed in the program execution.
To this end, let us first examine the relationship between pointers and arrays and their notations.
Suppose the following declarations:
int myArray[10];
int *myPointer;
We know that myArray is the name of the 10 individual elements, it is NOT a variable. Actually
myArray (the name of an array) is a synonym for the address of the initial element of an array, &a[0].
We know that myPointer is a variable that is capable of storing an address in it. Thus, if we want to
store the address of the first element of myArray into myPointer, the following two statements are
equivalent:
myPointer = &myArray[0];
myPointer = myArray;
So you can use the notations of pointers and arrays interchangebly. The following usages are
equivalent:
myArray[i] *(myArray+i)
myArray+i &myArray[i]
myPointer[i] *(myPointer+i)
myPointer+i &myPointer[i]
Please remember their differences again. A pointer is a variable, i.e., it is kept in some memory
locations. Thus myPointer=myArray or myPointer++ are legal statements. But array name is not a
variable and myArray=myPointer or myArray++ are ILLEGAL statements. And also remember that we
should not access the memory locations that are not allocated before. This rule is valid for both
arrays and pointers.
Exercise: Trace the following code and observe the consequence of each statement.

FILE:advanced_c_topics__relationship_between_arrays_and_pointer
s__dynamic_memory_allocation_with_malloc_calloc_and_realloc__poi
nter_array.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)CO
MPIL
E
(Ctrl-
F7)
UND
O
(Ctrl-
Z)RE
DO
(Ctrl-
Y) {
be
autify
();
}LOA
D
DEFA
ULT
CODE


1

2

3

4

5

6

7

8

9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2

#include<stdio.h>

int main(){
int a[] = {2, 20, 3, 1, -1, -6}, *p, t;
p = &a[0]; /* In p is the address of the
initial element of a */
printf("p:%d a:%d &a[0]:%d a:%d\n",p,a,&a[0],a);
t = *p; /* t becomes 2 */
printf("t:%d\n",t);
t = *(p + 1); /* t becomes 20 */
printf("t:%d\n",t);
p = p + 3; /* In p is the address of the third
element of a*/
printf("p:%d\n",p);
t = *p; /* t becomes 1 */
printf("t:%d\n",t);
t = a[2]; /* t becomes 3 */
printf("t:%d\n",t);
t = *(a + 2); /* t becomes 3 */
printf("t:%d\n",t);
p = a; /* In p is the address of the
initial element of a */
printf("p:%d\n",p);
p++; /* Increments the value of p */
printf("p:%d\n",p);
t = *p; /* t becomes 20 */
printf("t:%d\n",t);
t = p[2]; /* t becomes 1 */
printf("t:%d\n",t);
t = p[-1]; /* t becomes 2 (t can be 3 at other
compilers, which convert negative indexes to its positive
counterpart) */
printf("t:%d\n",t);
a = p; /* illegal, since a is not the
variable, comment out this line for successful compile*/
a++; /* illegal, since a is not the
variable, comment out this line for successful compile*/
anykey();
return 0;
}
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
3
3
3
4
So we have seen that we can use arrays and pointers interchangebly. Remember our problem, we
want to change the size of the allocated block during the execution of our program. In the
declaration of an array, an appropriate memory block is allocated implicitly and we cannot change its
size. It is possible to change the size of an allocated block only we perform our allocations explicitly.
There are three types of allocation functions defined in stdlib.h.
1. malloc: It allocates a block of bytes from memory. The size of the allocated block is given as
the argument to the function. On success, it returns the beginning address of the newly
allocated block. It returns NULL on error, e.g., if there is not enough memory.
2. int *a;
a = (int *)malloc(8 * sizeof(int));
In this example, the size of the block is 8*sizeof(int), which means we allocate a block in
which we can keep 8 integers. Note that the size of the integer or any data type varies from
computer to computer. sizeof(int) returns the size of the specified argument in bytes, in our
example it returns how much byte is necessary to keep an integer in the computer which our
program runs. The result of this function may be different for different computers. There are
other malloc examples:
double *numbers, char *letters;
numbers = (double *)malloc(348 * sizeof(double));
letters = (char *)malloc(100 * sizeof(char));
3. calloc: It allocates a memory block like malloc, the difference is that calloc sets the memory
to zero. The syntax of calloc is illustrated in the following example:
4. long *elements;
elements = (long *)calloc(348, sizeof(long));
5. realloc: It adjusts the size of the allocated block to its new size, copying the contents to a
new location, if necessary. On success, it returns the address of the beginning of the
reallocated block, which might be different of the original block. On failure, realloc function
returns NULL.
vector = (long *)realloc(vector, 4 * sizeof(long));
It adjusts the size of vector to 4 and returns the beginning address of a newly allocated block.
Realloc is applied to the blocks either previously obtained by malloc/calloc/realloc or set to
NULL. Otherwise undefined behaviors may occur.
Example: Write a program that takes the decimal numbers from the user and computes their
average. The number of decimal numbers is specified by the user at the beginning of the program. In
this example, we do not know the size of the numbers when we write our program. Therefore we
allocate space for the numbers in the execution, which requires explicit allocation.



FILE:advanced_c_topics__relationship_between_arrays_and_pointer
s__dynamic_memory_allocation_with_malloc_calloc_and_realloc__mal
loc.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)CO
MPIL
E
(Ctrl-
F7)
UND
O
(Ctrl-
Z)RED
O
(Ctrl-
Y) {
bea
utify()
;
}LOA
D
DEFA
ULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#include<stdio.h>
#include<stdlib.h>

int main(){
int size, i;
float *elements, avg;
printf("Enter the amount of the numbers:");
scanf("%d",&size);
if (size <= 0){
printf("The size must be positive\n");
exit(1);
}
elements = (float *)malloc(size * sizeof(float));
if (elements == NULL){
printf("Not enough memory space\n");
exit(1);
}
for (i = 0; i < size; i++)
scanf("%f",&elements[i]);
avg = 0.0;
for (i = 0; i < size; i++)
avg += elements[i];
avg /= size;
free(elements);
anykey();
return 0;
}
We know that variables are deallocated, i.e., freed, when we exit their scopes. In this example
variables size, i, elements adn avg are deallocated at the end of the program. Since we allocate the
memory block explicitly, we should also perform the deallocation of this block explicitly. free function
deallocates a memory block allocated by a previous allocation function, i.e., malloc, calloc or realloc.
If you try to free the memory block that was not allocated before, undefined behavior occurs.
Example: Write a program that takes the decimal numbers from the user until a negative value is
entered and computes their average. In this example, we do not know the size of the necessary block
neither before the executin nor during the execution. We can only know the exact size when a
negative value is entered. Therefore in this example, we assume the size of the block is 0 at the
beginning of the program, then we expand the block incremently. So we use realloc function.



FILE:advanced_c_topics__relationship_between_arrays_and_pointer
s__dynamic_memory_allocation_with_malloc_calloc_and_realloc__rea
lloc.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)CO
MPIL
E
(Ctrl-
F7)
UND
O
(Ctrl-
Z)RED
O
(Ctrl-
Y) {
bea
utify()
;
}LOA
D
DEFA
ULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include<stdio.h>
#include<stdlib.h>

int main(){
int counter = 0, i;
float *elements, avg, temp;
elements = NULL; /* This is necessary to
use the realloc
function in a
safe way later */
scanf("%f",&temp);
while (temp >= 0){
counter++;
elements = (float *)realloc(elements,counter *
sizeof(float));
if (elements == NULL){
printf("Error in the allocation\n");
exit(1);
}
elements[counter - 1] = temp;
scanf("%f",&temp);
}
if (counter == 0)
printf("There is no number\n");
else{
for (i = 0; i < counter; i++)
avg += elements[i];
avg / = counter;
}
free(elements);

anykey();
return 0;
}


Do not forget that, crashes are related overflowing an allocated chunk, using realloc function without
initializing its address argument or freeing the same pointer twice. Also accessing the unallocated
memory place may result in crashes. Consider the following statements and their validity.
#include <stdlib.h>
int main(){
int *a = NULL, *b, *c, *d, *e;
a = (int *)realloc(a, 3*sizeof(int)); /* (1) */
b = (int *)realloc(b, 3*sizeof(int)); /* (2) */
c = (int *)realloc(a, 3*sizeof(int)); /* (3) */
d = (int *)malloc(3*sizeof(int)); /* (4) */
d = (int *)realloc(d, 8*sizeof(int)); /* (5) */
d = (int *)realloc(d, 1*sizeof(int)); /* (6) */
free(c); /* (7) */
free(a); /* (8) */
free(a); /* (9) */
free(e); /* (10) */
d = (int *)malloc(50*sizeof(int)); /* (11) */
free(d); /* (12) */
d = (int *)malloc(50*sizeof(int)); /* (13) */
free(d); /* (14) */
return 0;
}
Let us examine each case.
(1): it is safe, since a was initialized by NULL in the declaration
(2): it results in crashes. Variable b was neither initialized by NULL nor allocated previously
(3): it is safe since variable a was allocated previosly, in (1). Be careful of this statement, the variable
a keeps the address, which indicates the block to be expanded. On the other hand, the variable c just
keeps the return value of the realloc function.
(4): it is safe, d points to an allocated block of 3 integers after this statement.
(5): it makes the size of the allocated block indicated by d eight. And it is safe since variable d was
allocated by malloc in (4) previously.
(6): it makes the size of the allocated block indicated by d one. And it is safe since variable d was
allocated by realloc in (5) previously.
(7): it is safe, since c was allocated before, in (3).
(8): it is safe, since a was allocated before, in (1).
(9): it is not safe, since a was freed in (8), and has not been allocated again. So do not try to
deallocate the unallocated memory locations.
(10): it is not safe, since variable e was not allocated before.
(11): it is safe, it is just an allocation. But the drawback of this allocation is that: we allocate some
space and we keep the starting address of this space in the variable d. When we allocate this variable
again, it begins to keep the address of the newly allocated space, and we cannot access the space
allocated previously any more.
(12): it is safe, since d keeps the adress of the allocated memory location, where allocation was done
in (11).
(13): it is safe, it is just an allocation.
(14): it is safe, since we allocate the variable d in (13).
In general, a pointer can be initialized as:
1. by using NULL.
2. int *a; long *b = NULL;
a = NULL;
3. by using the expressions involving the addresses of previously defined data of the
appropriate type.
4. double *a, b[100], c;
5. a = &c;
a = b + 2;
6. by using allocation functions, malloc, realloc or calloc.
The valid pointer operations are summarized as follows:
1. Assignment of addresses or pointers of the same type.
2. Adding or subtracting a pointer and an integer.
3. Subtracting two pointers of the same data type.
4. float *a, *b, c[10], t;
5. a = c; b = c + 3;
t = b - a; /* in this example, t becomes 3 */
6. Comparing two pointers. Suppose we have pointers p and q. p<q gives true if p keeps an
address smaller than that of kept in q. In the above example a<b gives true and a>b gives
false. It is also possible to use <=,>=,!=,== with pointers.

16.13. Advanced String Functions
char *strtok(char *S1, char *S2): scans S1 for the first token not contained in S2. In the firts call, it
returns a poinetr to the first character of the first token in S1 and writes a null character into S1
immediately following the returned token. Be careful in using this function, since the string S1 is
changed after calling this function.
FILE:advanced_c_topics__strtok.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxsize 100

int main(){
char S[maxsize], *temp;
char *token = " ,\t";
int *numbers = NULL, i = 0;
gets(s);
temp = strtok(s,token);
while (temp != NULL){
numbers = (int *)realloc(numbers,(i + 1) *
16
17
18
19
20
21
22
23
24
sizeof(int));
numbers[i] = atoi(temp);
i++;
temp = strtok(NULL,token);
}
free(temp);
free(numbers);

anykey();
return 0;
}
EXERCISE: What does the following functions do?
HINTS:
The ascii code of '\0' is 0
The precedence of ++ is higher than *


FILE:advanced_c_topics__advanced_string_functions__exercise
.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify()
;
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#include<stdio.h>

int f1(char *str){
int i=-1;
while(str[++i]);
return i;
}


void f2(char *s1, char* s2){
while(*s1++=*s2++);
}

void f3( char* s1, char* s2 ){
while (*s1) s1++;
while (*s1++ = *s2++);
}


int main(){

anykey();
return 0;
}


16.14. Array Of Pointers

Suppose there are 100 students in the class and we want to keep their names. So we can define a
two-dimensional character array with dimensions 100 MAX, where MAX is the maximum length of a
name possible. So the declaration is as follows providing a constant MAX was defined before.
char names[100][MAX];
In this case there is a waste of space since the length of the names vary. So instead of keeping each
name in an array with size MAX, we can allocate a memory block with an appropriate size and keeps
the starting address of this block in a pointer. Thus we have an array with size 100 and in each of its
elements an address is kept. The declaration of this array is as follows:
char *names[100];
This array can be considered as a two-dimensional array whose first dimension is fixed and second
dimension is free. And for the second dimension MEMORY ALLOCATION must be done! Suppose we
take the names from the user and store them in names array.
FILE:advanced_c_topics__array_of_pointers__read_names.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include<stdio.h>
#include <stdlib.h>

#define NUM_NAMES 5
#define MAX_NAME_LENGTH 50

int main(){
char temp[MAX_NAME_LENGTH+1], *names[NUM_NAMES];
int i;
printf("Enter %d names:\n",NUM_NAMES);
for (i = 0; i < NUM_NAMES; i++){
gets(temp);
names[i] = (char *)malloc((strlen(temp) +
1)*sizeof(char));
strcpy(names[i],temp);
}

printf("names read:\n");
for(i=0; i<NUM_NAMES;i++){
printf("%s\n",names[i]);
}

// we must deallocate the memory:
for(i=0; i<NUM_NAMES;i++){
free(names[i]);
}

anykey();
return 0;
}

Note that we can also use calloc or realloc function in the memory allocation.
names[4] = (char *)calloc(40, sizeof(char));
names[57] = (char *)realloc(names[57],50 * sizeof(char));
Example: Suppose we want to keep our payments for each month.
1. Write a function that takes the payments from the user. For each month, the number of
payments is read first.
2. Write a function that computes and returns the total payment for each month.
FILE:advanced_c_topics__array_of_pointers__payments.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#include<stdio.h>
#include <stdlib.h>

#define NUM_MONTHS 12

int *readPayments(int *payments[NUM_MONTHS]){
int *numberOfPayments = (int*)malloc(NUM_MONTHS *
sizeof(int)), i, j, temp;
for (i = 0; i < NUM_MONTHS; i++){
printf("Enter the number of payments of month %d:
",i+1);
scanf("%d",&temp);
if (temp < 0){
printf("The minimum number of payment can be
zero\n");
temp = 0;
}
numberOfPayments[i] = temp;
if (numberOfPayments[i] != 0){

payments[i] = (int
*)malloc(numberOfPayments[i] * sizeof(int));
for (j = 0; j < numberOfPayments[i]; j++){
printf("Enter payment %d of month %d:
",j+1,i+1);
scanf("%ld",&payments[i][j]);
}
}
}
return numberOfPayments;
}
int *computeTotalPayments(int *payments[NUM_MONTHS], int
*no){
int *total = (int *)malloc(NUM_MONTHS * sizeof(int));
int i, j;
for (i = 0; i < NUM_MONTHS; i++){
total[i] = 0;
for (j = 0; j < no[i]; j++)
total[i] += payments[i][j];
}
return total;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
}

void printArray(int arr[],int size){
int i;
for(i=0;i<size;i++){
printf("%d ",arr[i]);
}
printf("\n");
}

int main(){
int
*payments[NUM_MONTHS],*numberOfPayments,*totalPayments,i;
numberOfPayments = readPayments(payments);
totalPayments =
computeTotalPayments(payments,numberOfPayments);

printf("number of payments each month:\n");
printArray(numberOfPayments,12);

printf("total payments each month:\n");
printArray(totalPayments,12);

free(numberOfPayments);
free(totalPayments);
for(i=0;i<NUM_MONTHS;i++){
free(payments[i]);
}

anykey();
return 0;
}
Note that it is also possible to define pointers to arrays. In this case, the second dimension is fixed
and the first dimension is free. The declaration, allocation and deallocation of pointers to arrays with
type long are follows:
long (*powers)[10];
powers = (*(long)[10])malloc(8 * sizeof(long[10]));
powers = (*(long)[10])realloc(powers,4 * sizeof(long[10]));
free(powers);

16.15. Pointers To Pointers

Suppose we want to write matrix multiplication, remember we defined a matrix as a two-
dimensional array last week. But we do not want to restrict ourselves for fixed dimensions, i.e., we
want the first and the second dimensions to be free. Thus we should allocate memory blocks for both
dimensions explicitly. In the same manner the deallocation of both dimensions is our responsibility.
Suppose the following declaration:
char **myPointer;
myPointer is a variable that keeps a single value in it. This value is an address value, let us call this
address M1. When we access the memory location with address M1, we expect to get another
address value, say M2. And when we access the memory location with address M2, we expect to
obtain a value with a character data type.
Note that if we want to create a two-dimensional structure in a function and to return it at the end of
the function, we can only use pointers to pointers as in the allocation, multiplication, etc. functions in
the following examples.
Example: Perform the following operations on matrices with varied row and column size.
1. Allocate necessary space for a matrix with the specified dimensions.
2. Deallocate the given matrix
3. Print the contents of the matrix in a tabular format.
4. Add two matrices and return the resultant matrix.
5. Multiply two matrices return the resultant matrix.
6. Find the transpose of a given matrix.
7. Generate random elements for a given matrix. Use rand function to generate the integers
between 0 and 99, and assign these values to a matrix.
8. Use all these functions in a main function.
9. Run these codes and see the results as an exercise.

FILE:advanced_c_topics__pointers_to_pointers__matrix_operat
ions.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-
Z)REDO
(Ctrl-Y) {
beautify(
);
}LOAD
DEFAULT
CODE


1

2

3

4

5

6

7

8

9
1
0
1
1
1
2
1
3
1

#include<stdio.h>
#include <stdlib.h>

int **allocate_matrix(int row, int column){
int **temp, i;
temp = (int **)malloc(row * sizeof(int *));
for (i = 0; i < row; i++)
temp[i] = (int *)malloc(column * sizeof(int));
return temp;
}
void free_matrix(int **M, int row){
int i;
for (i = 0; i < row; i++)
free(M[i]);
free(M);
}
void print_matrix(int **M, int row, int column){
int i, j;
for (i = 0; i < row; i++){
for (j = 0; j < column; j++)
printf("%d\t",M[i][j]);
printf("\n");
}
printf("\n");
}
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
3
3
3
4
3
5
3
6
3
7
3
8
3
9
4
0
4
1
4
int **matrix_addition(int **M1, int **M2, int row, int
column){
int i, j, **temp = allocate_matrix(row,column);
for (i = 0; i < row; i++)
for (j = 0; j < column; j++)
temp[i][j] = M1[i][j] + M2[i][j];
return temp;
}
int **matrix_multiplication(int **M1, int **M2, int row1,
int column1, int column2){
int **temp = allocate_matrix(row1,column2), i, j, k;
for (i = 0; i < row1; i++)
for (j = 0; j < column2; j++){
temp[i][j] = 0.0;
for (k = 0; k < column1; k++)
temp[i][j] += M1[i][k] * M2[k][j];
}
return temp;
}
int **matrix_transpose(int **M, int row, int column){
int i, j;
int **temp = allocate_matrix(column,row);
for (i = 0; i < row; i++)
for (j = 0; j < column; j++)
temp[j][i] = M[i][j];
return temp;
}
void random_matrix(int **M, int row, int column){
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < column; j++)
M[i][j] = rand() % 100;
}
int main(){
int **M1, **M2, **result;

M1 = allocate_matrix(3,4);
random_matrix(M1,3,4);
printf("M1:\n");
print_matrix(M1,3,4);


M2 = allocate_matrix(3,4);
random_matrix(M2,3,4);
printf("M2:\n");
print_matrix(M2,3,4);

result = matrix_addition(M1,M2,3,4);
printf("M1+M2:\n");
print_matrix(result,3,4);

free_matrix(M2,3);
free_matrix(result,3);

M2 = allocate_matrix(4,2);
random_matrix(M2,4,2);
2
4
3
4
4
4
5
4
6
4
7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
printf("M2:\n");
print_matrix(M2,4,2);

result = matrix_multiplication(M1,M2,3,4,2);
printf("M1*M2:\n");
print_matrix(result,3,2);

free_matrix(M2,4);
M2 = matrix_transpose(result,3,2);
printf("(M1*M2)^T:\n");
print_matrix(M2,2,3);

free_matrix(M1,3);
free_matrix(M2,2);
free_matrix(result,3);

anykey();
return 0;
}
0
7
1
7
2
7
3
7
4
7
5
7
6
7
7
7
8
7
9
8
0
8
1
8
2
8
3
8
4
8
5
8
6
8
7
8
8
8
9
9
0
9
1
9
2
9
3
9
4
9
5
9
6
9
7
9
8
9
9

16.16. When Do You Use Multidimensional Arrays Array Of Pointers And Pointers Of Pointers

1. Suppose the following problem. We want to keep the distances between the cities of Turkey.
We know there are 81 cities, therefore we can keep them in a static structure, i.e., by using
two-dimensional array.
float distances[81][81];
In this declaration, allocation is done implicitly and after exiting the scope of this array
deallocation will be performed implicitly too. You do not need to allocate and deallocate a
memory block for this array.
2. Suppose we want to keep the distances from a city to its towns for each city in Turkey. We
know that there are 81 cities in Turkey, it is fixed at this moment. On the other hand
different cities may have different number of towns, thus the number of towns is not fixed.
In this example we can keep 81 address information in an array, where each of address
indicates the starting point of a memory block for the corresponding city. In a memory block,
we keep the distances from the city to its towns.
float *distances[81];
In this declaration, the allocation of the first dimension is done implicitly. However if we
need, we must allocate the space for the second dimension explicitly by using any allocation
functions. In the same manner when we exit from the scope of distances, the first dimension
will be allocated automatically but we must free the second dimension.
/* code for allocation */
for (i = 0; i < 81; i++){
printf("Enter the number of towns of city %d: ", i);
scanf("%d",&n);
distance[i] = (float *)malloc(n * sizeof(float));
}
/* code for deallocation */
for (i = 0; i < 81; i++)
free(distance[i]);
3. Suppose user enters some city numbers. And we only want to keep the distances between
these cities and their towns. In this case we know neither the number of cities nor the
number of towns, i.e., both dimensions are free. float **distances; In this declaration only a
pointer that is capable of keeping an address is defined. We keep an address in this variable.
This address will be an address of an address of a floating point number. We must allocate
spaces for each dimension and free them explicitly.
4. /* code for allocation */
5. printf("Enter the number of cities:");
6. scanf("%d",&no);
7. distance = (float **)malloc(no * sizeof(float));
8. for (i = 0; i < no; i++){
9. printf("Enter the number of towns of city %d:",i);
10. scanf("%d",&noTown);
11. distance[i] = (float *)malloc(noTown * sizeof(float));
12. }
13.
14. /* code for deallocation */
15. for (i = 0; i < no; i++)
16. free(distance[i]);
free(distance);

16.17. File Operations

So far, we all read data from the standard input and write data on the standard output. These
operations are automatically defined for a program by the operating system. Moreover, your
program can also access a file that has already connected to the program.
There is a structure that contains information about the file (location of a buffer, current position in
the buffer, read/write flags, etc.). We have a file pointer points to this structure. The declaration of a
file is given as follows:
FILE *id;
The FILE * data type is defined in stdio.h. Before you access a file, you should connect to it
by fopenfunction. You must specify the filename (with its path) and the mode of the operation in this
function. Mode can be write(w), read(r), append(a), etc. For example if you open the file with read
mode and try to write some data into it, you may have problem. The following example connects the
file with name data.txt for the write operation. If there is some error, e.g. if a file with the specified
name is not found, fopen function returns to NULL.
FILE *fid;
fid = fopen("data.txt","w");
Some functions defined on the files are given as follows. You can find detailed information or more
functions in the stdio.h library or any reference book. Note that before performing these operations,
you must connect the corresponding file, i.e., you must open it.
1. fprintf: to print the formatted data into a file which has already opened.
fprintf(fid,"%dHello world\n%f\t%s\n",12,data,str);
2. fscanf: to read data from the opened file.
fscanf(fid,"%d%c",&myInt, &myChar);
3. fgets: to read characters from stream into the string s. It stops when it reads either n-1
characters or a newline character, whichever comes first. On success, it returns the string
pointed to s. On error or end-of-file, it returns NULL.
char *fgets(char *s, int n, FILE *stream);
4. fputs: It copies the null terminated string s to the given output stream. It does not append a
newline character and the terminating null character is not copied. On success, it returns the
last character written. On error, it returns EOF.
5. EOF: It is a constant indicating that end-of-file has been reached on a file.
We should break the connection between the file pointer and its external name, freeing the file
pointer by using fclose function.
fclose(fid);
There are limitations on the number of files that may open in a program. So close them if
they are no longer needed.
After the program is terminated, fclose is called automatically for each open file.
Do not try to close a file that was not opened. Otherwise you may have some problems.
Example: In the following example, data entered by the user is written in a file called info.dat. Then
this information (in info.dat) is read. For this purpose, write a function that reads and writes data
from/into a file.


FILE:advanced_c_topics__file_operations__file.c

Load Previous Saves/Versions:0-1-2-4-8-16-32-64-128-256-
512
Empty

SAVE
(Ctrl-
S)COMPILE
(Ctrl-F7)
UNDO
(Ctrl-Z)REDO
(Ctrl-Y) {
beautify();
}LOAD
DEFAULT
CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#include<stdio.h>

void writeIntoFile(char *filename){
FILE *id;
int n, i;
double data;
id = fopen(filename,"w");
printf("Enter the number of data to be entered:");
scanf("%d",&n);
for (i = 0; i < n; i++){
scanf("%lf",&data);
fprintf(id,"%lf\n",&data);
}
fclose(id);
}

double *readFromFileIntoAnArray(char *filename, int
*no){
FILE *myFile = fopen(filename,"r");
double *myData = NULL, temp;
*no = 0;
while (fscanf(myFile,"%lf",&temp) != EOF){
(*no)++;
myData = (double *)realloc(myData,(*no) *
sizeof(double));
myData[(*no) - 1] = temp;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
}
fclose(myFile);
return myData;
}

int main(){
double *data;
int no, i;
writeIntoFile("info.dat");
data = readFromFileIntoAnArray("info.dat",&no);
for (i = 0; i < no; i++)
printf("%lf\n",data[i]);
free(data);

anykey();
return 0;
}

Potrebbero piacerti anche