Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: David8 en 10 Abril 2014, 08:30 am



Título: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 08:30 am
Muy buenas de nuevo. Estoy haciendo un programa ( muy básico ) en el que se debe introducir un número de alumnos, luego pedir una calificación a cada uno en el intervalo [0, 10], y por último clasificar el número de aprobados, notables, etc. TODO CON ENTEROS.
De momento llevo lo siguiente:

Código:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>

#define TAMANIO 10

int verificarEntrada(const char *ptrX);

int verificarEntrada(const char *ptrX)
{
for(; *ptrX != '\0'; ptrX++){
if(isdigit(*ptrX) == 0){
puts("->Entrada no permitida.");
return 0;
}
}

return 1;
}

int main(void)
{
char nAlumnos[TAMANIO];
int alumnos;
int longitud;
int x;   // valor que devuelve la función verificarEntrada()
int i;
char *notas[alumnos];
int notasEnteras[alumnos];


do{
printf("Numero de alumnos: ");

fgets(nAlumnos, TAMANIO, stdin);   // si introducimos 9 o más caracteres se produce OVERFLOW en el buffer

longitud = strlen(nAlumnos);

if(nAlumnos[longitud-1] == '\n'){   // si la cadena tiene una longitud menor a TAMANIO-1 evitamos la "impresión de '\n'
nAlumnos[longitud-1] = '\0';
}

x = verificarEntrada(nAlumnos);

puts("");

if(x == 1){
alumnos = atoi(nAlumnos);
}

} while(x == 0);

for (i = 0; i < alumnos; i++){
do{
notas[i] = malloc (TAMANIO * sizeof (char));
 
       printf("Nota alumno %d : ", i + 1);
       scanf("%[^\n]", notas[i]);
       while(getchar() != '\n');
      
       x = verificarEntrada(notas[i]);

if(x == 1){
int n = atoi(notas[i]);

if(n < 0 || n > 10){   // cada nota debe estar comprendida en el intervalor [0, 10]
x = 0;
}
else{
notasEnteras[i] = atoi(notas[i]);
}
}

} while(x == 0);
   }


return EXIT_SUCCESS;
}

El problema es que compila pero en cuanto se abre la consola se termina el proceso.
No encuentro que puede estar mal.
Agradecería mucho indicaciones de cómo mejorar un poco el código (ya que lo veo un poco desastroso, sobre todo en la declaración de variables  ;D )

Gracias.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: amchacon en 10 Abril 2014, 12:44 pm
¿Que IDE usas?

En el codeblocks si pulsas F8 activas el depurador, y puedes avanzando el programa línea a línea. Así ves donde el programa "estalla".

Otra opción es ir poniendo printfs por el código y ver cuantos printfs llega a escribir antes de que de error, pero el depurador es una tecnica un poco chapucera xD


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 13:20 pm
Uso el dev c++
Pero el problema es que no ejecuta nada, es decir, doy a compilar y bien, pero al ejecutar en cuanto aparece la consola sale un mensaje de error de Windows

No ves nada que pueda estar mal en el código? Estoy casi seguro de que falla en alguna parte dentro del for, pero no sé el qué...

Un saludo


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: amchacon en 10 Abril 2014, 13:35 pm
Uso el dev c++
Pero el problema es que no ejecuta nada, es decir, doy a compilar y bien, pero al ejecutar en cuanto aparece la consola sale un mensaje de error de Windows

No ves nada que pueda estar mal en el código? Estoy casi seguro de que falla en alguna parte dentro del for, pero no sé el qué...

Un saludo
Te lo he dicho, tienes que averiguar en que línea te da el problema.

Hazme caso y pon printfs cada 3-4 líneas de código:

Código
  1. int main(void)
  2. {
  3.        printf("1 - Inicio \n");
  4. char nAlumnos[TAMANIO];
  5. int alumnos;
  6. int longitud;
  7. int x;   // valor que devuelve la función verificarEntrada()
  8. int i;
  9. char *notas[alumnos];
  10. int notasEnteras[alumnos];
  11.  
  12.        printf("2 - Tras declarar las variables \n");
  13.  
  14.        // Etc...
  15.  

Solo tienes que ver el último printf que escribes, y sabrás por donde falla (da igual que te salga error de Windows, los printfs los veras igual).

PD: Por cierto, usas la variable "alumnos" pero no está inicializada.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 13:51 pm
Te lo he dicho, tienes que averiguar en que línea te da el problema.

Hazme caso y pon printfs cada 3-4 líneas de código:

Código
  1. int main(void)
  2. {
  3.        printf("1 - Inicio \n");
  4. char nAlumnos[TAMANIO];
  5. int alumnos;
  6. int longitud;
  7. int x;   // valor que devuelve la función verificarEntrada()
  8. int i;
  9. char *notas[alumnos];
  10. int notasEnteras[alumnos];
  11.  
  12.        printf("2 - Tras declarar las variables \n");
  13.  
  14.        // Etc...
  15.  

Solo tienes que ver el último printf que escribes, y sabrás por donde falla (da igual que te salga error de Windows, los printfs los veras igual).

PD: Por cierto, usas la variable "alumnos" pero no está inicializada.


Probaré lo de los prints.

Respecto a lo de alumnos, si quiero usar correctamente
Código:
char *notas[alumnos];
int notasEnteras[alumnos];
debería de declararlos una vez que tenga alumnos definido no? Es decir, antes del for)

Muchas gracias y un saludo


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: amchacon en 10 Abril 2014, 13:57 pm
Si, cuando ya lo tengas inicializado.

Los arrays variables mejor con malloc por cierto.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 14:02 pm
Si, cuando ya lo tengas inicializado.

Los arrays variables mejor con malloc por cierto.

Código:
int v;
char *notas[v] = malloc(alumnos * sizeof (char));

Así?


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 18:26 pm
Si, cuando ya lo tengas inicializado.

Los arrays variables mejor con malloc por cierto.

Hice lo que me dijiste y el código me queda así:

Código:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>

#define TAMANIO 10

int verificarEntrada(const char *ptrX);

int verificarEntrada(const char *ptrX)
{
for(; *ptrX != '\0'; ptrX++){
if(isdigit(*ptrX) == 0){
puts("->Entrada no permitida.");
return 0;
}
}

return 1;
}

int main(void)
{
char nAlumnos[TAMANIO];
int alumnos;
int longitud;
int x;   // valor que devuelve la función verificarEntrada()
int i;

do{
printf("Numero de alumnos: ");

fgets(nAlumnos, TAMANIO, stdin);   // si introducimos 9 o más caracteres se produce OVERFLOW en el buffer

longitud = strlen(nAlumnos);

if(nAlumnos[longitud-1] == '\n'){   // si la cadena tiene una longitud menor a TAMANIO-1 evitamos la "impresión de '\n'
nAlumnos[longitud-1] = '\0';
}

x = verificarEntrada(nAlumnos);

puts("");

if(x == 1){
alumnos = atoi(nAlumnos);
}

} while(x == 0);

char *notas = malloc(alumnos * sizeof (char));
int notasEnteras[alumnos];

for (i=0; i<alumnos; i++){

do{
notas[i] = malloc(TAMANIO * sizeof (char));
 
      printf("Nota alumno %d : ", i + 1);
        scanf("%[^\n]", notas[i]);
       
        while(getchar() != '\n');
       
        x = verificarEntrada(notas[i]);

if(x == 1){
int n = atoi(notas[i]);

if(n < 0 || n > 10){   // cada nota debe estar comprendida en el intervalor [0, 10]
x = 0;
}
else{
notasEnteras[i] = atoi(notas[i]);
}
}

} while(x == 0);
   }


return EXIT_SUCCESS;
}

También puse los printf y todo va bien hasta que entra en el for, que no pasa de:
Código:
scanf("%[^\n]", notas[i]);

Aquí pongo los mensajes que me deja el compilador (los  que no he conseguido solucionar):
Citar
In function 'main':
57 13 [Warning] assignment makes integer from pointer without a cast [enabled by default]
60 10 [Warning] passing argument 1 of 'fgets' makes pointer from integer without a cast [enabled by default]
354 39 c:\program files (x86)\dev-cpp\mingw32\include\stdio.h expected 'char *' but argument is of type 'char'
64 10 [Warning] passing argument 1 of 'verificarEntrada' makes pointer from integer without a cast [enabled by default]
10 5 expected 'const char *' but argument is of type 'char'
67 5 [Warning] passing argument 1 of 'atoi' makes pointer from integer without a cast [enabled by default]
304 37 c:\program files (x86)\dev-cpp\mingw32\include\stdlib.h expected 'const char *' but argument is of type 'char'
73 6 [Warning] passing argument 1 of 'atoi' makes pointer from integer without a cast [enabled by default]
304 37 c:\program files (x86)\dev-cpp\mingw32\include\stdlib.h expected 'const char *' but argument is of type 'char'

No quiero la solución en código del problema si no una pista de lo que pudiese estar fallando.

Un saludo.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: leosansan en 10 Abril 2014, 20:26 pm

Todo el mal radica en cómo declaras notas y el char que usas.

Ya que usas array de longitud variable en:


Código
  1. int notasEnteras[alumnos];

no sé por qué no haces lo mismo con notas:

Código
  1. char *notas[alumnos];

Pero si lo quieres hacer con malloc, entonces:

Código
  1. char **notas;
  2. *notas=malloc(alumnos * sizeof (char));

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 20:50 pm
Todo el mal radica en cómo declaras notas y el char que usas.

Ya que usas array de longitud variable en:


Código
  1. int notasEnteras[alumnos];

no sé por qué no haces lo mismo con notas:

Código
  1. char *notas[alumnos];

Pero si lo quieres hacer con malloc, entonces:

Código
  1. char **notas;
  2. *notas=malloc(alumnos * sizeof (char));

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)


Funciona!!! Muchísimas gracias.
Aunque no comprendo muy bien lo de punteros a punteros, pero eso es cuestión de estudiarlo mejor.

Ya que me lo dijiste, ¿es mejor hacer
Código:
int notasEnteras[alumnos];
como un array dinámico? Sólo lo uso para almacenar enteros. (perdona mi ignorancia)

Un saludo


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: leosansan en 10 Abril 2014, 21:31 pm
Funciona!!! Muchísimas gracias.
Aunque no comprendo muy bien lo de punteros a punteros, pero eso es cuestión de estudiarlo mejor.

Ya que me lo dijiste, ¿es mejor hacer
Código:
int notasEnteras[alumnos];
como un array dinámico? Sólo lo uso para almacenar enteros. (perdona mi ignorancia)

Un saludo

Es otra alternativa a la que puede ponerse el pero de que algún compilador no la acepte. En general la uso para matrices normalitas. Si el tamaño es importante uso asignación dinámica de memoria.

Salu2!.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 10 Abril 2014, 23:01 pm
Es otra alternativa a la que puede ponerse el pero de que algún compilador no la acepte. En general la uso para matrices normalitas. Si el tamaño es importante uso asignación dinámica de memoria.

Salu2!.


Una última cosa, el compilador me da (en modo estricto) el siguiente warning:
Citar
54 9 [Warning] 'notas' is used uninitialized in this function [-Wuninitialized]

Respecto a:
Código:
char **notas;
*notas = malloc(alumnos * sizeof (char));

Un saludo.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: amchacon en 10 Abril 2014, 23:13 pm
Cambia:
Código
  1. *notas = malloc(alumnos * sizeof (char));

Por:
Código
  1. notas = malloc(alumnos * sizeof (char));


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 11 Abril 2014, 10:51 am
Cambia:
Código
  1. *notas = malloc(alumnos * sizeof (char));

Por:
Código
  1. notas = malloc(alumnos * sizeof (char));

Una última cosa y ya doy por solucionada la duda.
Para liberar la memoria que uso cuando reservo con malloc tendré que usar free así no?
Código:
free(notas[i]);
después del
Código:
while(x == 0);
O uso
Código:
free(notas)
solamente?

Un saludo.


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: rir3760 en 13 Abril 2014, 16:30 pm
Como ya te comentaron el problema principal se debe a que tratas de almacenar todas las lineas cuando lo único que haces con ellas es obtener (mediante atoi) un entero. Es mejor declarar un solo array de caracteres (ya lo haces, el array "nAlumnos") y reutilizar este cada vez que debas leer una linea de la entrada estándar.

Si con todo quieres utilizar memoria dinámica debes reservar primero la memoria del bloque principal y a continuación la memoria para cada linea. Antes de terminar el programa liberas la memoria de cada linea y por ultimo la del bloque principal. De esta forma:
Código
  1. /* ... */
  2.  
  3. #define TAMANIO  10
  4.  
  5. /* ... */
  6.  
  7. char nAlumnos[TAMANIO];
  8. int alumnos;
  9. int longitud;
  10. int x;
  11. int i;
  12. char **notas;
  13.  
  14. /* ... */
  15.  
  16. /* 1) Obtienes el numero de alumnos */
  17.  
  18. /* 2) Reservas el bloque de memoria principal */
  19. notas = malloc(alumnos * sizeof *notas);
  20.  
  21. /* 3) Reservas el bloque de memoria para cada alumno */
  22. for (i = 0; i < alumnos; i++)
  23.   notas[i] = malloc(TAMANIO);
  24.  
  25. /* 4) Realizas las operaciones del programa */
  26.  
  27. /* 5) Liberas la memoria utilizada por cada alumno */
  28. for (i = 0; i < alumnos; i++)
  29.   free(notas[i]);
  30.  
  31. /* 6) Liberas el bloque principal */
  32. free(notas);

Un saludo


Título: Re: Ejercicio compila pero no se ejecuta
Publicado por: David8 en 20 Abril 2014, 22:47 pm
Como ya te comentaron el problema principal se debe a que tratas de almacenar todas las lineas cuando lo único que haces con ellas es obtener (mediante atoi) un entero. Es mejor declarar un solo array de caracteres (ya lo haces, el array "nAlumnos") y reutilizar este cada vez que debas leer una linea de la entrada estándar.

Si con todo quieres utilizar memoria dinámica debes reservar primero la memoria del bloque principal y a continuación la memoria para cada linea. Antes de terminar el programa liberas la memoria de cada linea y por ultimo la del bloque principal. De esta forma:
Código
  1. /* ... */
  2.  
  3. #define TAMANIO  10
  4.  
  5. /* ... */
  6.  
  7. char nAlumnos[TAMANIO];
  8. int alumnos;
  9. int longitud;
  10. int x;
  11. int i;
  12. char **notas;
  13.  
  14. /* ... */
  15.  
  16. /* 1) Obtienes el numero de alumnos */
  17.  
  18. /* 2) Reservas el bloque de memoria principal */
  19. notas = malloc(alumnos * sizeof *notas);
  20.  
  21. /* 3) Reservas el bloque de memoria para cada alumno */
  22. for (i = 0; i < alumnos; i++)
  23.   notas[i] = malloc(TAMANIO);
  24.  
  25. /* 4) Realizas las operaciones del programa */
  26.  
  27. /* 5) Liberas la memoria utilizada por cada alumno */
  28. for (i = 0; i < alumnos; i++)
  29.   free(notas[i]);
  30.  
  31. /* 6) Liberas el bloque principal */
  32. free(notas);

Un saludo

Lo voy pillando poco a poco.
Muchas gracias por curraros tanto las respuestas :)

Un saludo.