Un programa con varias funciones y sin entradas

Iniciado por ciquee, 16 Mayo 2019, 20:42 PM

0 Miembros y 3 Visitantes están viendo este tema.

ciquee

Buenas!
YreX-DwX no entiendo muy bien el pseudocódigo que me pones para EsPrimo:

para i := 2 hasta numero-1
    si numero % i == 0
        return true
    fin si
fin para
return numero == 2


Acabando con return == 2 no devolverá siempre "2"?
¿Me la podrías explicar un poco más porfa?

Bueno, de momento he puesto la que decía string Manolo, que yo también sabía (aunque es contando los múltiplos y la tengo que cambiar) para probar el funcionamiento o no funcionamiento del programa. Y no sé que es lo que está mal pero este es mí código

#include <iostream>
#include <math.h>

using namespace std;

bool EsPrimo(unsigned long long);
unsigned long long Potencia (int);

int main(void) {
unsigned long long primo = 2, mersenne = 0, perf = 0;

while (perf < 10){

if (EsPrimo(primo)){
mersenne = Potencia(primo)-1;

if (EsPrimo(mersenne)){
perf = mersenne * Potencia(primo-1);
cout << perf << endl;
perf = perf + 1;
}
}
primo = primo + 1;
}

cin.get();
return 0;
}

// Esta funcion nos dice si un numero es primo o no
bool EsPrimo (unsigned long long num) {

int contador = 0;
bool es_primo = false;

for (int i=1; i < (num + 1); ++i)
{
if (num % i == 0)
{
contador++;
}
}

if (contador != 2)
{
return es_primo;
}

else
{
es_primo = true;
return es_primo;
}
}


// Esta función "Potencia" eleva una base entera (2) a una potencia entera y devuelva un 'unsigned long long
unsigned long long Potencia (int exponente){
unsigned long long res = 2;

for (int i = 1; i < exponente; i++){
res = res * 2;
}

return res;
}



Y no me saca nada más que los dos primeros números perfectos usando los primos de Mersenne, o sea el 6 y el 28 nada mas ¿que es lo que tengo mal?

K-YreX

Citar
Buenas!
YreX-DwX no entiendo muy bien el pseudocódigo que me pones para EsPrimo:

para i := 2 hasta numero-1
    si numero % i == 0
        return false
    fin si
fin para
return numero >= 2

¿Me la podrías explicar un poco más porfa?
Acabo de ver que le di la vuelta a lo que es ser primo en esa función por lo que no es correcta, ahora te la corrijo (está corregida en la cita)
Un número es primo si solo es divisible por si mismo y la unidad (no se considera al 1 primo). Entonces en vez de contar los divisores desde 1 hasta n y comprobar si el número de divisores es 2 (es primo) o es >2 (no primo); lo que hacemos es evitar esas dos divisiones. En lugar de empezar en 1 hasta n, empezamos en 2 hasta n-1. De esta forma se define como número primo todo aquel número que no es divisible por ningún número entre 2 y n-1 (excepto el 2 que es divisible por 2 y es primo).
El 1, en cambio, no es primo y el bucle no llega a ejecutarse para números < 3. Entonces en caso de que el bucle no se ejecute (esto sucede si los números son 1 o 2) tenemos que el 1 no es primo y el 2 sí.
Para tratar esa excepción usaremos <return (numero >= 2)> (date cuenta de que es una expresión booleana cuyo valor siempre es true/false, no son asignaciones).
Funcionamiento:
Se ejecuta el bucle (para números > 2) y si encuentra un divisor devuelve <false> (fallo mío que puse <true> lo voy a corregir en los otros mensajes) .
Si no encuentra un divisor podemos tener 2 motivos:
  • El número es < 3: {0, 1, 2} en cuyo caso el único primo es el 2
  • El número es > 2 y es primo: {3, 5, 7, 11, ...}
    Entonces con la condición <return (numero >= 2)> obtendremos <true> (para el 2 y todos los primos) y <false> (para el 0 y el 1). Ahora sí está correcta la función y disculpas por el error... :-X


    Citar
    Y no me saca nada más que los dos primeros números perfectos usando los primos de Mersenne, o sea el 6 y el 28 nada mas ¿que es lo que tengo mal?
    Eso es porque estás usando la variable <perf> para guardar la cantidad de números perfectos que llevas y el número perfecto actual. Entonces en el momento que el número perfecto supera el 10 (28 en este caso) termina. Usa dos variables distintas, una para el número perfecto y otra para la cantidad de números perfectos que llevas.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

ciquee

Por fin lo conseguí!!í Muchas gracias!! Aunque solo me saca 8 números perfectos, pero a todos los compañeros les pasa igual, del 7º al 8º tarda bastante, igual si lo dejo mucho tiempo mas saca el 9º y el 10º o igual mi ordenador no es potente ni para eso! jajja.

Bueno, ahora estoy con otro ejercicio que lo tengo casi casi, o eso creo, del mismo estilo, aunque sin formulas ni nada, solo que se han de usar mas funciones para estructurarlo. El enunciado me pide esto:

Realiza un programa en C++ que lea números enteros de un fichero y nos diga de cada uno de ellos si es primo o no lo es, utilizando en este la función EsPrimo que hiciste para un ejercicio anterior. El programa principal debe seguir
el siguiente esquema:


void AnalizarFichero(string nombre);
int main (void)
{
int num;
MostrarPresentacionPrograma ();
num = PedirNumeroPositivo ();
if (EsPrimo (num) )
cout << "El numero es primo.\n";
else
cout << "El numero NO es primo.\n";
return 0;
}
void AnalizarFichero(string nombre)
{
// Abrir Fichero
...
// Comprobar la correcta apertura del
// fichero
...
// Mientras sea posible leer
// un entero num del fichero
...
if (EsPrimo (num) )
{
cout << "El numero " << num;
cout << " es primo.\n";
}
else
{
cout << "El numero " << num;
cout << " NO es primo.\n";
}
// Cerrar Fichero
return;
}


Y la salida debería ser algo así:
Este programa determina si los numeros enteros positivos de un fichero son o no primos
- Dame nombre del fichero: enteros.dat
- El numero 23 es primo
- El numero 6 NO es primo
- El numero 3 es primo
- El numero 27 NO es primo
- El numero 20 NO es primo

Vale, y ahora va lo que yo tengo hecho:


#include <iostream>
#include <fstream>

using namespace std;

void AnalizarFichero(string);
int PedirNumeroPositivo (int);
bool EsPrimo(int);
void MostrarPresentacionPrograma (void);

int main (void) {

int num;
MostrarPresentacionPrograma ();
void AnalizarFichero (string nombre);
num = PedirNumeroPositivo (num);
if (EsPrimo (num) == 1)
cout << "El numero es primo.\n";
else
cout << "El numero NO es primo.\n";

cin.get();
return 0;
}


void AnalizarFichero(string nombre) {
ifstream archivo;
string nombreArchivo;

cout << "Introduzca el nombre del archivo: " << endl;
getline (cin,nombreArchivo);

archivo.open (nombreArchivo.c_str());

if(!archivo){
cout << "No se pudo abrir el archivo" << endl;
}

while (!archivo.eof())
{

archivo.close ();
return;
}


int PedirNumeroPositivo(int num) {
string archivo;

archivo >> num;
}

return 0;
}


int MostrarPresentacionPrograma (int){

cout << "Este programa determina si los numeros enteros positivos de un fichero son o no primos" << endl;

return num;
}


bool EsPrimo (int num) {
bool es_primo = false;

for (int i = 2; i <= num-1; i++){
if (num % i == 0){
return false;
}
}

return num >= 2;
}


Creía que le había pillado ya el truquillo a trabajar con varias funciones, pero cuando entran en juego más de 2 me pierdo. Además de que me lio a la hora de declararlas, y no sé como hacerlo bien, por ejemplo aquí seguro que tengo mal alguna (espero que no todas!). En la función PedirNumeroPositivo no tengo ni idea de como hacerlo, teniendo en cuenta que se lo pedimos a un archivo, y como lo he hecho no puede ser porque la función no conoce a "archivo".

Espero que me podáis orientar un poco por favor!!
Gracias!!

K-YreX

Para problemas diferentes mejor abrir un tema nuevo Por si a alguien más le interesa uno de los dos temas...
Lo primero que tienes que pensar es qué funciones quieres usar. Es decir, piensa quiero una función que haga tal cosa y luego piensa cómo implementarla, por ejemplo, quiero una función que me diga si el fichero se pudo abrir correctamente.
  • Qué necesito? Pasarle el nombre del fichero o el propio fichero (yo diría que mejor el nombre).
    Código (cpp) [Seleccionar]

    <retorno> ficheroAbiertoCorrectamente(string nombre_fichero);

    Ahora miramos el retorno.
  • Qué va a hacer la función? Dos posibilidades:
    - El fichero se abre correctamente.
    - El fichero no se abre correctamente.
    Idea 1:
    Código (cpp) [Seleccionar]

    bool ficheroAbiertoCorrectamente(string nombre_fichero);
    // Comprueba si se abrio bien y devuelve true si se abrio bien o false si no se abrio
    // Problema: Tenemos que abrir el fichero en la funcion para comprobar si se abrio bien y al salir de la funcion volver a abrirlo otra vez

    ifstream abrirFichero(string nombre_fichero);
    // Comprueba si se pudo abrir el fichero y en caso de que si, lo devuelve abierto
    // Problema: y si no lo pudo abrir? Tendremos que hacer que el programa termine si no se pudo abrir

    Si quieres puedes pensar tu propia alternativa, no tiene que ser una de esas dos, pero es para que te hagas una idea. Haz eso con cada función que vayas a crear. Piensa en grande, es decir, piensa en que cada función tiene que hacer una cosa específica y de la mejor forma posible.

    Un truco es escribir el <main> de forma que se entienda a simple vista, por ejemplo:
    Código (cpp) [Seleccionar]

    int main(){
        fichero = abrirFichero();
        numero = leerNumero();
        if(esPrimo(numero))
            cout << numero << " es primo" << endl;
        else
            cout << numero << " no es primo" << endl;
    }

    Y en base a eso crear las funciones añadiendo los parámetros que veas que necesitas, poniendo los retornos que necesitas, etc.
    Tampoco te pases con las funciones, es decir, no empieces a meter una función dentro de otra y esta dentro de otra... Porque se hará demasiado lioso y no te valdrá la pena encapsular tanto. Tienes que encontrar el término medio. Piensa que una función es un trozo de código que puedes usar muchas veces en diferentes programas. Haz funciones que sean reutilizables.
    Por ejemplo, puedes pensar en hacer una función que te muestre por pantalla si un número es primo o no, pero... y si en algún momento quieres saber si el número es primo pero no quieres mostrarlo por pantalla? (como en tu ejercicio anterior). Pues mejor hacer una función que te diga si es primo o no, sin mostrar nada y tú verás en cada situación si quieres mostrar por pantalla el resultado obtenido o no.

    Comenta los avances que consigas empleando esta técnica y cuando pueda te seguiré ayudando. Suerte :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

ciquee

Buenas! Gracias YreX-DwX! y perdón por no abrir un nuevo tema, pero como es un ejercicio que trata de lo mismo que el anterior... no lo volveré a hacer!

Con tu explicación he entendido más o menos lo de los retornos y las funciones que quiero que haga cada función, aunque en este ejercicio está claro las funciones a utilizar porque me lo piden en el enunciado.
- La función MostrarPresentacionPrograma creo que esta claro que debe ser void ya que no nos devuelve nada, solo nos tiene que mostrar los "cout".
- La función AnalizarFichero qué creo que también puede ser void ya que necesitamos que nos abra el fichero solamente.
- La función PedirNumeroPositivo (que más bien se debería llamar CogerNumeroPositivo) ya que los va a extraer del fichero, la cual debe retornar un int.
- Y la función EsPrimo, la cual ya tenemos, y será bool.

Vale, la función EsPrimo ya la tengo, y las demás por más vueltas que le dé no consigo hacerlas. Además, la función AnalizarFichero me abre el fichero pero también me lo cierra, no sé cómo hacer para que lo deje abierto (porque podría obviar la linea de archivo.close() pero luego de pasarle la siguiente función PedirNumeroPositivo ¿cómo la cierro?).

Con la función PedirNumeroPositivo tampoco sé cómo proceder, ya que como tiene que ser independiente de las demás debería abrir el archivo dentro de esta para poder coger los números positivos. Y esto que yo he hecho como que no lo veo...


int PedirNumeroPositivo(int num) {
string archivo;

archivo >> num; // Guardamos en num un numero entero del fichero
}

return 0;
}


En cuanto a la función "MostrarPresentacionPrograma" bastaría con un cout que diga lo que va a hacer el programa ¿no? algo así...:


void MostrarPresentacionPrograma (){

cout << "Este programa determina si los numeros enteros positivos de un fichero son o no primos" << endl;

return 0;
}


Y luego una duda que me surge a la hora de hacer las funciones, mi profesor califica de "Mala práctica" el utilizar más de un Return en cada función, y en por ejemplo en la función EsPrimo (utilizada ya en el ejercicio anterior) he usado 2, pero no sabría como hacerla sin ambos ¿sabes porque es una mala práctica?

@XSStringManolo

Si declaras una función como void no puede retornar un valor y tu le tienes return 0 Si quieres que retorne usa int, short. bool o lo que necesites.
El tipo que ponga la funcion es lo que tiene que devolver.
En el caso de void no hay return.

Te voy a dejar codigos de ejemplos en un documento de apuntes que estoy haciendo. Así ves diversos métodos y como no abuso del return:

Código (cpp) [Seleccionar]

//Pasar parametros a funciones:
void imprimirSuma(int sumando1, int sumando2)
{
cout sumando1+sumando2;
}

int main()
{
imprimirSuma(3,5);
return 0;
}


//Retornar Valores:
int retornarSuma(int sumando1, int sumando2)
{
return sumando1+sumando2;
}

int main()
{
int sum = retornarSuma(3,5);
cout<<sum;
return 0;


//Pasar por punteros:
void retornarSuma(int sumando1, int sumando2, int* retornarValor)
{
*retornarValor = sumando1+sumando2;
}

int main()
{
int suma=0;
retornarSuma(sumando1,sumando2, &suma)
cout <<suma;
return 0;
}


//Pasar por referencia:
void retornarSuma(int sumando1, int sumando2, int& retornarValor)
{
retornarValor = sumando1+sumando2;
}

int main()
{
int suma =0;
retornarSuma(sumando1, sumando2, suma)
cout << suma;
return 0;
}



//Pasar estructuras. Esto te lo dejo para que no te suene a chino si te lo piden en algun momento.
struct ParametrosParaSumar
{
int a;
int b;
int resultado;
};

void sumarNumeros(ParametrosParaSumar& parametros)
{
parametros.resultado = parametros.a + parametros.b;
}

int main()
{
ParametrosParaSumar suma;
suma.a = 3;
suma.b = 6;
suma.resultado = 0;

sumarNumeros(suma); //Se pasa suma por referencia

cout << suma.resultado;
return 0;
}



Que funciones tienes que hacer que no te salen? Te ayudo.

Por cierto te recomiendo que vayas por adelantado a la clase? Así te sirve de repaso, entenderás lo que no te quedó claro en casa y podrás hacer preguntas a cerca de cosas que te surgan.
Si vas al día de la clase no te enterarás de nada de lo que te expliquen hasta que llegues a casa y te rompas los codos. A parte no habrás preguntado dudas que te van a surgir durante los ejercicios y no vas a encontrar la respuesta en casa. Solo te romperás la cabeza y perderás el tiempo.
Si haces esto un par de semanas verás como la constumbre de llevar las cosas por adelantado no se te pierde nunca. Podrás ayudar a los compañeros, estarás menos estresado y podrás tener una mejor relación con tu profesor al ver este que tienes interés, y sentirá que está haciendo las cosas bien motivando al alumnado. A parte de que podrás intimar mejor con la programación y dejarás de verla como un jodecabezas xD Dale una oportunidad ahora que aún estás al principio, lo agradecerás mucho cuando empieces con Plantillas, Clases, Metodos, Objetos... Porque son temas que se suelen dar practicamente juntos.

Te recomiendo un libro sencillo e interesante con explicaciones claras y concisas llamado Apress Learn C++ for Game Development 2014.

Después puedes ir a algo más teórico y extenso como C++ Primer fifth edition. O a algo mas práctico teórico como Programing Principles and Practice using C++.

K-YreX

Citar
Y luego una duda que me surge a la hora de hacer las funciones, mi profesor califica de "Mala práctica" el utilizar más de un Return en cada función, y en por ejemplo en la función EsPrimo (utilizada ya en el ejercicio anterior) he usado 2, pero no sabría como hacerla sin ambos ¿sabes porque es una mala práctica?
Se considera mala práctica en ocasiones porque puede que se te olvide algún <return>. Para evitar esto se suele usar una variable de tipo <bool> (la que tú habías creado en tu código "es_primo" pero que no usabas en la función).
Código (cpp) [Seleccionar]

bool esPrimo(unsigned int numero){
    bool es_primo = true; // suponemos que es primo
    size_t i = 2;
    while(i < numero and es_primo){ // mientras i < numero y numero sea primo
        es_primo = (numero % i != 0); // es primo si el resto es distinto de 0
        i++;
    }
    // llegas aqui cuando i == numero o cuando es_primo = false
    return es_primo;
}



La función para mostrar la presentación del programa está casi bien. Está bien que sea de tipo <void> pero las funciones de tipo <void> no retornan nada. Siempre pones un <return 0>  en todas las funciones y eso solo se pone en el <main>. No tiene sentido hacer funciones que siempre devuelvan 0 y menos si son de tipo <void>.


La función <AnalizarFichero()> es mejor que le añadas algo más como una de las opciones que te di en el mensaje anterior:
Citar
Código (cpp) [Seleccionar]

bool ficheroAbiertoCorrectamente(string nombre_fichero);
// Comprueba si se abrio bien y devuelve true si se abrio bien o false si no se abrio
// Problema: Tenemos que abrir el fichero en la funcion para comprobar si se abrio bien y al salir de la funcion volver a abrirlo otra vez

ifstream abrirFichero(string nombre_fichero);
// Comprueba si se pudo abrir el fichero y en caso de que si, lo devuelve abierto
// Problema: y si no lo pudo abrir? Tendremos que hacer que el programa termine si no se pudo abrir
Yo por ejemplo usaría la segunda opción. Si se abre el fichero correctamente, lo devuelve como parámetro y sino termina el programa con <exit()> (de <cstdlib>).


La función <leerNumero()> la haría que reciba el fichero y devuelva el siguiente valor a leer.
Código (cpp) [Seleccionar]

int leerNumero(ifstream &fichero);
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

ciquee

Muchas gracias a los dos! Manolo me apunto tus apuntes y libros! Y gracias por el consejo, se hace lo que se puede, estoy haciendo la carrera ya un poco mayor y además soy deficiente visual así que me entero más buscando por mi cuenta y preguntando por aquí después de clase, no lo puedo hacer de otra manera... pero muchas gracias!

A ver, pues yo sigo atascado, porque mi principal bloqueo es al dividir en dos funciones las tareas de abrir un fichero, y leer de este mismo. Y es que por más que lo miro y le doy vueltas no sé hacer lo que me dices YreX-DwX, no sé como es eso de devolver como parámetro. Si me lo pudierais explicar... además luego como cierro el fichero?

Y respecto al resto de funciones a ver como están ahora, he hecho algún cambio pero no se...


#include <iostream>
#include <fstream>

using namespace std;

bool AnalizarFichero(string);
int PedirNumeroPositivo (int);
bool EsPrimo(int);
void MostrarPresentacionPrograma (void);

int main (void) {

int num;
MostrarPresentacionPrograma ();
bool AnalizarFichero (string nombre);
num = PedirNumeroPositivo (num);
if (EsPrimo (num) == 1)
cout << "El numero " << num << "es primo.\n";
else
cout << "El numero " << num << " NO es primo.\n";

cin.get();
return 0;
}


bool AnalizarFichero(string) {
ifstream archivo;
string nombreArchivo;

cout << "Introduzca el nombre del archivo: " << endl;
getline (cin,nombreArchivo);

archivo.open (nombreArchivo.c_str());

if(!archivo){
return 0;
}

else {
PedirNumeroPositivo(int num);
}

archivo.close ();
}


int PedirNumeroPositivo(int num) {
string archivo;

while (!archivo.eof())
{
archivo >> num;
}
}


void MostrarPresentacionPrograma (){
cout << "Este programa determina si los numeros enteros positivos de un fichero son o no primos" << endl;
}


bool EsPrimo (int num) {
bool es_primo = false;
for (int i = 2; i <= num-1; i++){
if (num % i == 0){
return false;
}
}

return num >= 2;
}


A ver qué me decís!!

K-YreX

No voy por orden, la verdad no sé por qué pero te voy comentando las funciones:
Citar
Código (cpp) [Seleccionar]

bool EsPrimo (int num) {
    bool es_primo = false;   
    for (int i = 2; i <= num-1; i++){
       if (num % i == 0){
           return false;
       }
    }
    return num >= 2;
}
En esta función estás creando una variable <bool es_primo = false> que no llegas a usar. Si la creas es para usarla y no usar más de 1 <return> en ese caso como ya te dije, la función quedaría así:
Código (cpp) [Seleccionar]

bool esPrimo(unsigned int numero){
    bool es_primo = true; // suponemos que es primo
    // for(size_t i = 2; i < numero and es_primo; ++i){ // se puede poner asi o como viene a continuacion
    // el for o el while depende de si quieres/te dejan poner dos condiciones dentro del for
    size_t i = 2;
    while(i < numero and es_primo){ // mientras i < numero y numero sea primo
        es_primo = (numero % i != 0); // es primo si el resto es distinto de 0
        i++;
    }
    // llegas aqui cuando i == numero o cuando es_primo = false
    return es_primo;
}

Aquí ves que solo haces un <return> ya que usas la variable <es_primo> como condición de salida o de fin. En el momento que sabes que no es primo, terminas el bucle y retornas el valor que es <false> en ese caso. Si es primo hasta el final, retornas la misma variable que en este caso valdrá <true>.
La línea:
Código (cpp) [Seleccionar]

es_primo = (numero % i != 0);

Es lo mismo que poner:
Código (cpp) [Seleccionar]

if(numero % i == 0)
    es_primo = false;

Por si así lo ves mejor.

En mi caso le estoy pasando como parámetro un <unsigned int numero>, es decir, que no tiene signo, por lo que siempre va a ser positivo. Si a esa función le pasas un <int> (puede ser negativo) te va a salir que cualquier número negativo es primo. Tenlo en cuenta. Esto lo puedes arreglar poniendo:
Código (cpp) [Seleccionar]

bool es_primo = num > 0;
// donde pone
bool es_primo = true;

Para considerar los negativos como no primos. Esto ya a tu gusto o al nivel de lo que te pidan.


Siguiente función:
Citar
Código (cpp) [Seleccionar]

int PedirNumeroPositivo(int num) {
    string archivo;
    while (!archivo.eof()){
        archivo >> num;
    }
}
Aquí tienes varios problemas. Uno es que no puedes aplicar la función <eof()> a <archivo> que es un <string>. Además <num> no es algo que necesites pasar como parámetro. Y esa función retorna un <int> y ahí no retorna nada.
Para poder usar esta función, la función debe conocer el fichero (ifstream) <archivo>. Entonces eso necesitas pasarlo como parámetro. El <num> lo creas dentro de la función y lo retornas al finalizar esta.
Código (cpp) [Seleccionar]

int devolverNumero(ifstream &fichero){
    int numero = 0; // le ponemos un 0 (o lo que queramos) para saber que cuando retorne ese valor es porque el fichero ha llegado a su fin
    if(!fichero.eof())
        fichero >> numero;
    return numero;
}

Esta función devuelve el siguiente número del fichero de entrada <fichero> o 0 si ha llegado al final del fichero. La posición en la que vas del fichero se guarda. Entonces cada vez que llames a esta función, devolverá el número siguiente al que retornó la última vez.
El tema de dónde cerrar el fichero te lo comento más abajo.


La siguiente función es la de <AnalizarFichero()>. Aquí tienes dos opciones que yo veo buenas y no muy complicadas:
  • Opción 1: Pasar el <ifstream> por referencia y devolver un <bool> de si se abrió correctamente o no.
    Parámetros necesarios: ifstream &fichero (le podríamos pasar también el string con el nombre del fichero o se lo podemos pedir dentro de la función al usuario)
    Retorno de la función: bool fichero_correcto
    Código (cpp) [Seleccionar]

    bool analizarFichero(ifstream &fichero){
        string nombre_fichero;
        bool fichero_correcto = true; // suponemos que se va a abrir bien...
        // pedimos el nombre del fichero
        fichero.open(nombre_fichero.c_str());
        if(!fichero) // ...y si no es asi, cambiamos el valor a esa variable <fichero_correcto>
            fichero_correcto = false;
        return fichero_correcto;
    }

    Si quieres pedir el nombre del fichero en el <main> y pasarlo como parámetro, te recomiendo que lo intentes tú. Incluso aunque no lo vayas a usar así, leyendo código no se aprende, se aprende escribiendo código porque ahí es dónde se ven los errores que comete uno y que en código ajeno no ve.
  • Opcion 2: Pasar el nombre como parámetro (o no pasar nada y pedirlo dentro de la función) y retornar un fichero abierto.
    En este caso podemos hacerlo simple, recibimos el nombre como parámetro, creamos un <ifstream> con dicho nombre y lo devolvemos y se acabó.
    Código (cpp) [Seleccionar]

    ifstream abrirFichero(string nombre_fichero){
        ifstream fichero(nombre_fichero.c_str()); // lo mismo que crear el fichero y hacer fichero.open(...)
        // podemos hacer que si el fichero no es valido, termine el programa
        if(!fichero)
            exit(1); // exit termina el programa desde cualquier funcion en la que se ejecute. Pertenece a la libreria <cstdlib>
        // y si no se cumple la condicion anterior, devolvemos el fichero
        return fichero;
    }


    También podemos pedirle nombres al usuario hasta que uno sea correcto:
    Código (cpp) [Seleccionar]

    ifstream abrirFichero(){
        ifstream fichero; // aqui como no conocemos el nombre del fichero todavia usamos open(...) mas abajo
        string nombre_fichero;
        do{ // hacer esto de dentro...
            // pedir nombre fichero y guardarlo en nombre_fichero
            fichero.open(nombre_fichero);
        }   while(!fichero); // ... mientras el fichero no se haya abierto
        // llegamos aqui cuando por fin se ha abierto un fichero de entrada. Entonces lo devolvemos
        return fichero;
    }


    Puedes crear muchas alternativas más, como a ti se te ocurran. Así que te dejo que sigas investigando por tu cuenta. No te limites o copiar y pegar lo que yo he hecho porque así no vas a saber el porqué de cada cosa que hice, ni vas a ver los fallos que cometes al hacerlo tú.


    Por último te dejo algún ejemplo de <main> para que veas como usar las funciones:
    Código (cpp) [Seleccionar]

    int main(){
        // si le vamos a pasar el nombre del fichero como parametro, tendremos que declararlo aqui y pedirselo al usuario
        // como abrir el fichero usando <ifstream abrirFichero()> (el ultimo ejemplo)
        ifstream fichero = abrirFichero(); // sin parametros porque dentro de la funcion es donde le pediremos al usuario el nombre del fichero
        // cuando estemos aqui el fichero ya esta bien abierto
        // como sabemos segun la funcion <int devolverNumero(ifstream &fichero)> que hice arriba que retorna 0 cuando el fichero termina hacemos...
        int numero = devolverNumero(fichero);
        while(numero != 0){
            cout << "El siguiente numero es: " << numero << endl;
            if(esPrimo(numero)) // no hace falta poner == 1 o == true. Ya se entiende si no se pone nada que tiene que valer 1/true
                cout << "El numero " << numero << " es primo" << endl;
            else
                cout << "El numero " << numero << " no es primo" << endl;
            numero = devolverNumero(fichero);
        }
        // el fichero abierto es <fichero> entonces lo cerramos aqui
        fichero.close(); // si se te olvida y no lo cierras tu, ya lo hace el programa al terminar
    }


    Dale vueltas a todo esto que no es poco y practica. Es posible que me haya comido alguna palabra o me haya confundido al escribir algo pero no me apetece revisar todo el mensaje. Suerte :-X :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

ciquee

Nada, ya le puedo dar todas las vueltas que quiera que me da errores con la función AnalizarFichero y PedirNumeroPositivo. Yo no me limito a copiar y pegar, como bien dices para aprender hay que entender el código, pero no entiendo porque me da error, pongo en negrita los errores que me indica mi programa:


#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

void MostrarPresentacionPrograma (void);
ifstream AnalizarFichero(string);
int PedirNumeroPositivo (ifstream);
bool EsPrimo(int);


int main (void) {

int num;
MostrarPresentacionPrograma ();
ifstream fichero = AnalizarFichero(string);
[b]num = PedirNumeroPositivo (ifstream);[/b]

while (num != 0){
if (EsPrimo (num) == 1)
cout << "El numero " << num << "es primo.\n";
else
cout << "El numero " << num << " NO es primo.\n";
[b]num = PedirNumeroPositivo(fichero);[/b]
}

fichero.close();
cin.get();
return 0;
}


ifstream AnalizarFichero(string nombreFichero) {
ifstream fichero;

cout << "Introduzca el nombre del fichero: " << endl;
getline (cin,nombreFichero);

fichero.open (nombreFichero.c_str());

if(!fichero){
exit (1);
}

return fichero;
}


int PedirNumeroPositivo(ifstream fichero) {
int numero = 0;

if(!fichero.eof())
fichero >> numero;

return numero;
}

void MostrarPresentacionPrograma (){
cout << "Este programa determina si los numeros enteros positivos de un fichero son o no primos" << endl;
}


bool EsPrimo (int num) {
for (int i = 2; i <= num-1; i++){
if (num % i == 0){
return false;
}
}

return num >= 2;
}


No he cambiado la función EsPrimo porque he estado probando con la que me dices y no me da bien algunos resultados, pero no pasa nada, dejo esta que tengo quitando la variable que no usaba.

Y también he probado a hacer la función AnalizarFichero de esta otra forma y nada...

bool AnalizarFichero(ifstream &fichero) {
string nombreFichero;
bool fichero_ok = true;

cout << "Introduzca el nombre del fichero: " << endl;
getline (cin,nombreFichero);

fichero.open (nombreFichero.c_str());

if(!fichero){
fichero_ok = false;
}

return fichero_ok;
}


Y respecto a a la función MostrarPresentacionPrograma ¿esta bien ahora? porque no entiendo muy bien para que sirve, ya que no es reutilizaba para otros programas ni nada, y me cuesta menos poner un cout con lo que hace el programa que llamar a la función... no se...