#Makefile para compilar todos los modulos
all: primers

llista.o:llista.cpp llista.h
	g++ -c llista.cpp

node.o:node.cpp node.h
	g++ -c node.cpp

ppal.o:ppal.cpp
	g++ -c ppal.cpp

primers:llista.o node.o ppal.o
	g++ llista.o node.o ppal.o -o primers

/****************************llista.cpp******************************/
#include "llista.h"

int llista::esFi()
{
	//pequenna diferencia con el programa que hace lo mismo en C
	//aqui miramos cuando act apunta a NULL, por tanto, nos
	//hemos pasado del final, el otro lo hace cuando estamos sobre
	//el ultimo numero, pero para el caso gracias a la raiz 
	//cuadrada da el mismo numero

	return (act == NULL);
}

llista::llista()
{
	//funcion constructora, ponemos los punteros a NULL

	pri = NULL;
	act = NULL;
	ult = NULL;
}

void llista::Insereix(int i)
{

	//inserimos al final de la lista

	node *n;
	//definimos el puntero al objeto

	n = new node(i);
	//instanciamos el objecto, pasandole de parametro el numero

	if (n != NULL) {
		//si hemos podido pedir memoria
		n->ModificaSeg(NULL);
		//siempre lo annadimos al final, valdra por tanto
		//NULL el puntero al siguiente


		if (pri == NULL) {
			//si pri==NULL estamos en una lista vacia

			pri = n;
			ult = n;
			act = n;
			//todo tiene que apuntar al nuevo numero

		} else {
			ult->ModificaSeg(n);
			//el que era ultimo antes tendra que apuntar
			//al nuevo ultimo               

			ult = n;
			//y ult tiene que apuntar al nuevo ultimo tambien
		}
	} else {
		cout << "Error de memoria" << endl;
		//nos ha faltado memoria
	}
}

void llista::VesPrincipi()
{
	act = pri;
	//rebobinamos la lista :-)
}

node llista::Consulta()
{
	return (*act);
	//devolvemos el node que apuntamos
}

int llista::ConsultaNum()
{
	node n;
	n = Consulta();

	return (n.ConsultaNum());
	//cojemos el node y devolvemos el numero que contiene
}

void llista::Avanca()
{
	act = act->ConsultaSeg();
	//avanzamos uno
}
/**************************llista.h******************************/
#ifndef _LLI
#define _LLI

#include "node.h"
#include <iostream.h>

//definiremos la clase que controla la lista

class llista {
	node *pri;
	node *act;
	node *ult;
	//3 punteros privados para el control

      public:
	 llista();
	//funcion constructora

	void VesPrincipi();
	//para ir al principio de la lista


	void Avanca();
	//para avanzar un numero


	node Consulta();
	//devuelve el node apuntado por act

	int ConsultaNum();
	//devuelve el numero apuntado por act

	void Insereix(int i);
	//inserta elementos

	int esFi();
	//asi sabremos si llegamos al final de la lista

};
#endif	/* _LLI */
/*****************************node.cpp**************************/
#include "node.h"

node::node()
{
	//constructor sin parametros, lo ponemos todo a 0
	seg = NULL;
	num = 0;
}

node::node(int i)
{
	seg = NULL;
	num = i;
	//asignamos el numero que nos pasan
}

int node::ConsultaNum()
{
	return num;
	//devolvemos el numero que contiene el node
}

node *node::ConsultaSeg()
{
	return (seg);
	//devolvemos el puntero al siguiente
}

void node::ModificaNum(int i)
{
	num = i;
	//por si necesitamos modificar el numero
}

void node::ModificaSeg(node * n)
{
	seg = n;
	//por si necesitamos modificar el puntero al siguiente elemento
}
/**************************node.h********************************/
#ifndef _NOD
#define _NOD

#include <iostream.h>

//definimos la clase node y las operaciones que podemos hacer con ella
class node { node *seg;
	int num;

      public:
	 node(int i);
	 node();
	int ConsultaNum();
	node *ConsultaSeg();
	void ModificaNum(int i);
	void ModificaSeg(node * n);
};

#endif
/****************************ppal.cpp************************/
#include "llista.h"
#include "node.h"
#include <iostream.h>

int esPrimer(int n, llista l);

void main()
{
	llista l;
	int n;

	l.Insereix(2);
	//inserimos el numero 2

	cout << "2-";
	//y lo imprimimos por pantalla

	n = 3;
	//empezaremos comprobando el numero 3

	l.VesPrincipi();
	//rebobinamos la lista

	while (n < 2000000) {
		//iremos hasta el numero 2 000 000

		if (esPrimer(n, l) == 1) {
			//si es primero, lo imprimimos y lo inserimos
			cout << n << "-";
			l.Insereix(n);

		}
		n = n + 2;
		//vamos comprobando los numeros impares
	}

}

int esPrimer(int n, llista l)
{
	int ret = 1;
	//pensamos que en principio es primero

	l.VesPrincipi();
	//rebobinamos

	while (ret == 1 && l.esFi() == 0
	       && l.ConsultaNum() * l.ConsultaNum() <= n + 1) {
		//mientras sea primero, no estemos en final de lista y estemos
		//comprobando un numero menor de la raiz cuadrada del numero a 
		//comprobar iremos haciendo

		if (n % l.ConsultaNum() == 0)
			ret = 0;
		//eps! no es primero
		else
			l.Avanca();
		//avanzamos
	}
	return ret;
}