Notes On C Programming Language
Notes On C Programming Language
Abdelkader BELAHCENE
3. Advanced Statements 20
3.1. pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2. Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.3. More on Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4. Working on Libraries 28
4.1. Program splitted in Multi-les . . . . . . . . . . . . . . . . . . . . . . . 28
5. Oriented Object 32
5.1. Object Oriented Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.2. Improved C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3. Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.4. Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.5. Input output Commandes . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2
Contents Page 3
A. List of Programs 61
A.1. HomeWorks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
A.2. More Complete Programs . . . . . . . . . . . . . . . . . . . . . . . . . . 62
A.3. Graphical Interface Programs . . . . . . . . . . . . . . . . . . . . . . . . 67
An introduction to linux, to familiarise with this excellent system, Basic C++ state-
ments, just as a structured langage (as C), The concept of oriented object programming
and classes, Finaly, a graphical interface toolkit.
To design a program and run it in order to give a valuable thing we need to write it
on an environment, the natural one nowadays is the Linux system, because it is free,
available and contains all required softwares, like compilers, linkers. We need of course to
translate the source code (a human reading statements) to the machine code understood
by the computers also called executable program.
Since the system is multi-user we need, for security, a login and password to log on the
system. Therefore we have a perfect system for developers as like for users.
The machine or the system has of course an administrator which manage the machine,
gives the users the facilities and the possibility to work. The administrator or the
superuser, can do everything on the system, and destroy all the system too!!!
This is not the case for the simple user which has his own working space, and a limited
privileges. On the other side his work is protected, since nobody (but the superuser)
can access to his own space without his permission.
To avoid having unhappy surprise, the superuser creates for himself a simple login, for
personal and private works, and use the superuser login only for the administration.
The console or terminal is the main and basic interface with the computer, although
we can use mouse and button on graphical screen, the line command stay the most
important way to dialogue with the computer.
In some other environment, specially on windows, the command line is forgotten by the
users, even by their system administrator this leads to spread the eort and spend a lot
of time to do a very small tasks.
In the following examples, We 'll explain how the command line is very important and
useful for both administrator and users.
4
1.2. The File System Page 5
Example 1. Suppose you want to convert all your gif images to jpeg format and then
you archive and compress them. If you do it thru a graphical software, say gimp, you
have must do it interactively and repeatedly for each one. From a terminal, you can do
it very simply with a for loop like this:
Example 2. ypu want to download all openOce les from www.openoce.org. With
any browser like Netscape, Mozilla, .., you have to connect on-line to the site, look for
the les and download them one after one or in best case, get the directory but on-line
(you ought be in front you browser). Suppose now the connection is bad, so you expect
to do on night , if you are allowed!!!
2
Now let see how to do it from terminal or via a script shell . From the terminal we can
do at any time not necessary now and on-line, for example at 23:00 (when the connection
is good and partially free) you just need to run :
at 23:003
wget -c www.openoffice.org/pub/Openoffice.1.1.4.deb
So we save time and eort.
/sbin binary command (executable) for super user (administrator) : i.e: ifcong to
congure the network card
A user has his own working space, by default in /home. When the administrator creates
a count for someboday he uses a login name, say user33, by default the system creates
/home/user33 directory for this user, and all les created by user33 are stored there or
in subdirectories.
A user has a working space and environment, and can customise his environment. The
env command gives the content of all current variables, like $PATH,$HOME and so on,
5
check the command env and display, use echo $PATH and echo $HOME.
.bashrc Gives the behaviour for the login and at the opening terminal. To put changes
permanently, the changes, for example export PATH=$PATH:/opt/bin/ changes
the PATH on hot just for the current session, after logout it is lost, to put it for
ever put it in .bashrc. On we put here permanent changes les a .
5 le$ is required
6 par default : /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
7 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11
8 Hint: If the changes you have done is so bad that you want to retrieve the standard, just remove this
directory, next using will create a new directory.
9 For more details see Linux for beginners from www.tldp.org
cp -R tmp1 tmp2
Copies recursively the content of tmp1 (without subdirectory if any) to tmp2. cp: is the
command, -R is an option, tmp1 and tmp2 are parameters.
ls -lrt /etc Gives list of les and directories of /etc. The options mean long format (-l)
sorted in inverse (-r) time (-t).
mkdir myDir to create a directory, here we create myDir in the current directory
cat le.txt Displays the content of le.txt. use zcat to display a zipped le.
tail -15 le.txt Gives the tail of the le, here the last 15 lines (by default the 10 last).
The head does same for the head of the le.
cp f1.txt f2.txt Copies the content of f1.txt to f2.txt. If the last argument is directory,
it copies all the les, thus cp f*.txt myDir copies all les starting with f to myDir.
mv f1.txt f3.txt Rename or move the le, here f1.txt becomes f3.txt
rm *.txt Removes all les with extension txt.
ps aux Gives the list of running processesliste tous les process. Check top command
too.
kill -9 2345 Kills the process with PID 2345, (provided that it's yours).
more ch.txt Runs like cat, but splitted by page.
ls -l > f1.txt To redirect the output, instead of listing on the screen (standard output)
it is redirected to the le f1.txt. With the >> symbole, it is appended.
at 10:00 at time 10:00 executes commands given after the prompt (>), to end com-
mand use Ctrl+D
chmod o+w .txt To change le permissions. Here we add writting ermission to .txt.
So anybody can change or overwite this le. Each le has 3 leds ( u:user, g:group
, o:other) each eld is divided in 3 bits (r:read, w:write, x:execute). for example :
chmod 756 .txt means rwxr-xrw- for .txt.
10 be care with $, needed by shell variable
1.5. Questions
1. Create a directory called myDir, copy the les /etc/*.conf to myDir, list theses
les with details and in dierent order (ordered by time, by size,...).
2. Create le with a text editor and with cat command. Try the command mkdir
/theDir? what is the answer of the system? why?
6. Open propriety of the menu bar and add arrow to hide and show the bar
8. Use an editor, emacs, to create le F1.txt, put in some text. Copy F1.txt to F2.txt,
rename F2.txt to F1New.txt. Change permissions of F1.txt, read only for other
and read write for group. hint: see commands: cp, mv, chmod.
9. In which directory are you working, goto the parent directory, come back. Create
a directory, say temp, put in it the cong le (with conf extension) from /etc
directory. Create an archive le and save them on your usb pen. Try the command
mkdir /myDir ? What is the system response? Why? list the directory with ls -l
/.
The program needs to be compiled and linked. Compiling means, in one word, translat-
ing the code written by a human (source code) to a code understanding by the machine
( machine code) or an object code . But this is not enough to create an executable
program, in the previous example the program needs the code of the sine function which
is normally is in the system library, otherwise, the executable couldn't created.
How to execute this program? if you type only hello, on the command line, the system
doesn't nd it, because the current directory is not included in the path. Check your
path variable type echo $PATH. So we have 2 possibilities to x the problem:
1. Write ./hello, with dot (.) to precise that the le is here in the current directory
( ./ is a short cut for present directory);
9
2.2. Declarations Page 10
2. Add to the path, the list of searching directories, PATH=$PATH:., test it with the
command echo $PATH
2.2. Declarations
2.2.1. Hello Program Commented
Lines beginning with // are comments until the end of line, another way is to use /*
to start comment and */ to end it, in this case we can have several commented lines.
#include <iostream> is needed by the "cout" and "cin" statements which are external
1
statements, the declaration of "cout" is this le. In C++, all external functions must
2
be declared before their use.
int main(){ the main function, a program must has a main function, and only one.
The function is recognised by the double parentheses ( and ). This function can
return an integer value for another program, if any one calls it. The open brace begins
the code and the closed brace } ends it.
int x=12; here we reserve a space in memory used as integer value3 , called x and we
put the value 12.
cout<<"Hello World!"; Prints the string between the double quotes on the standard
output, thus on the screen.
cin>>x Reads from the standard input, the keyboard, and puts the value in x variable.
cout<<value of x is << x<<endl; prints a the string between quotes and the
content of the variable. Notice that we didn't give the type of the variable, it is found
automatically by the compiler. endl an \n have same eect that is go to new line.
To create the executable use the command :
g++ hello.cpp -o hello
The output name is hello, If we don't give the (-o hello) option, by default name is
a.out.
If we need only the object le (the name is hello.o) we use the -c option like this: g++
-c hello.cpp
Exercise 3. Write a program which calculates and prints the sum of 2 numbers, read
from the keyboard.
A variable may be initialised when it is dened. The variable is only known in the block
or function where it is declared, this is a local variable. A global variable, declared out
1 declare means type of arguments and returning variable, not the code of the function. See later
functions
2 In C language, a function non declared is taken int by default
3 we'll see how the numbers are represented in memory
side of all functions, even main function, is known everywhere. We call this the scope
of the variable.
Another dierence between local and global variable is the time life, the global variable
remains until the end of the program, while the local variable ends when the block or
function is left.
4
A variable must be declared before its using this is also true for function.
5
The programmer can create new type of variable , the fundamental types are :
int, unsigned integer number, resp. signed and unsigned, represented on bytes, 32 bits.
oat, double real number, respectively simple (4 bytes) and double precision (8 bytes).
char, unsigned a single character on 8 bits, signed and unsigned. each character is
represented by ASCII code (code of A is 65, b is 98, 0 is 48, and so on).
A character (char)
Is represented in one byte (8 bits), using the ASCII code. See the ASCII table. for
example the code of A is 65, of 0 is 48 of $ is 36 , of a is 97. The code is stored
in binary xed representation, which is a list of 0's and 1's, so $' is represented by the
binary string: 00100100. A character has no sign, the code is positive number.
char x='A';
if we print the x variable as integer ( the code), the string 65 is displayed, if we print
it as a caracter the string A is printed.
integer number
K C K C K C K C K C K C K C K C
0 null 16 nd 32 sp 48 0 64 @ 80 P 96 ` 112 p
6
1 nd 17 nd 33 ! 1 65 A Q 97 a q
2 nd 18 2 B R b r
3 nd # 3 C S c s
4 nd $ 4 D T d t
5 nd % 5 E U e u
6 nd & 6 F V f v
7 BEL ' 7 G W g w
8 BS ( 8 H X h x
9 TAB ) 57 9 I Y i y
10 LF * : J 90 Z j 122 z
11 VT + ; K [ k {
12 FF , < L ] l |
13 CR - = M \ m }
14 nd . > N ^ n ~
15 nd / ? O _ o 127 DL
real number
The real numbers are represented in oatting format. The oat type is a simple word
(32 bits: 1,7,24 stands respectively 1 bit for sign, 7 bits for exponent and 24 bits for
mantissa) and the double type is double precision representation (64 bits: 1, 15, 48). To
explain the procedure we suppose a machine with just 16 bits (1, 4, 11) the following
15
example represents the value : +
16
∗ 22 = 3.75
• bits 5-15: mantissa ( 0<m<1): here 0.1111 is 2−1 + 2−2 + 2−3 + 2−4 which is 0.9375.
Example 4. Let us study the following program. It is documented enough, more details
will be given at the appropriate moment.
2.3. Operators
Once we know the existence of variables and constants we can begin to operate with
them for that purpose, C++ provides many operators. It is important to know them
since they are the basis of the C++ language.
The complete list of operators are given in table 2.3.1 on page 15, here we give an
abstract of the main operators.
Assignation (=).
The assignation operator serves to assign a value to a variable a=5. assigns the integer
value 5 to variable a. The part at the left of the = operator is known as lvalue (left value)
and the right one as rvalue (right value). lvalue must always be a variable whereas the
right side can be either a constant, a variable, a result of an operation or any combination
of them.
It is necessary to emphasize that the assignation operation always takes place from right
to left and never at the inverse, a = b assigns to variable a (lvalue) the value that
contains variable b (rvalue) independently of the value that was stored in a at the that
moment. Consider also that we are only assigning the value of b to a and that a later
change of b would not aect the new value of a.
For example, if we take this code ( with the evolution of the variables content in green
color ):
int a, b; // a, b?? contain anything
a = 10; // a:10 b:?
b = 4; // a:10, now b contains 4
A property that C++ has over other programming languages is that the assignation
operation can be used as the rvalue (or part of an rvalue) for another assignation. For
example:
a = 2 + (b = 5); b = 5;
is equivalent to : a = 2 + b;
That means: rst assign 5 to variable b and then assign to a the value 2 plus the result
of the previous assignation of b (that is 5), leaving a with a nal value of 7. Thus, the
following expression is also valid in C++ :
+ addition
- subtraction
* multiplication
/ division
% modulo
Operation of addition, subtraction, multiplication, and division should not suppose an
understanding challenge for you since they literally correspond to their respective math-
ematical operators.
The only one that may not be known by you is the , specied with the percentage sign
(%). Module is the operation that gives the reminder of a division of two integer values.
for example, if we write a = 11%3; , the variable a will contain 2 as the result since 2 is
the remainder from dividing 11 by 3.
Compound assignation operators (+=, -=, /=, %=, >>=, <<=, &=, ^=, !=)
A feature of assignation in C++ that contributes to its fame of sparing language when
writing are the compound assignation operators (+=, -=, *= and /= among others ),
which allow to modify the value of a variable with one the basic operators.
see table 2.3.1 on the following page, the priority is given from the highest to the lowest
level.
See the complete programs in appendix A.2 on page 62 for more usage of operators.
7 the '{' and '}' are not required if there is only one statement.
:: Scope operator
. direct member
! unary NOT
& * References
12 +, - Unary sign
5 | bitwise Or left
3 || logical Or left
0 , comma
The command break stops and leaves the switch or the inner loop, while continue ,
continue the loop, that it takes the next iteration.
for (int i=0; i < 4; i++)
for (int j=0; j < 8; j++){
if (j==2) continue;
if (j==5) break;
cout <<\ni = <<i<<j= << j;
}
Exercise 5. Replace the switch of the previous paragraph with equivalent if 's
This loop doesn't print for j=2, it goes to the next j=3; but never for j greater or equals
to 5;
Exercise 7. Write a procedure which gives the numbers from n to m by step s for
example for n=2, m=20, s=3 we obtain: 2 5 8 11 14 17 20. Use dierent loop: while,
do while and for.
2.5. Functions
A function is a set of statements grouped together under a name and called by another
statement. The more complete type function is like: type NameOfFunction (argument1,
argument2, ...). The type may be any legal simple type (int, oat, char, struct, *int....)
the argument may be a simple or compound type (array , structure, class... ).
Example 8. The folowing function just prints message and doesn't return anything,
so it is declared void. The next one accepts a string as argument, the last one is more
complete with arguments and returning value.
void F1( ){ cout << Hello World ;}
void F2(string txt){ cout << txt<<endl; }
int F3(int a,int b){ int c=a+b; return c; }
To use these functions we call them from main for example like this: F1() to call F1
function without argument, F2( hello world); the string is sent to F2 which prints this
string. The function F3 returns value.
int y; y = F1(5, 12.5); y receives the returning value. Of course we can use variables as
arguments if tey are instanced.
In declaration we give just the type of the returning value and of arguments, unlike in
denition we give the code of the function. In another word, declaration contains the
head of the fonction and the denition the complete body. In the previous example, the
declaration is : int F1(int , int ); Before we use a function, we must dene it or at least
we declare it.
The well known .h header les contains the decalaration, for example math.h (see /us-
r/include directory) contains the head of mathematical functions, while the compile code
(the object) is in /usr/lib. See for more details the section 4.1 on page 28.
we nd there something like double sin(double) for sine function, double cos(double) for
cosine and so on. The header le iostream contains declaration for the input/output
functions (cout, cin, ...).
Example 9. The argument of the function may be an array, here the function returns
the sum of a elements of vector received as argument. Don't forget bracket [ in
declaration, but no bracket in the call statement:
int PrintVect (int nb,int v[]){
int p=0;
for(int i=0; i<nb;i++)
p =p + v[i];
return p;
}
int main () {
int A[]={10,12,13,4};
int y =PrintVect(4,A);
cout <<"\n the sum is "<<y<<endl;
}
Finally a function may be recursive, thus it calls itself. So this is a recursive cersion for
the factorial function.
int fact (int n) {
int b;
if (n == 1) return 1;
b= n * fact (n-1);
return b;
}
2.6. Arrays
An array is a set of same type of data. So int AA[10]; declares an array of 10 integer
numbers, it is equivalent to reserve 10 integer variables. these varaiables are namely
a[0], a[1], ..., a[9].
An array may be initialised at the declaration time, like double d[]= {12.5, 13, 25.6,
4.5}; The size is not necessary given, here , it is dened by the numbers of declared
values (here 4). To assign a value, d[2]=15.9, we precise the index, here 2. Recall index
of the rst element is 0.
The index is not necessary positive, and may be out the range, thus d[-5]=23.6 or
d[34]=55, are correct for the compiler, but of course it may lead to strange result, be
careful you are warned.
An array may have more than one dimension, so oat M[2][5] is a 2-dimensional array
with 2 x5 variables, each one is a real number. To initialise such array we use braces
like:
float M[2][5]={ {1.4, 2, 3.3,-2, 4 },{11, -2.1, 2, 3,0.5 } } ;
2.7. Exercises
1. Write in respectively bases 2, 4, 8, 16 the numbers 38, 234, 1482,0X8FC02.
3. Represent the real numbers in 16 bits following the format sign+ exp (in 5bits) +
mantissa(in 10 bits): 32.25, 325.3125, 0.001254, -23.12, -1.
4. What are the biggest and smallest positive number represented on this machine ?
5. Give the representation of the value 6 , what is the adjacent bigger number to this
value?
7. Redo the exercises 6 on page 16 and 7 on page 16 by using functions called from
main function.
8. Print multiples of 3 in a given interval [n, m], m and n are read from keyboard.
10. Print multiples of 3 in a given interval [n, m], m and n are read from keyboard.
It is important to precise the type of object pointed to, the compiler calculates the
shifting for an element of an array. suppose P contains the address 0XFF40 P+1 is
0XFF44, P+2 is OXFF48, because the size of a oat number is 4. To take a value we
1
use star '*', thus *P is same as P[0] , same as B[0], is 12. *P is read the object pointed
by P. In the inverse the ampersand '&' is used to take address of a variable, thus &B[0]
is 0XFF40.
1 #include <iostream>
2 using namespace std;
3 // Declaration of functions
4 void swap1( int , int);
5 void swap2( int * , int*);
6 int max1 ( int, int);
7 void max2 ( int , int, int *);
8 void readVect(int, double []);
9 double ProdScal (int,double [],double []);
10 int main(){
11 int x, y, z;
12 cout << "\n give 2 integer numbers (x,y)\t";
13 cin >> x >> y;
14 z= max1(x,y);
15 cout << "\n First function: The max of "<<x
16 << " and " << y<< " is " << max1(x,y)<<endl;
17 max2(x,y, &z);
20
3.1. pointers Page 21
70 p= v[i]*w[i];
71 return p;
72 }
3.2. Structures
3.2.1. Structure
A structure is a generalised array, where type of elements are not necessary the same,
in fact it is a special case of class, what w'll see later. The keyword struct is used to
declare a structure.
struct { int key;
string name;
float grade[5];
char *addr;
} student;
student is the name of the new type, which is a record. the variables key, name, grade,
addr are called elds. To take a eld we use a dot '.' thus student st1,st2; st1 and st2
2
are variables with student type , st1.name corresponds to the eld name of the variable
st1. in the case of pointer we use '->' symbol, thus struct *ptr; ptr= &st1; ptr->name
gives the name eld of the student pointed by ptr. for more details study the example.
1 #include <iostream>
2 #include <string>
3 using namespace std;
4 struct myStruct{
5 int Id;
6 char name[16];
7 float grade[3];
8 myStruct *next;
9 } ;
10
11 int main(){
12 myStruct Struct1, Struct2, *ptrStr;
13 Struct1.Id=123;
14 strcpy(Struct1.name,"Mohamed Ali");
15 Struct1.grade[0]=12.5;
16 strcpy(Struct2.name,"Youcef Islam");
17 Struct2.grade[1]=17.5;
18 ptrStr= & Struct2;
19 Struct2.next = &Struct1;
20 // contains adddress of structure
21 ptrStr->Id=546; // assign a value to Id
2 student is not a variable, but a type.
3.2.2. Union
Union allows one same portion of memory to be accessed as dierent type, for
example:
union {
int aa;
char cc;
float ff;
} myunion;
The three data type are implemented in the same place, and can be used as dierent
types (integer, character and oat), to access the oat type we use myunion.
Exercise 12. Store in a le the list of students (name, dateOfBorn, average). Dene a
structure for student.
Add to the previous exercise list of grades and average. The numbers of grades is only
known at the execution step.
3.2.3. Enumeration
Enumeration creates new type to contain other values than fundamental data. The
form is like this: enum enumName {value1, value2, .....} objectName. For example :
enum color_t { black=4, red, blue=11, yellow, green };
color_t mycolor=red;
The rst value is initialised to 4 (by default if not given, is 0), thus red is 5, yellow is 12
and so on.
ptr 0XFF00
Two ways to reserve dynamic the old way, C function malloc and the new one with the
new operator.
float *ptr;
ptr = (float *) malloc ( 6* sizeof(float ) );
The sizeof function calculates the size of the oat, it is interesting for compatibility,
if for example on big system the size is not the same as on small PC, we don't need
to recompile the code. The malloc function returns the address of the reserved space,
the cast is needed because by default the character pointer is returned. Suppose in this
3
example, see gure 3.3.1, 0xFF00 is the address of the reserved memory, this value is
returned by malloc and assigned to the variable ptr, the address of the next element,
pointed by ptr+1 is 0xFF04, since the size of a oat is 4 bytes, and ptr+2 is 0xFF08,
and so on. The object pointed by ptr ( that is *ptr) is the real number (a oat number)
13.5, in another way we can write also ptr[0] is 13.5, and ptr[1] is 15.4, which is same as
*(ptr+1) or the object pointed by the address ptr+1 (which is 0xFF04).
3 in hexadecimal format
1 #include <iostream>
2 using namespace std;
3 struct Param {
4 double left, right, step;
5 };
6 double Cube(double x){
7 return x*x*x;
8 }
9 double F1(double x){
10 return ( x + Cube(x) );
11 }
12 double Trapeze (double (*Fonc)(double ), Param *P ){
13 double c, X1, X0, Y0, Y1, Z = 0;
14 X0 = P->left; int i=1;
15 for(c=X0; c <= P->right ; c = c + P->step) {
16 X1 = X0 + P->step;
17 Y1 = (*Fonc)(X1); Y0 = (*Fonc)(X0);
18 Z += (Y1 + Y0) * P->step * 0.5;
19 X0 = X1;
20 }
21 return Z;
22 }
23 int main(){
24 Param arg;
25 arg.left=0; arg.right=2; arg.step=0.05;
26 cout << "\nIntegration of (x^3+ x) from 0 to 2:\n";
27 cout << "Exact Value : 6";
28 cout << "\nValue approx: "<<Trapeze(F1,&arg) << endl;
29 return 0;
30 }
Exercise 15. What are the main advantages of dynamic reservation over the static
reservation.
Exercise 16. Give the signicant (in English words) of the following declarations:
1. oat a =0.67; oat *b=&a; int *px;
5. initialize 2 variables to "Message" and "that is Ok" use both pointer and array
6. a pointer to function returning a real number and has 3 integer numbers as argu-
ments
7. a pointer to function returning a pointer to real number and has an array of integers
as argument.
Exercise 18. Give the output of the following program, Draw the schema for variables
on memory, suppose that address of implementation for a = 0xbffffb50 for c =
0xbffffb80
1 #include <iostream>
2 using namespace std;
3 int main(){
4 char *c[]={"This","is My","first","program"};
5 char **cp= c+1 ;
6 int a[]={1,3,5,7,9,10 };
7 int *p=a;
8 cout << "\naddr a = "<< a;
9 cout << "\naddr c = "<< c;
10 cout <<"\n a[1]= " << a[1];
11 cout <<"\n a+1 = " << a+1;
12 cout <<"\n p + 1 = " << p+1 ;
13 cout <<"\n *(p + 1)= " << *(p+1);
14 // be carefull with parentheses '()'
15 cout <<"\n c[2] = " << c[2] ;
16 cout <<"\n *(c+1) = "<< *(c+1) ;
17 cout <<"\n *(*cp+1)= " << *(*cp+1) ;
18 return 0;
19 }
Exercise 19. Write a program which calculates the sum (say F3) of 2 others functions
(say F1, F2) at a given value. Put F1,F2 in a le, F3 in another one and nally a test
Program in another one.
Exercise 20. Rewrite the previous program for general functions, that is F3 calculates
the sum of any 2 functions ( not known at the compilation step). hint: use pointer to
function.
28
4.1. Program splitted in Multi-les Page 29
Prog1.cpp MyLib1.cpp
Compile Compile
Link
Prog1 (executable)
Figure 4.1.1.: Link several les
code of the sine function. The executable program is now myexec (-o option: o for
output)
We can also write this in one command like this (compiling and linking in same
command):
g++ prog1.cpp mylib1.cpp -o myexec
-lm stands for /usr/lib/libm.a, in general -lYYY stands for library /usr/lib/libYYY.a.
By default, the libraries are install in /usr/lib directory, and header les in /usr/include.
Exercise 21. Complete the program 2.1 on page 9 and change its name, in order to
calculate a sum of three numbers, print them and their sum in dierent lines (each
output in line alone).
Exercise 22. Write prog2.cpp and mylib2.cpp. prog2.cpp reads 2 real numbers, prints
their sum and product. Use function to calculate the sum and the product, and put
them in mylib2.cpp le. Compile each program alone and then link them to create the
executable.
Exercise 23. Create in your home directory, 3 directories : Prog, Include, Lib. Put the
source les (prog2.cpp, mylib2.cpp) in the Prog directory.
We 'll use the le mylib1.cpp (which contains the two functions : square and sum) as
example to show how to create an archive library le. This library can be used by
anyone as a compiled object, this is the case for example, of the mathematical library,
2
in libmath.a le, we have all the standard functions (sin, cos, exp, log, ..).
ar (stands for ARchive) command can create archives, with miscellaneous options. The
more useful is r, for replacement or creation le in archive. For details type man ar
(recall man stands for manual, to read help manual on the given command).
After that use ranlib to create an index all the functions in archive, to facilitate the
searching. To list the content of an archive use t option, check for example ar t /us-
r/lib/libm.a
let us now see the example. If you have done correctly the exercise 23 on the preceding
page, the tree of your area is something like gure
Assume we are working in Prog (i.e /home/user1/Prog) directory, so the archive
library is created in Lib (i.e /home/user1/Lib) and the include le in Include (i.e
/home/user1/Include). In Lib, we create libpers.a , which contains the two object
function sum and square.
ar r libpers.a mylib1.o
ranlib libpers.a
In le Include/mylib1.h, we put the function declarations:
double square(double); double sum (double, double);
Now to create the executable program, we only need to write the following command,
g++ prog1.cpp -L/home/user1/Lib -lpers -I/home/user1/Include
The rst option -L , gives the path for extra library directories, the second -l for the
name of the library (recall statement 4.1 on the previous page) and the third for the
include directory.
If we want to make the library available for the public user, as a superuser we put it in
the standard place /usr/lib for library and /usr/include for header le, in this case
we don't need the previous options (-L/home/user1/Lib, -I/home/user1/Include).
Exercise 24. Move to the Prog directory, create there library for the functions of
mylib2.cpp, then create the executable for prog2.cpp from exercise 22.
The make command calls, by default, Makefile (if not name is given) , otherwise you
should give the name with -f option thus: make -f NameOfFile. Here is an
example, see the comments after each line:
lib = -lpers -lm
objects = ProgEx1.o ProgEx2.o
lib variable receives linking options
objects variable receives object les
prog: $(objects)
g++ -o prog $(objects) $(lib)
2 Please don't confuse, libmath.a, library of mathematical function (contains the code of functions)
with the header les math.h (contains declaration of function)
The result le prog depends in objects which are in objects variable notice the $.
Before g++, put a tabulation and not blanks. The variables $(objects) and $(lib) are
replaced by their content.
%.o: %.cpp
g++ -c $<
The command means all object les are obtained from the source (*.cpp) with the
g++ -c, all the targets are in the variable $<.
clean :
rm prog $(objects)
When the parameter clean is given to the make command, all object les are removed.
The previous script may be rewritten equivalently, (but the previous is more ecient:
you don't need to give explicitly the programs).
prog: ProgEx1.o ProgEx2.o
g++ -o prog ProgEx1.o ProgEx2.o -lm -lPers
ProgEx1.o: ProgEx1.cpp
g++ -c ProgEx1.cpp
ProgEx2.o: ProgEx2.cpp
g++ -c ProgEx2.cpp
clean :
rm prog ProgEx1.o ProgEx2.o
Another interesting thing with the make utility, the recompilation of a program is done
only if it is necessary, that is, if the source is more recent than the object.
The previous program is one of the simpler programs that can be written in C++, but
it already includes the basic components that every C++ program has. We are going to
take a look at them one by one.
Exercise 25. Suppose your are on tmp directory, create a make le for all program
les. Of course one le contains a main function and other functions on dierent les.
5.1.1. Encapsulation
In order to protect the data against bad manipulation, part of object is declared private
and couldn't be accessed directly, and are hidden to the external world, so methods are
required to do such access.
5.1.2. Inheritance
The properties of a class can be used in the derived class by the inheritance. For example
a window is a rectangle with background color so window is derived from rectangle with
an extra property, the color.
5.1.3. Polymorphism
Permits for a given call to a method to choose the appropriate function. This means
that several methods can have same name in class and its derived subclasses. more
details will be given later. For the moment consider the following example :
Rectangle R; Triangle T;
Polygon *Ptr;
Ptr=&R; R.area(); // calls the rectangle method.
Ptr=&T; T.area() ; // calls the triangle method
Polygon is a primitive class, triangle and rectangle are 2 derived classes. The area()
method can be dened in both triangle and rectangle. Now if we declare P as pointer
to Polygon and dependant of the content of the pointer (Rectangle or Triangle) the
appropriate method is choosen.
5.1.4. Templates
32
5.2. Improved C Page 33
5.2. Improved C
C++ is not only an improved C, since dierent aspect of C are improved in C++, but
also another concept is introduce, the oriented object. C++ is based on object and
class, of course all other statements of C remain correct.
The main improved elements in C by the new compiler C++ are listed here:
1. C++ is more strict in declaration and type, so all variables, functions too, must
be declared before using.
3. Declaration of variable at any place in the program, not necessary a the beginning,
then we can declare variable local to block of statements.
4. Overloading functions, so same name for multiple functions, int max(int, int) and
double max(double, double, double) are correct declarations.
6. operator new and delete replace malloc and free, for dynamic memory reservation.
8. The const attribut to declare constant data and avoid unwanted removing of values.
5.3. Classes
5.3.1. Declaration
class rational{
private:
int num, den;
public:
rational(int a, int b ){
num=a; den =b ;
}
float rational::getReal();
void print(){
cout << a << / <<b;
}
};
float rational::getReal(){
return num / den;
}
int main(){
rational r1(12,7),r2(123,76);
r1.print(); r2.print();
cout <<real part of r1 is << r1.getReal();
//cout<< r1.num; Error: direct access forbidden
}
In this example we dene a class of rational number. The data are private (even if the
private is not used, this is the default), means not used from outside of the class, the
last line in the main is not allowed.
To access the data (private part) we need a method which belongs to the rational class,
like print or getReal. We write r1.print() to say the object r1 of rational class calls its
print method.
• dened completely, head and body code inside the class like the print() method,
• or declared, just the head, and out of the class the body code, like getReal(). In
this case the name of the class and the scope operator :: must be used
5.3.2. Constructors
The creation of object is doing by the constructor, which creates the object, reserved
the space and links to the appropriate methods. In our example rational r1(12,7)
means a new object of type rational r1 is created and initialised by values 12 and 7.
The constructor has same name as the class. If a constructor is not given in the class,
one is given by default by the system. Another way to declare the previous rational
constructor is to write :
rational (int a, int b): num(a),den(b) {}
here the body of the function is empty, the initialisation is done in the head, num(a)
means num=a.
If no constructor is given, the system creates 2 constructors: the default and the copy
constructor. The rst one is to create the object without any initialisation, the second
is use when we create an object from an existent one. that is :
rational r1; rational r2=r1;
The rst declaration uses the default constructor to create r1 object, the second calls
the copy constructor to create r2 object and copy the content of r1.
Don't confuse
rational r2=r1;
rational r2; r2=r1;
In the rst case we call a copy constructor, in the second case we call a default constructor
and after that we use the = operator if it not explicitly dened, the default operator
is used.
Example 26. This program is split in tree les: The declaration of the class, the
implementation and a program test for the class.
1 // ratio1.h
2 //--------------------------------------------
3 class rational{
4 int num, den;
5 public:
6 rational( );
7 rational(int );
8 rational(int, int );
9 // can be repaced by one declaration like:
10 // rational(int =0,int =1) choose values
11 void print();
12 rational product ( rational);
13 rational operator* (rational);
14 };
15
16 //---------------------------------------
17 // ratio1.cpp
18 //-------------------------------------
19 #include <iostream>
20 using namespace std;
21 #include "ratio1.h"
22
23 rational::rational(){
24 num=0; den=1; // values are arbitrary
25 }
26 rational::rational(int n){
27 num=n; den=1;
28 }
29 rational::rational(int n , int d){
30 num=n; den=d;
31 }
32 void rational::print(){
33 cout << num << " / " << den;
34 }
35 rational rational::product( rational p){
36 rational r;
37 r.num = num * p.num;
Exercise 27. Show why have we to dene our copy constructor if the class contains a
pointer. Consider the following example:
1 #include <iostream>
2 using namespace std;
3 class myclass{
4 int x; int *y;
5 public :
6 myclass(int a, int b ){
7 x=a;
8 y = new int;
9 *y=b;
10 }
11 void print(){
12 cout << "x is " <<x<<" y is "<< y<< " *y "<<*y;
13 }
14 void putValue(int v){
15 *y = v;
16 }
17 };
18 int main(){
19 myclass A(10,12),B=A;
20 cout << "\n A is : ";
21 A.print();
22 cout << "\n B is : ";
23 B.print();
24 A.putValue(17);
25 cout << "\n A is : ";
26 A.print();
27 cout << "\n B is : ";
28 B.print(); cout <<"\n";
29 return 0;
30 }
5.3.3. Overloading
A function can be overloaded, that means, the same name is given for dierent functions.
In fact the dierences are in type or number of argument. In the previous example, the
constructor is redened or overloaded, we used a constructor without argument, with one
and with 2 arguments. I the same way, the * operator is redened for the rational class,
since it already exist for the integer and real numbers. Another example of reloading is
the default values, since we can call a function or operator with and without argument.
Consider for example the overload of > (greater than) operator in the following
program.
bool Rectangle::operator > ( Rectangle & r){
if ( area() > r.area() ) return true;
else return false;
}
We can write rect1 > rect2 where rect1 and rect2 are rectangle. This way is more natural
than using a function to compare them, just as we used to do with numbers for example.
Of course we have to dene the meaning of the operator, here for example, we consider
a rectangle is larger than another if its area is greater, other can consider the perimeter,
or any other measure.
Here other examples, more complete with comments and details. Look at the
programs: (See exercise 26 on page 35)
1 // Rect1.h
2 //-----------------------------------------
3
4 #include <iostream>
5 using namespace std;
6
7 #define NL cout <<"\n"
8
9 // To use word instead of value
10 enum COLOR {blue,green,red,white,black,yellow};
11 // Avoid multiple definition for tabCol
12 static char *tabCol[6]={
13 "blue", "green","red","white","black","yellow"
14 };
15 class Rectangle {
16 int *width, * height; // be carefull with pointers
17 COLOR color;
18 // color takes any values from the enumerated
19 char shape;
20 public:
21 // this part is acceed from out of the class
22 Rectangle (int, int, COLOR, char);
23 Rectangle (const Rectangle &);
24 char* getcolor( ){
25 return tabCol[color];
26 }
27 bool operator > ( Rectangle &);
28 bool operator==( Rectangle & x){
29 return ( area() == x.area() );
30 }
31 inline void putShape (char c){ shape=c; }
32 inline int getWidth ( ){ return *width; }
33 inline int getHeight( ){ return *height; }
34 // the next operator doesn't belong to the class
35 // declared friend, as external function,
36 // it can access to the member
37 // 2 arguments in a method is not allowed
38 friend Rectangle operator + (Rectangle &, Rectangle & );
39 // difference r - s or s - r
40 Rectangle operator -(Rectangle &);
41
42 int area();
43 void show();
44 }; // don't forget the ";"
45 /* Rect1.cpp
46 Program demonstrating pointer to class
47 */
48
49 #include "Rect1.h"
50 // The copy constructor must be redefined since pointers
51 // are used. See the exercise.
52
53 Rectangle::Rectangle (int w, int h, COLOR c, char chr='*'){
54 width= new int; // width and height are pointers,
55 height = new int;// Reservation needed
56 *width= w; *height=h;
57 color = c; shape=chr;
58 }
59 Rectangle::Rectangle ( const Rectangle & r){
Sometimes we need to give possibility to extern functions, not member of the class, to
manipulate the element of the class, to do so we use the friend keyword.
In the previous example, the + operator is used to add two rectangles, since in a
method we can't use 2 arguments, we declared an independent function with the keyword
friend. Thus, now the + operator can access the elements of the rectangle class.
The call is like R=R1 + R2; so the operator doesn't belong to any function, R1 and R2
are argument to +.
We can rewrite the + like the - operator, in this case, the call like R=R1-R2, means
the object R1 calls the - operator with R2 as argument. See the following exercise, in
the statement cout << nb, nb is an argument for the operator, and must be dened so.
• The operator is void (no value returned), the line commented doesn't work, let it
works, see the exercise 29 on the next page.
1 // ratio1Bis.h
2 //------------------------------------
3 #include <iostream>
4 using namespace std;
5 class rational{
6 int num, den;
7 public:
8 rational(int=0, int=1 );
9 rational operator* (rational);
10 friend void operator <<
11 (ostream &, rational & );
12 };
13 // ratio1Bis.cpp
14 //-------------------------------------
15 #include "ratio1Bis.h"
16 rational::rational(int n , int d){
17 num=n; den=d;
18 }
19 rational rational::operator *( rational p){
20 rational r;
21 r.num = num * p.num;
22 r.den =den * p.den;
23 return r;
24 }
25 void operator<< (ostream & ostr,rational & r ){
26 ostr<<r.num <<" / "<< r.den;
27 // ostr in our case "cout" receives all the stream
28 // return ostr; is needed to accept multiple "<<"
29 }
30 // ratio1BisTest.cpp
31 //-------------------------------------------------
32 #include <iostream>
33 using namespace std;
34 #include "ratio1Bis.h"
35
36 int main(){
37 rational r1(12,7), r2(3,2), r3;
38 cout <<"\n r1 is : "<< r1 ;
Exercise 29. Add a print operator << to our rational class, that we can write:
rational nb1,nb2;
cout <<nb1= << nb1<<nb2=<<nb2;
5.4. Inheritance
The lost advantage of the oriented object programming, is to complete a class with
properties and create a new class without creating all elements. In the following example
we'll see how a polynomial class can be derived from a vector. We call vector a parent
class of polynomial or polynomial is derived from vector.
Here we consider a polynomial a vector of coecients and a number argument. Thus
to calculate y=Poly(x), we send coecients as a vector and value of x.
class Poly : public Vector {
To use protected data from the parent class, we add the keyword public to the
declaration of the class. Notice that we never access to the private part out the class
itself !!!
In our case the data in vector are declared protected, and the inheritance is public. Just
to check, change for example in vector data to private, or omit the word, by default it
is private.
• to test only the vector class uncomment the main function, create the executable
from the vector.cpp.
• In this declaration of the Poly constructor, Poly::Poly (int n): Vector (n){ }we
send the value n to the Vector. This value is copied in size of Vector, there is no
size in Poly, it gets it from vector.
• The operator << is rewritten in Poly, since there is dierence in info to print.
The system is able to choose the appropriate operator depending on the object
used.
• The operator + used in the program test Poly3=Poly1+Poly2; has been rede-
ned for Poly class, since the object returned is Poly, because the left side is a
Poly object. But if the returned object was Vector, we don't need to redened it
in Poly, although we add 2 Poly objects. The parent operator + is used.
1 #ifndef VECTORH
2 #define VECTORH
3 #include <iostream>
4 using namespace std;
5 class Vector{
6 protected:
7 int size;
8 float * content;
9 public:
10 Vector (int=1 );
11 Vector (const Vector &);
12 inline int getSize(){
13 return size;
14 }
15 Vector & operator = (const Vector &);
16 Vector operator + (Vector &);
17 float & operator [] (int i);
18 friend ostream& operator << (ostream&, Vector& );
19 friend istream& operator >> (istream&, Vector& );
20 };
21 #endif
22 //----------------------------------------------
23
24 #include "vector.h"
25 Vector::Vector(int nbre){
26 size = nbre;
27 content= new float [size];
28 }
29
30 Vector::Vector(const Vector & tab){
31 size=tab.size;
32 content = new float [size];
33 for(int i=0; i < size; i++)
34 content[i] = tab.content[i];
35 }
36 float & Vector::operator [] (int i){
37 return content [i];
38 }
39 Vector & Vector::operator = ( const Vector & tab){
40 for(int i=0; i < size; i++){
41 content[i] = tab.content[i];
42 }
43 return *this;
44 }
45 Vector Vector::operator + ( Vector & tab){
46 Vector v;
47 v.size=size;
48 for(int i=0; i < size; i++){
We can use cin to get strings with the extraction operator (>>) as we do with
fundamental data type variables: cin >> mystring;
cin >> mystring;
However, cin extraction stops reading as soon as if nds any blank space character, so
in this case we will be able to get just one word for each extraction. If we want to get a
sentence or entire line from the user, we can use the function getline, which is the more
recommendable way.
The standard header le <sstream> denes a class called stringstream that allows a
string-based object to be treated as a stream. This is especially useful to convert strings
to numerical values and vice versa.
Example 32. In this example, we acquire numeric values from the standard input
indirectly. Instead of extracting numeric values directly from the standard input, we get
lines from the standard input (cin) into a string object (mystr).
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main () {
string mystr; float price=0; int quantity=0;
cout << "Enter price: ";
getline (cin,mystr);
stringstream(mystr) >> price;
cout << "Enter quantity: ";
getline (cin,mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;
return 0;
}
The classes for manipulating les is provided by fstream for input/output or ifstream
for input and ofstream for output. The manipulation of array can be handled with
strstream (or istrstream for input and ostrstream for output).
First we have to open a le, the keyboard and screen stream are open by default. the
following command open le example1.cpp in output mode:
ofstream outFile;// outFile is an an output file object
outFile.open(example1.cpp);
outFile is the name or the reference in the program, to le stored on the disk under the
name example1.cpp. The other argument precise the way to use the le.
In the same way we read data from a le, using the ifstream class, we rst open it and
at the end we close it, inFile.close().
We can check if the le was opened, if for example, it doesn't exist. The method returns
a boolean value. Here is an example.
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int sum = 0; int x;
ifstream inFile;
inFile.open("example1.cpp.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
• ofstream ios::out
• ifstream ios::in
Text le streams are those where we do not include the ios::binary ag in their opening
mode. These les store text exactly as you enter it, you can read it in any standard
editor, in the same way with the standard cin or cout.
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile ("example.txt");
if (myfile.is_open()) { // is it correctly opened
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile << setprecision(10)<< 0.1<< endl;
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
ifstream, like istream, has a pointer known as the get pointer that points to the element
to be read in the next input operation.
ofstream, like ostream, has a pointer known as the put pointer that points to the location
where the next element has to be written.
Finally, fstream, inherits both, the get and the put pointers, from iostream (which is
itself derived from both istream and ostream).
tellg() and tellp(): These two member functions have no parameters and return a
value of the member type pos_type, which is an integer data type representing the
current position of the get stream pointer (in the case of tellg) or the put stream pointer
(in the case of tellp).
seekg(pos) and seekp(pos): These functions allow us to change the position of the get
and put stream pointers. Both functions are overloaded with two dierent prototypes.
The rst prototype is:
Example 34. This example uses the member functions we have just seen to obtain the
size of a le:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
long begin,end;
ifstream myfile ("example.txt");
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) << " bytes.\n";
return 0;
}
the operator << and >> are inecient to read (or write) les. We need other methods.
We copy from (or to ) memory a block of data, without fromatting. Remember after
declaration int x; the command cout << x; use the format the xed representation value
in a string to dsiplay it.
For example int i=109; in memory we have a zone with 32 bits 25 zeros and the last
are 1101101. Now to print with cout<<i; the compiler convert this block of memory to
a string 109. In the following example we use the appropriate methods:
Abdelkader BELAHCENE
52
6. Graphical User Interface
6.1. Introduction
A C++ compiler as other high level language doesn't contain a graphical interface.
To complete this lack on modern computer many softwares do it, as example with Qt
designer, kdevelop, glade or eclipse. Some of them depend on the platform, kdevelop
runs on Kde desktop, glade on gnome, some other are multiplatform but very huge like
eclipse.
We decide to use a small software, open source and cross-platfom, but very simple to use
and to develop with. The software is Fast Light Tool Kit (FLTK: pronouced fulltik).
For more details see the reference [1].
Fltk is a set of graphical statements, we can use them in a standard editor like emacs
or gedit, but we can also use a special editor Fast Light User Interface Designer (Fluid)
which generates the statements from the graphs.
To create a window, we can use the following command
Fl_Window *window = new Fl_Window(300,180,MyWindow);
or by using the uid, on which we create the window and draw it by dragging the mouse.
In our case, we want that the student learns how to program and not how to use tools,
we write our program in a standard editor. At the end we give some examples and show
how to use uid.
Exercise 35. Install the software : get the source of the current version tk-1.1.7.tar.bz2.
After untared the les. This software needs libX11-dev. mesa-GL mesa-Glut , libjpeg,
libpng are recommended. After installing theses packages , run
2. If there is no error, the Makele is created, make to compile and create the exe-
cutable programs like uid
3. make install is to run as a root, to install in the system and put it available for
every user.
Exercise 36. Use Fluid to generate the hello.cxx program in the following example.
You'll notice that Fluid includes the required les.
53
6.3. Basic classes Page 54
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
int main(int argc, char **argv) {
Fl_Window *window = new Fl_Window(300,180);
Fl_Box *box = new Fl_Box(20,40,100,90,"Hello");
box->labelsize(24);
box->box(FL_UP_BOX);
box->labelfont(FL_BOLD)
window->end();
window->show(argc, argv);
return Fl::run();
}
The rst 3 lines are the include headers le. we create an object instance from the
Fl_window class, with dimensions 300 and 180, relatively to the corner of this window
we draw a box with the precised values, 20 and 40 are positions, 100 and 90 are the
size, and the last hello is a label and other properties (labelsize, labelfont, ...). The
window->end is a method to nish window description. The show method is needed to
show the window, at last we need event running command run. Now check the
program. rst compile it with the command:
fltk-config --compile hello.cxx
The previous command is equivalent to the following, it calls all the required libraries:
f ) Fl_Round_Button - A button
a) Fl_Counter - A widget with arrow buttons that shows the current value.
a) Fl_Pack - A collection of widgets that are packed into the group area.
5. Callbacks: are functions that are called when the value of a widget changes. void
xyz_callback(Fl_Widget *w, void *data) { ... } The callback() method sets the
callback function for a widget
6.4. Examples
The best way to understand how all this system is running, is to give examples in
increasing diculties. The list of all programs is too long, you can get them as tared
and zipped le: uidExamples.tgz..
Example 37. Input output widget. To generate the executable program, use the com-
mand:
Have a look to the les : Fl_Window.H and Fl_Window.cxx. Remember, the Fltk is
an open source so we can get the source of the software.
Have a look to Fl_Window class. The constructor called in our case is:
The variables inp and outp are pointers to new objects, or instance of their classes.
The inp object accepts input values from keyboard and outp displays on screen.
Fl_Button* o=new Fl_Button(245,160,90,30,"Execute");
o->callback((Fl_Callback*)cb_Execute);
This is a call to function: a role of a button, is to execute a function ( a callback function)
when we click on it.
Here the cb_Execute is called and executed when we ckick on the button-image, thus
the content of inp object is copied to the output object.
All what we had is done on memory until we show the window. Remember that the
program uses the events, this means that it waits for mouse click or keyboard hit to do
somethings.
As exercise comment the statement ( w->show() ) which displays the window on the
screen.
Let us study now the class Fl_Input, just to see the value method :
const char *Fl_Input::value()
int Fl_Input::value(const char*)
int Fl_Input::value(const char*, int)
The rst form return the content of the intern buer of the object hasn't argument,
while the others accept the string as parameter and return the integer value.
In our example, in the main function we used the second form to initialize the input
eld,
inp->value("Welcome");
while in the function cb_execute we sent the value, without parameter, as argument
for the method output->value() .
outp->value(inp->value() );
So we can use this method to put in the buer or to get the content of that buer. As
we have seen before in section 5.3.3 on page 37, the value method is overloaded. The
gure 6.4.1 on the next page shows an example of execution.
In fact Fl_Window derived from the Fl_Group and the value are sent to the parent
class. See the inheritance section 5.4 on page 42.
Example 38. In the following example we see how to use a user class, here a rational
number, read in window and write from a window.
33 (int)num2->value() );
34 r1.show();
35 }
36 void cb_Quit(Fl_Button*, void*) { exit(0); }
37 int main(int argc, char **argv) {
38 Fl_Window * w=new Fl_Window(500,300,"Rational Numbers");
39 num1 = new Fl_Value_Input(175,20,200,50, "number1");
40 num1->type(2);
41 num2 = new Fl_Value_Input(175,80,200,50, "number2");
42 outp = new Fl_Output(175,160,200,70, "Rational Number");
43 outp->type(12);
44 outp->color(FL_GREEN);
45 Fl_Button* but = new Fl_Button(175,250,80,30,"create");
46 but->labelsize(18);
47 but->callback((Fl_Callback*)cb_create);
48 but->color(FL_BLUE);
49 Fl_Button* quit = new Fl_Button(280,250,80,30,"Quit");
50 quit->labelsize(18);
51 quit->callback((Fl_Callback*)cb_Quit);
52 quit->color(FL_RED);
53 w->show(argc, argv);
54 return Fl::run();
55 }
The C function sprintf() : prints the string in a variable, not on the screen. Here
sprintf(str,"%d\n\n%d",num, den);, prints in the variable str the values of num
and den in a formatted format. We need this conversion because the output widget
accepts string since num and den are integer numbers.
For more complete programs, with drawing functions, browsing le and multi-layers see
the section
Exercise 39. For the previous examples, 37 on page 55 and 38 on page 57, use the
interface program uid to do the same program.
Exercise 40. Write a program with 3 elds, 2 rst elds are input widgets, the third
receives the concatenation of the 2 others when we click on a button. Get help from the
rst example 37 on page 55.
For more details see the ocial site www.tk.org and the documentation in the docu-
mentation directory of the source. Several examples come with the source software. See
the directory test.
Problem 42. Write a program in two les the rst contains the main function and the
other the functions, give the command which generates the executable program.
Problem 43. The program calculates the dot product ( i.e: y=A*B ) and the sum of
sine and cosine of real numbers of vectors (i.e: C[i]=sin(A[i]) + cos(B[i]) ).
1 see also les: uidExamples.tgz
61
A.2. More Complete Programs Page 62
To do:
Problem 44. Suppose in a machine the real numbers are represented in memory in 16
bits, the following example represents the value : + 15
16
∗ 22 = 3.75
What are the biggest and smallest positive number represented on this machine ?
Give the representation of the value 6 , what is the adjacent bigger number to this value?
1 // ----------------------------------------------
2 #include <iostream>
3 using namespace std;
4 // size is given by the initialisation
5 float A[]={ 1.5, 2.5, -5.5, 4, 3,125};
6 char C[] = {'f','i','r','s','t',' ','p','r',
7 'o','g','r','a','m',0};
8 char ptC[]="first program"; // same as the previous
9 string strC="first program"; // same as the previous
10 double B[][3] = { {2.5, 3.5, 4.5},
11 { 2.6, 3.6, 4.6}
12 };
13 // the second argument must be given ( here 3 )
14 int main(){
15 double x, y;
16 cout << "\n Values of A : "<<endl;
17 for (int i=0; i < 6;i++)
18 cout << A[i]<<"\t";
19 cout << "\n Values of matrix B : "<<endl;
20 for (int i=0; i < 2;i++){
21 for (int j=0; j < 3;j++)
74 /* to creat lib:
75 ar r libpers.a Funct1.o
76 ranlib libpers.a
77 sudo cp libpers.a /usr/lib
78 g++ PolyTest2.cpp -lpers
79 */
80 double Cube( double w){
81 // be carefull with uppercase/ lower
82 return w*w*w;
83 }
84 double Power(double base, int expo){
85 double y= 1;
86 for(int i=1; i <= expo; i++)
87 y *= base;
88 return y;
89 }
90 void InputParam(Poly_t *Ptr){
91 cout << "\nGive the Polynomial degree \t";
92 cin >> Ptr->degree;
93 cout <<"Give the "<<Ptr->degree+1<<
94 " coeffs in increasing order\t";
95 for (int i=0; i <= Ptr->degree; i++)
96 cin >>Ptr->coeff[i];
97 }
98 double Poly(Poly_t p, double x){
99 double Sum = p.coeff[0];
100 if ( !x ) return Sum;
101 for (int i=1; i <= p.degree; i++)
102 Sum += p.coeff[i] * Power (x, i);
103 return Sum;
104 }
105 int main(){
106 Poly_t myPoly;
107 double x;
108 InputParam(&myPoly);
109 cout << "\n to stop the program give 0 "<<endl;
110 for ( int i=0; ; i++){
111 cout <<"\n give value of x \t";
112 if (!x) {
113 cout <<endl;
114 return 0;
115 }
116 cin >> x;
117 double y=Poly(myPoly, x);
118 cout << "value of the polynomial is \t"<< y;
119 cout << "\n its cube is " << Cube(y);
120 }
121 }
122 /* More complete Example on how to use pointer to function
123 Solution of F(x) = b
124 Besearch method
125 F= fonct ( Poly2)
126 */
127 #include <iostream>
128 using namespace std;
129 const int DIM = 20;
130 const int NBTERM = 4;
131
132 /* POLYNOMIAL Max Degree */
133 double coef[DIM];
134 double Z_center, center, init_left, init_right;
135 double Left, Right, Epsilon, sec_membre;
136 int max_iter, degre;
137 struct {
138 int nbre;
139 double (*fnc)(double);
140 } funcTab;
141 struct lib_fnc {
142 char *name;
143 double (*pointer)(double);
144 } ;
145 double sin2 (double x){
146 return ( sin(x) * sin(x) );
147 }
148 double cos2 (double x){
149 return ( cos(x) * cos(x) );
150 }
151 double identity (double x){
152 return x;
153 }
154
155 struct lib_fnc tf[]={"identity", identity,"log",log,"sqrt",
156 sqrt,"sin", sin ,"fabs", fabs, "cos", cos, "exp", exp,
157 "sin2", sin2, "cos2", cos2, NULL, NULL
158 };
159 double Power(double x, int n){
160 int i;
161 double prod = 1;
162 for (i = 0; i < n; i++)
163 prod *= x;
164 return prod;
165 }
166 double Poly(double x, int deg, double Coef[]){
167 int i;
168 double S = Coef[0];
169 if ( !x ) return S;
170 for (i=1; i <= deg; i++)
171 S += Coef[i] * Power(x, i);
172 return S;
173 }
174 double (*ptrfonc(char * pn) )(double){
175 struct lib_fnc *p;
176 // searching for the function, when the name is given
177 for(p=tf;p->name!=NULL && strcmp(pn,p->name);p++);
230
231 Z_center += f_compose(center);
232 Z_left += f_compose(b_inf);
233 if (!Z_center ) return 0;
234 if (Z_center * Z_left < 0) b_sup = center;
235 else b_inf = center;
236 return Z_center;
237 }
238 int main(){
239 int j=0;
240 cout <<"\n\t\tSolution of F(x)=b with besearch method\n";
241 InputSec();
242 InputFunc();
243 InputPoly();
244 Z_center = - sec_membre;
245 Z_center += f_compose(Left);
246 if(!Z_center)
247 center = Left;
248 else {
249 Z_center = - sec_membre;
250 Z_center += f_compose(Right);
251 if(!Z_center) center = Right;
252 else
253 do {
254 Z_center = Besearch (Left,Right);
255 center = (Left + Right)/ 2;
256 }while (fabs(Z_center)>Epsilon && ++j<max_iter);
257 }
258 Z_center =0;
259 Z_center += f_compose(center);
260 cout <<"\nX= "<<center<<"\tF(X)= "<< Z_center<<endl;
261 cout << "Number of Iteration : "<< j <<endl;
262 return 0;
263 }
10 #include <FL/Fl_Value_Output.H>
11 #include <FL/Fl_Browser.H>
12 #include <FL/Fl_Return_Button.H>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 Fl_Input *inp1=(Fl_Input *)0;
18 Fl_Input *inp2=(Fl_Input *)0;
19 Fl_Input *outp=(Fl_Input *)0;
20 Fl_Value_Input *nb1=(Fl_Value_Input *)0;
21 Fl_Value_Input *nb2=(Fl_Value_Input *)0;
22 Fl_Value_Output *result=(Fl_Value_Output *)0;
23 Fl_Input *com=(Fl_Input *)0;
24 Fl_Browser *brow=(Fl_Browser *)0;
25
26 void execute() {
27 char fname[30],car;
28 FILE *file; int nb;
29 strcpy(fname, com->value() );
30 strcat (fname, " > res 2>err ");
31 system (fname);
32 file=fopen("err", "r");
33 nb = fscanf(file,"%c",&car);
34 fclose(file);
35 if (nb==1) brow->load( "err" );
36 else brow->load( "res" );
37 }
38 void cb_Copy(Fl_Button*, void*) {
39 char ch[100];
40 sprintf(ch,"%s\n%s",inp1->value(),inp2->value());
41 outp->value(ch);
42 }
43 void cb_Product(Fl_Button*, void*) {
44 result->value(nb1->value()*nb2->value() );
45 }
46 void cb_Run(Fl_Button*, void*) {
47 execute();
48 }
49 static void cb_cancel(Fl_Button*, void*) {
50 exit(1);
51 }
52 static void cb_OK(Fl_Return_Button*, void*) {
53 exit(0);
54 }
55 int main(int argc, char **argv) {
56 Fl_Window* w= new Fl_Window(390,470,"Layers");
57 Fl_Tabs* t = new Fl_Tabs(20,20,340,400);
58 t->selection_color(FL_SELECTION_COLOR);
59 Fl_Group* g = new Fl_Group(20,40,340,380, "Text");
60 inp1 = new Fl_Input(60,70,270,70,"input text1");
61 inp1->type(4);
62 inp1->align(FL_ALIGN_TOP_LEFT);
63
64 inp2 = new Fl_Input(60,160,270,70,"input text2");
65 inp2->type(4);
66 inp2->align(FL_ALIGN_TOP_LEFT);
67 outp = new Fl_Input(60,250,270,110,"output text");
68 outp->type(4);
69 outp->align(FL_ALIGN_TOP_LEFT);
70
71 Fl_Button* b = new Fl_Button(110,370,150,40,"Copy");
72 b->callback((Fl_Callback*)cb_Copy);
73 g->end();
74 Fl_Group::current()->resizable(g);
75
76 Fl_Group* g1= new Fl_Group(20,40,340,290,"Product");
77 g1->hide();
78 nb1= new Fl_Value_Input(90,70,220,50,"float 1");
79 nb2= new Fl_Value_Input(90,140,220,50,"float 2");
80 result= new Fl_Value_Output(90,210,220,50,"product");
81 Fl_Button* b1= new Fl_Button(150,280,110,40,"Product");
82 b1->callback((Fl_Callback*)cb_Product);
83 g1->end();
84
85 Fl_Group* g2 = new Fl_Group(20,40,340,380,"Command");
86 g2->labelfont(3);
87 g2->hide();
88 com = new Fl_Input(30,60,240,40,"Command Shell");
89 com->align(FL_ALIGN_TOP_LEFT);
90
91 brow = new Fl_Browser(30,100,330,320);
92 Fl_Button* b2 = new Fl_Button(270,60,80,40,"Run");
93 b2->callback((Fl_Callback*)cb_Run);
94
95 g2->end();
96 t->end();
97 Fl_Group::current()->resizable(t);
98
99 Fl_Button* b3 = new Fl_Button(50,430,60,30,"cancel");
100 b3->callback((Fl_Callback*)cb_cancel);
101
102 Fl_Return_Button* b4 = new Fl_Return_Button
103 (250, 430, 60, 30, "OK");
104 b4->callback((Fl_Callback*)cb_OK);
105
106 w->end();
107 w->show(argc, argv);
108 return Fl::run();
109 }
1
2 #include <FL/Fl.H>
3 #include <FL/Fl_Double_Window.H>
4 #include <FL/Fl_Return_Button.H>
5 #include <FL/Fl_Button.H>
6 #include <FL/fl_draw.h>
7 #include <FL/Fl_Value_Input.H>
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12
13 class Drawing: public Fl_Widget {
14 void draw();
15 public:
16 Drawing(int,int,int,int,const char *);
17 };
18 Drawing *d;
19 void DrawCurve();
20
21 void cb_Exit(Fl_Return_Button*, void*) {
22 exit(0);
23 }
24 void cb_Draw(Fl_Button*, void*) {
25 DrawCurve();
26 }
27 Fl_Value_Input *inpNb=(Fl_Value_Input *)0;
28
29 Drawing::Drawing(int X,int Y,int W,int H,const char *str):
30 Fl_Widget(X,Y,W,H,str) {
31 }
32 void DrawCurve() {
33 d->redraw(); // the new graphic
34 }
35
36 int main(int argc, char **argv) {
37 Fl_Double_Window* w;
38 { Fl_Double_Window* o = new Fl_Double_Window(485,545,"WinMain");
39 w = o;
40 { Drawing* o=new Drawing(40,105,410,415,"The Lines");
41 o->box(FL_ROUNDED_FRAME);
42 o->color((Fl_Color)55);
43 o->selection_color(FL_GREEN);
44 o->labeltype(FL_NORMAL_LABEL);
45 o->labelfont(0);
46 o->labelsize(18);
47 o->labelcolor((Fl_Color)80);
48 o->align(FL_ALIGN_TOP);
49 o->when(FL_WHEN_RELEASE);
50 d=o;
51 }
52 { Fl_Return_Button* o = new Fl_Return_Button
53 (380,30,65,35,"Exit");
54 o->callback((Fl_Callback*)cb_Exit);
55 }
56 { Fl_Button* o = new Fl_Button(290,30,65,35,"Draw");
57 o->callback((Fl_Callback*)cb_Draw);
58 }
59 { Fl_Value_Input* o = inpNb = new Fl_Value_Input
60 (30,30,240,35,"Nbre Of Lines");
61 o->align(FL_ALIGN_TOP_LEFT);
62 }
63 o->end();
64 }
65 w->show(argc, argv);
66 return Fl::run();
67 }
68
69 void Drawing::draw() {
70 int vx=d->x(), vy=d->y(), vw=d->w(), vh=d->h();
71 int nb= int (inpNb->value() );
72 int cx = int (vx + vw /2 );
73 int cy = int (vy + vh /2);
74 int ray = int (vw < vh ? vw /4 : vh / 4 );
75 double ang =0, depang = 6.28 / nb;
76 int endx, endy;
77 fl_clip(vx,vy,vw,vh);
78 fl_color(FL_DARK3);
79 fl_rectf(vx, vy,vw,vh);
80 fl_color(FL_RED);
81
82 fl_begin_line();
83 for (int i=0; i < nb ;ang += depang, i++){
84 endx = int( cx + ray* cos (ang));
85 endy = int ( cy+ ray* sin (ang) );
86 fl_vertex(cx,cy);
87 fl_vertex(endx, endy);
88 }
89 fl_end_line();
90 fl_pop_clip();
91 }
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19 #include <FL/fl_draw.H>
20
21 Fl_Input *pattern=(Fl_Input *)0;
22 Fl_Input *current=(Fl_Input *)0;
23 Fl_Browser *browfile=(Fl_Browser *)0;
24 float Min(int , float [] );
25 float Max(int , float [] );
26 int x_center, y_center;
27 #define NBPOINTS 50
28 int NbPts;
29 float args[2][NBPOINTS];
30 float inputs[2][NBPOINTS];
31
32 const char* help =
33 "\n This program draws the curve corresponding to the points "
34 "\n read from a file. As example use F_Gr_Example2.dat \n"
35 "\n The file contains the number of points and their coordonates"
36 "\n in the form x1 y1 for first point, x2 y2 for second and so on2, "
37 "\n\n"
38 "\n The origine (0,0) is is the center of the window "
39 "\n the methods d->x(), d->w(), d->y(), d->h() give respectivly "
40 " \n the left, right corners , the width and height of the window "
41 "\n The ChooseFile button let to choose the data file"
42 "\n LoadFile button load the data file in the corresponding zone\n\n"
43 "\n The Draw button draws the curve corresponding to the loaded file \n\n";
44
45 float Min(int taille, float tableau[] ){
46 int min=0; int i;
47 for(i=1;i<taille;i++) /* retourne Indice du Min */
48 if(tableau[min] >tableau[i]) min=i;
49 return( tableau[min]);
50 }
51 float Max(int taille, float tableau[] ){
52 int max=0; int i;
53 for(i=1;i<taille;i++) /* retourne Indice du Max */
54 if(tableau[max] < tableau[i]) max=i;
55 return(tableau[max] );
56 }
57 class Drawing : public Fl_Widget {
58 void draw() {
59 fl_clip(x(),y(),w(),h());
60 fl_color(FL_DARK3);
61 fl_rectf(x(),y(),w(),h());
62 fl_push_matrix();
63 fl_color(FL_RED);
64 fl_translate(transx, transy);
65 fl_begin_line();
222 o->align(FL_ALIGN_TOP);
223 }
224 { Fl_Value_Slider* o=new Fl_Value_Slider(580,380,30,250,
225 "shift on y");
226 o->type(4);
227 o->labelfont(1);
228 o->minimum(-250);
229 o->maximum(250);
230 o->step(5);
231 o->callback((Fl_Callback*)CallVer);
232 o->align(130);
233 }
234 o->end();
235 }
236 w->show(argc, argv);
237 return Fl::run();
238 }
[1] uidExamples.tgz
77