Paradigmes soutenus par C++

1) Prog. procédurale

Choisissez les procédures. Utilisez les meilleurs algorithmes que l'on peut trouver.

ex.

#include <iostream>

double sqrt(double arg)
{
	double res=100.00;
	for(int i=0; i<100; i++)
		res=0.5*(res+arg/res);
	return res;
}

int main()
{
	double root2=sqrt(2);
	std::cout << "Valeur approx de racine de 2: " << root2 << std::endl;
}

2) Prog. modulaire

Choisissez vos modules. Découpez le programme de telle sorte que les données soient masquées par ces modules.

ex. 

/* compilation séparée:

g++ -c stack.cpp
g++ -c user.cpp
g++ user.o stack.o 

*/

/* Remarque on peut aussi compiler directement avec 

g++ user.cpp stack.cpp

mais ce n'est pas dans l'esprit "prog modulaire"
*/ 

//stack.hpp

namespace Stack {
	void push(char);
	char pop();
	
	class Overflow{};  //exception
}

//stack.cpp

#include "stack.hpp"

namespace Stack  {
	const int max_size = 200;
	char v[max_size];
	int top =0;
}

void Stack::push(char c)
{
	if(top==max_size)
		throw Overflow();
	
	v[top]=c;
	top++;
}

char Stack::pop()
{
	if(top>0)
	{
		top--;
		return v[top];
	}
}

//user.cpp

#include "stack.hpp"
#include <iostream>

using namespace std;

int main()
{
	try{
		Stack::push('t');
		Stack::push('e');
		Stack::push('s');
		Stack::push('t');
	
		Stack::pop();
	
		cout << Stack::pop() << "\n";   // doit afficher 's'

		while(true)
			Stack::push('c');
	}
	catch(Stack::Overflow) {
		cout << "Error overflow \n";
	}
}

4) Abstraction des données

4.a) Modules définissants des types

ex.

//stack.hpp

namespace Stack {
	struct Rep;
	typedef Rep& stack;
	
	stack create();
	void destroy(stack s);
	
	void push(stack s, char c);
	char pop(stack s);
	
	class Overflow{};
	class Underflow{};
}

//stack.cpp

#include "stack.hpp"

namespace Stack  {
	const int max_size = 200;
	
	struct Rep {
		char v[max_size];
		int top;
		int num;
	};
	
	const int max = 16;
	
	Rep stacks[max];
	bool used[max]={false};
	
	typedef Rep& stack;
}

void Stack::push(stack s, char c)
{
	if(s.top==max_size)
		throw Overflow();
	
	s.v[s.top]=c;
	s.top++;
}

char Stack::pop(stack s)
{
	if(s.top>0)
	{
		s.top--;
		return s.v[s.top];
	}
	throw Underflow();
}

Stack::stack Stack::create()
{
	int i=0;
	while(i<max && used[i]) i++;
	
	if(i==max)
		throw Overflow();
		
	used[i]=true;
	stacks[i].top=0;
	stacks[i].num=i;
	
	return stacks[i];
}

void Stack::destroy(stack s)
{
	used[s.num]=false;
}

//user.cpp

#include "stack.hpp"
#include <iostream>

using namespace std;

int main()
{
	try{
		Stack::stack s1 = Stack::create();
		Stack::push(s1,'t');
		Stack::push(s1,'e');
		
		Stack::destroy(s1);
		
		Stack::stack s2 = Stack::create();
		
		Stack::push(s2,'s');
		Stack::push(s2,'t');
		
		Stack::pop(s2);
	
		cout << Stack::pop(s2) << "\n";  //doit afficher 's'

		Stack::pop(s2);
		Stack::destroy(s2);
	}
	catch(Stack::Overflow) {
		cout << "Error overflow \n";
	}
	catch(Stack::Underflow) {
		cout << "Error underflow \n";
	}
}

4.b) Types définis par l'utilisateur

Choisissez les types dont vous avez besoin. Fournissez un ensemble complet d'opérations pour chaque type.

ex.

#include <iostream>

using namespace std;

class complex  {
	double re,im;
public:
	complex(double r, double i)
	{
		re=r;
		im=i;
	}
	complex(double r)
	{
		re=r;
		im=0;
	}
	complex()
	{
		re=im=0;
	}
	
	void affiche(){cout << "(" << this->re <<"+" << this->im << "i)";}
	
	friend complex operator+(complex,complex);
	friend complex operator-(complex,complex);
	friend complex operator*(complex,complex);
	friend complex operator/(complex,complex);
	
	friend complex operator-(complex); // moins unaire
	
	friend complex operator&(complex);   // conjugué
	
	friend complex operator==(complex,complex);
	friend complex operator!=(complex,complex);
};

main()
{
	complex a=2.3;
	complex b=7+2/a;
	complex c=a+b*complex(1,2.3);
	complex d=&a+2*c;
	d.affiche(); cout << "*"; c.affiche(); cout << " = "; (c*d).affiche(); cout << endl;
}

complex operator+(complex a, complex b)
{
	return complex(a.re + b.re, a.im + b.im);
}

complex operator-(complex a, complex b)
{
	return complex(a.re - b.re, a.im - b.im);
}

complex operator-(complex a)
{
	return complex(-a.re, - a.im);
}

complex operator*(complex a, complex b)
{
	return complex((a.re)*(b.re) - (a.im)*(b.im), (a.im)*(b.re) + (a.re)*(b.im));
}

complex operator/(complex a, complex b)
{
	return complex((a.re*b.re + a.im*b.im)/(b.re*b.re + b.im*b.im), (a.im*b.re - a.re*b.im)/(b.re*b.re + b.im*b.im));
}

complex operator&(complex a)
{
	return complex(a.re, - a.im);
}

complex operator==(complex a, complex b)
{
	return (a.re==b.re && a.im==b.im);
}

complex operator!=(complex a, complex b)
{
	return (a.re!=b.re || a.im!=b.im);
}

4.c) Types concrets

ex.

//stack.hpp

class Stack {
	char *v;
	int top;
	int max_size;
public:
	class Underflow{};
	class Overflow{};
	class Bad_size{};
	
	Stack(int);
	~Stack();
	
	void push(char c);
	char pop();
	
	void affiche();
};

//stack.cpp

#include <iostream>
#include "stack.hpp"

using namespace std;

Stack::Stack(int s)
{
	top=0;
	if(s<0 || 10000<s)
		throw Bad_size();
	max_size=s;
	v=new char[s];
}

Stack::~Stack()
{ 
	cout << "Destr. stack max_size" << this->max_size << endl; 
	delete[] v;
}

void Stack::push(char c)
{
	if (top==max_size)
		throw Overflow();
	v[top]=c;
	top=top+1;
}

char Stack::pop()
{
	if (top==0)
		throw Underflow();
	top=top-1;
	return v[top];
}

void Stack::affiche()
{
	for (int i=0; i<this->top; i++)
		cout << this->v[i] << " ";
	cout << endl;
}

//user.cpp

#include <iostream>
#include "stack.hpp"

using namespace std;

Stack s_var1(10);

void f(Stack& s_ref, int i)
{
	Stack s_var2(i);
	Stack* s_ptr = new Stack(3);
	
	s_ptr->push('d');
	s_ptr->push('e');
	s_ptr->push('f');
	s_ptr->affiche();
	delete s_ptr;
	s_var1.push('a');
	s_var1.pop();
	s_var2.push('b');
	s_ref.push('c');
	s_ref.affiche();
}

main(){
	try{
		s_var1.affiche();
		Stack s(5);
		s.push('r');
		s.affiche();
		f(s,5);
		s.affiche();
		s_var1.affiche();
	}
	catch(Stack::Bad_size)
		{cout << "Bad Size" << endl;}
	catch(Stack::Underflow)
		{cout << "Underflow" << endl;}
	catch(Stack::Overflow)
		{cout << "Overflow" << endl;}
}

4.d) Types abstraits

ex.

//main.cpp

#include "Array_stack.hpp"
#include "List_stack.hpp"

void f(Stack& s_ref); //interface avec "user.cpp"
class Bad_pop{};      //

void g()
{
	Array_stack as(200);
	f(as);
}

void h()
{
	List_stack ls;
	f(ls);
}

int main()
{   g();
    h();             
}

//user.cpp

#include "Stack.hpp"
#include<iostream>

class Bad_pop{};

void f(Stack& s_ref)
{
	s_ref.push('c');
	if(s_ref.pop() != 'c')
		throw Bad_pop();
	try{
        while(true)
                   s_ref.push('a');
        }
    catch(Stack::Overflow){std::cout << "Overflow\n";}
}

//stack.hpp

#ifndef _STACK_H_
#define _STACK_H_

class Stack {
public:
	class Underflow{};
	class Overflow{};
	
	virtual void push(char c)=0;
	virtual char pop()=0;
};
#endif

//arraystack.hpp

#include "Stack.hpp"

class Array_stack : public Stack {
	char* v;
	int max_size;
	int top;
	
public:
	class Bad_size{};

	Array_stack(int s);
	~Array_stack();
	
	void push(char c);
	char pop();
};

//liststack.hpp

#include "Stack.hpp"
#include <list>

using namespace std;

class List_stack : public Stack {
	list<char> lc;

public:
	List_stack(){}
	
	void push(char c)
	{
		lc.push_front(c);
	}
	char pop();
};

//arraystack.cpp

#include "Array_stack.hpp"

Array_stack::Array_stack(int s)
{
	top=0;
	if(s<0 || 1000<s)
		throw Bad_size();
	
	max_size=s;
	v=new char[s];
}

Array_stack::~Array_stack()
{
	delete[] v;
}

void Array_stack::push(char c)
{
	if(top==max_size)
		throw Overflow();
	
	v[top]=c;
	top++;
}

char Array_stack::pop()
{
	if(top==0)
		throw Underflow();
		
	top=top-1;
	return v[top];
}

//liststack.cpp

#include "List_stack.hpp"

char List_stack::pop()
{
	char x=lc.front();
	lc.pop_front();
	return x;
}