Ayuda, violación de segmento

Iniciado por antolinalvaro, 2 Diciembre 2018, 11:46 AM

0 Miembros y 1 Visitante están viendo este tema.

antolinalvaro

Buenos días.
¿Alguien sabe por que me da violacion de segmento (core generado) este código?
Incluyo tambien el fichero por si puede ayudar.

/*Incluyo las libreria stdio.h porque voy a usar ficheros*/
#include<stdio.h>
/*Añado la libreria string.h para poder usar strings o cadenas*/
#include<string.h>
/*Defino las longitudes maximas dpara vectores y cadenas de caracteres*/
#define DIMMAX 200
#define STRMAX 200
/*Realizo la primera funcion del programa, en la cual pido el nombre del fichero de lectura.
  Argumentos de entrada:
    char NombreFichero[]: Variable de tipo char donde tengo el nombre del fichero de lectura
    FILE* Fichero: Variable de tipo FILE donde esta el fichero de lectura de datos
  Argumentos de salida:
    No tiene
*/
void pedirNombre(){
  char NombreFichero[100];
  FILE* Fichero;
/*Uso un bucle do...while, para pedir el fichero hasta que se logre abrir*/
  do {
    printf("Dame el nombre del fichero: ");
    scanf("%s",NombreFichero);
    Fichero = fopen(NombreFichero,"r");
/*Si no lo logra abrir, se lo comunica al usuario por pantalla*/
    if(Fichero==NULL){
      perror("No se consiguio abrir el fichero\n");
    }
  } while(Fichero==NULL);
}
/*Hago la funcion principal, donde recopilo toda la informacion de mi programa*/
int main(){
  char NombreFich[STRMAX];
  FILE* Fich;
  float CantidadNumeros,Numeros[DIMMAX],SumaNumeros,Media;
  int i;
/*Llamo a la funcion anterior*/
  pedirNombre(&NombreFich,&Fich);
/*Abro el fichero de lectura de datos*/
  Fich = fopen(NombreFich,"r");
/*Inicializo las variables a 0 para el bucle, que me recorrera todo el fichero*/
  CantidadNumeros = 0;
  SumaNumeros = 0;
  i = 0;
  while(!feof(Fich)) {
/*Leo los numeros del fichero y los almaceno en un array flotante*/
    fscanf(Fich,"%f ",&Numeros[i]);
/*Sumo dichos numeros*/
    SumaNumeros = SumaNumeros + Numeros[i];
    i = i + 1;
    CantidadNumeros = CantidadNumeros + 1;
  } 
/*Calculo la media de los numeros y devuelvo la informacion por pantalla*/
  Media = SumaNumeros / CantidadNumeros;
  printf("En el fichero hay: %.0f numeros\nLa media de los numeros del fichero es: %f\n",CantidadNumeros,Media);
/*Cierro el fichero al acabar el programa*/
  fclose(Fich);
}


K-YreX

La función <pedirNombre()> dices que tiene argumentos de entrada pero en la implementación de la función no los tiene...
Código (cpp) [Seleccionar]

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

antolinalvaro

¿Quieres decir que he de declarar las variables entre los parentesis?

K-YreX

Tienes que poner los parámetros que le pasas a la función, claro.
Código (cpp) [Seleccionar]

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

antolinalvaro

Me sigue dando violacion de segmento

K-YreX

#5
Envía el código de tu programa a ver cómo has hecho los cambios.

Edit: Te escribo aquí un par de cosas más para agilizar esto. Hay dos formas de hacer lo que quieres hacer (bueno igual hay más pero te voy a comentar dos):
- Forma 1: Pasar el puntero a <FILE> como parámetro y que el fichero se abra en la función. Para ello hay que pasar el puntero por referencia y en C todo el paso de parámetros se hace por valor. Entonces no tienes que pasar un <FILE*>, sino un <FILE**>.

void pedirNombre(char nombreFichero[], FILE **fichero){
    do{
        printf("Nombre del fichero: ");
        scanf("%s", nombreFichero);
        *fichero = fopen(nombreFichero, "r");
        if(*fichero == NULL)
            perror("Error al abrir el archivo\n");
    }  while(*fichero == NULL);
}

int main(){
    char nombreFichero[STRMAX];
    FILE *fichero;
    pedirNombre(nombreFichero, &fichero);
    // ahora ya haces lo que quieras con <fichero> pues ya esta el fichero abierto
}


- Forma 2: Pasar como parámetro la cadena donde vas a guardar el nombre y hacer que la función devuelva <FILE*>. En ese caso tendrías que asignar el retorno de la función a una variable de tipo <FILE*>.

FILE* pedirNombre(char nombreFichero[]){
    FILE *fichero;
    do{
        printf("Nombre del fichero: ");
        scanf("%s", nombreFichero);
        fichero = fopen(nombreFichero, "r");
        if(fichero == NULL)
            perror("Error al abrir el archivo\n");
    }  while(fichero == NULL);
    return fichero;
}

int main(){
    char nombreFichero[STRMAX];
    FILE *fichero = pedirNombre(nombreFichero);
    // Y ahora ya haces lo que quieras con <fichero>
}


Ahora recomendaciones aparte:
- Usas una variable de tipo <float><cantidadNumeros> que siempre va a ser un entero ya que sumas de uno en uno y luego usas una variable tipo <int><i> que hace exactamente lo mismo que <cantidadNumeros>. Una de las dos sobra. Pensarás que para que en <media> se guarde un <float> ambos operandos deben ser <float> pero con que lo sea uno es suficiente, entonces con que <suma> sea de tipo <float>, la media también lo va a ser.

- Al finalizar el programa haces <%.0f> para mostrar la cantidad de números sin decimales. Usa <%d> que sirve para representar enteros y deja el <%.2f> por ejemplo para la media (o con los decimales que quieras).

- Para inicializar los contadores y sumas a 0 lo puedes hacer a la vez que los declaras y así lo haces de una vez. Porque si lo haces por separado puedes usar el valor de una variable antes de inicializarla por lo que tendría basura en ese momento.

- Tu programa también funciona si como has hecho tú abres el fichero en la función <pedirNombre()> y como no lo has pasado por referencia lo vuelves a abrir en el <main> pero es una solución un poco absurda tener que abrirlo en los dos sitios.

Corrige los fallos que tienes y fíjate en cómo están implementadas las dos formas de hacer la función que te he puesto arriba ya que tienen algunas sutiles diferencias por si hay algo que no entiendas. Suerte.
Código (cpp) [Seleccionar]

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

CalgaryCorpus

El nombre del archivo solo se usa para abrir este, no tiene otra utilidad, de modo que la funcion que lo abre podria llamarse, por ejemplo, abrirArchivo, no pasar ningun parametro y retornar el FILE*. Internamente puede definir la variable que guarda el nombre, no es necesario definirla en el main, pasarsela a la funcion y modificarla. Una excepcion seria que que despues el main la use para algo, pero no es el caso aqui.

FILE* abrirArchivo() {
    char nombre[ALGUN_TAMANO_AQUI];
    FILE* archivo;
    ..
    // pedir nombre, do-while, etc. usarlo para abrir el archivo

    return archivo;
}

int main() {
     FILE* archivo = abrirArchivo();

     // usar archivo

    return 0;
}
Aqui mi perfil en LinkedIn, invitame un cafe aqui