Autor Tema: Duda: Proyecto en lenguaje C (Devc++)

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

25 Noviembre, 2014, 05:46 am
Leído 13488 veces

Huxley

  • Junior
  • Mensajes: 35
  • Karma: +0/-0
  • Sexo: Masculino
Hola a todos!!!
Tengo el siguiente código en lenguaje c, trabajado en dev c++. El programa solicita el nombre de n cantidad de alumnos, pide sus calificaciones y genera el promedio de las calificaciones dadas:
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<locale.h>
#define p printf
#define s scanf
        main(){ setlocale(LC_CTYPE,"Spanish");
               int i,j,num_1,num_2,mayor=0,contador;
               float calificacion[100][100],promedio,suma=0;
               char nombre[20][100];
               p("¿Cuántos alumnos serán evaluados?: ");
               s("%d",&num_1);
               for(i=0;i<num_1;i++){
                   p("Ingrese el nombre del estudiante número [%d]: ",i+1);
                   fflush(stdin);
                   gets(nombre);
                                }
               p("¿Cuántas calificaciones ingresará por alumno?: ");
               s("%d",&num_2);
               for(i=0;i<num_1;i++)
               for(j=0;j<num_2;j++){
                   p("Ingrese la calificación número [%d] del estudiante[%d]: ",j+1,i+1);
                   s("%f",&calificacion[j]);
                   contador=num_1*num_2;
                                }
                   
               p("La lista de calificaciones queda de la siguiente manera:");
               p("\n");
               for(i=0;i<num_1;i++){
                   p("%s:",nombre);
                   for(j=0;j<num_2;j++)
                   {p("\n");
                   p("%3.2f",calificacion[j]);
                                        }
                   p("\n");
                                    }
               for(i=0;i<num_1;i++)
               for(j=0;j<num_2;j++){
                      suma=suma+calificacion[j];
                                    }
               p("La suma de todos los promedios es igual a %.2f. Total de datos introducidos %d",suma,contador);
               p("\n");
               promedio=suma/contador;
               p("\n");
               p("El promedio de las calificaciones es igual a %.2f",promedio);
               p("\n");
        p("\n\n\t");
        system("pause");
                        }
Lo que ahora necesito hacer es generar la suma de las calificaciones de cada alumno, para poder sacar el promedio personal... es decir:
Alumno 1:5,8,7
Alumno 2:10,9,6
Alumno 3:6,5,8
Alumno 4:7,6,6
Se tienen cuatro alumnos con esas calificaciones... y necesito que el programa me imprima lo siguiente:
"La suma de las calificaciones del alumno 1 es igual a 20"
"El promedio del alumno 1 es igual a 6.6"
y así con cada uno de los alumnos...
alguna idea de cómo lo puedo hacer?
Saludos!!!!

25 Noviembre, 2014, 11:31 am
Respuesta #1

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
¿el código que mandaste funciona?

en particular, no entendí bien
Código: [Seleccionar]
s("%f",&calificacion[j]);
¿no es un arreglo bidimensional de calificaciones?


luis

25 Noviembre, 2014, 03:49 pm
Respuesta #2

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,292
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
  • Vean mis posts activos en mi página personal
    • Mis posts activos (click aquí)
Hola Huxley.
Me voy a permitir hacerte varias críticas, que espero entiendas no son algo personal, sino que es lo que muchos programadores de C te dirían.

Definir abreviaturas de los nombres de las funciones printf y scanf (o de cualquier otra función conocida en general) es una práctica malísima de programación.

Las declaraciones #define hay que usarlas con otros propósitos más constructivos de programación.
Es decir, definen constantes con un nombre significativo para el programador (y por lo tanto largo, todo lo contrario de "abreviado"), o bien definen macros con argumentos, en situaciones donde una función no es apropiada (ya sea porque el tipo de datos de los argumentos es arbitrario, o por alguna otra razón bien pensada).

En cambio, usar las abreviaturas p y s para funciones conocidas printf y scanf es sólo "comodidad", y le quita significado al programa.
Alguien que lee tu programa, si ve la función printf(), fácilmente entenderá lo que estás haciendo, porque printf() es muy conocida por los programadores de C, y saben cómo actúa.

El problema es que has tenido que usar varias veces las funciones printf() y scanf(),
y eso te ha aburrido.
No hay que aburrirse: hay que escribir todas las veces los nombres completos de las funciones.

En todo caso, mejor harías en fijarte cómo diseñar el programa para no tener que invocar tantas veces esas funciones.

Lo que yo haría es aprovechar la funcionalidad de printf() para poner varios mensajes en una sola sentencia.

------------------

Otros detalles:

* La función main() necesita una declaración más prolija: indicar el tipo de salida (int), y los argumentos de entrada (que en este caso no hay, y se pone: void).

* Las llaves que abren y cierran los bloques de setencias deberían estar colocados de una manera más visible.

* La librería "conio.h" no la has usado nunca, no debería estar.

----------------

Por último, tener en cuenta la observación de luis de que el array es bidimensional.


En realidad lo escribiste bien, pero acá en el foro cuando pones [i]
se interpreta como: poner letra cursiva, y entonces no se ve que pusiste eso,
y en cambio aparece todo en cursiva.

Lo arreglé pegando el código dentro de etiquetas [nobbc][/nobbc],
que figuran en la lista de iconitos cuando editas el post.


-------------

Todos estos detalles los tuve en cuenta para reescribir tu código, que queda así:


#include<stdlib.h>
#include<stdio.h>
#include<locale.h>

int main(void)
{
    setlocale(LC_CTYPE,"spanish");

    int i,j,num_1,num_2,mayor=0,contador;
    float calificacion[100][100],promedio,suma=0;
    char nombre[20][100];

    printf("¿Cuántos alumnos serán evaluados?: ");
    scanf("%d",&num_1);

    for(i=0;i<num_1;i++)
    {
       printf("Ingrese el nombre del estudiante número [%d]: ",i+1);
       fflush(stdin);
       gets(nombre[i]);
    }

    printf("¿Cuántas calificaciones ingresará por alumno?: ");
    scanf("%d",&num_2);

    for(i=0;i<num_1;i++)
        for(j=0;j<num_2;j++)
        {
            printf("Ingrese la calificación número [%d] del estudiante[%d]: ",j+1,i+1);
            scanf("%f",&calificacion[i][j]);
            contador=num_1*num_2;
        }

    printf("La lista de calificaciones queda de la siguiente manera:\n");

    for(i=0;i<num_1;i++){
       printf("%s:",nombre[i]);
       for(j=0;j<num_2;j++)
       {
         printf("\n");
         printf("%3.2f",calificacion[i][j]);
       }
       printf("\n");
    }

    for(i=0;i<num_1;i++)
        for(j=0;j<num_2;j++){
          suma=suma+calificacion[i][j];
        }

    printf("La suma de todos los promedios es igual a %.2f. "
           "Total de datos introducidos %d\n",suma,contador);

    promedio=suma/contador;

    printf("El promedio de las calificaciones es igual a %.2f\n\n\n\t",promedio);

    system("pause");
}

 

25 Noviembre, 2014, 05:49 pm
Respuesta #3

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,292
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
  • Vean mis posts activos en mi página personal
    • Mis posts activos (click aquí)
A continuación voy a seguir modificando la estética del programa.

En mi opinión, al arreglar la estética del programa se consigue entender mejor qué diablos es lo uno está haciendo, y entonces es más fácil encontrar los errores.

Por ejemplo, veo que has puesto varios printf() porque los has separado innecesariamente.
Las secuencias de escape \n \t, etc., pueden ponerse todas juntas con el texto, así:

printf("Una línea entera finalizada con dos saltos de línea.\n\n");

---------------

Otra recomendación:

* Separar los cálculos de la parte de entrada y/o salida de datos.

Yo haría algo más compacto, poniendo una explicación general al principio de lo que hace el programa,
y a continuación pedir los datos principales.

Además, no queda bien poner algo como esto:

printf("\n");
printf("%3.2f",calificacion[i][j]);

El problema con eso es que estás dejando colgado un "salto de línea" que en realidad le pertenece a un mensaje anterior.
En lo posible hay que evitar "desarmar" así los mensajes,
a menos, claro, que estés haciendo una función específica que se encarga de procesar los datos de salida de una forma precisa y complicada.

Pero aquí, que lo único que importa es el resultado de las notas de los alumnos,
las "peripecias" con printf() sólo resultan en código incomprensible.

---------------

Tampoco se recomienda usar fflush() con stdin, porque no está pensado para ese tipo de "archivo" (que es de entrada), sino para archivos de salida.
Por ejemplo, en mi sistema no funciona.
O sea que no es código portable.

Tampoco creo que sea necesario.
Si hubiera algún problema con los datos de entrada, hay que buscar la manera de ordenar las sentencias para que no haya ese problema.

Probando el programa detecté problemas, y entiendo por qué has tenido que usar fflush().
Sin embargo lo reemplacé con un simple:

scanf("%c");

Esa sentencia intenta leer un caracter, y consume algún "ENTER" que haya quedado dando vueltas por ahí.
Ahora bien, para que esto funcione, el usuario también tiene que cooperar ingresando datos prolijamente.
Si mi "parche" no funcione, pues vuelves a poner fflush(stdin), tal como antes, y listo.

En realidad, si estuvieras pensando en hacer el programa "perfecto", que evite errores en la entrada de datos del usuario, entonces tampoco sirve una solución como ésta, que apenas emparcha algunos casos de errores de entrada, pero no arregla todos los posibles errores.

Lo apropiado sería diseñar una función que se encarga de procesar los datos de entrada con mayor control.
Es decir, escribir una función específicamente diseñada para controlar esto.
Si no vas a hacer esto, entonces me parece que mejor no hacer nada, y tan sólo tener cuidado de no cometer errores en la entrada de los datos cuando corras el programa.

Lo ideal es usar alguna combinación de fgets(..., stdin) y sscanf().
Pero eso es parte de otra discusión, que no conviene perder tiempo aquí.

------------

También veo que las variables num_1, num_2, no tienen ningún significado,
lo cual dificulta la lectura del programa.

Yo cambié num_1 por num_A, que quiere decir: número de Alumnos,
y cambié num_2 por num_C, que quiere decir: Número de calificaciones por alumno.

-------------

Hay algo que considero un error:

En todas las iteraciones de la carga de notas pusiste:

contador = num_1 * num_2;

Estás repitiendo el mismo cálculo en todas las iteraciones, porque num_1 y num_2 están fijos durante todo el doble for() anidado.

Ese cálculo bien puede hacerse al final de todo el programa.

----------

La función gets() es algo que está en desuso por el estándar C.
Hay que evitar su uso.
En su lugar, hay que usar fgets(..., stdin), poniendo el número máximo de caracteres del buffer usado para guardar los caracteres:

fgets(nombre[i], 100, stdin);

Esta función es mejor porque se limita el número de caracteres de entrada,
evitando errores de desboramiento de memoria.

Sin embargo, como trae otros "pequeños" (pero molestos) inconvenientes,
te la dejé tal cual estaba, o sea,
dejé gets() tal cual estaba, y listo.

-----------------

Al final, la sentencia

system("PAUSE");

no funciona en mi sistema.
Sólo funciona en Windows.

Así que la quité.
En su lugar puse:

scanf("%*c%*c");

que consume un par de caracteres sin guardarlo en ninguna parte.
Se ponen tantos %*c como hagan falta.
(Igual, es una solución totalmente chapucera al problema de hacerle un "fflush" al teclado).

Como sea, con eso ya quité la librería <stdlib.h>.
Es una pena llamar toda una librería sólo para poner una pausa no portable al final del programa.

---------

Fijate esta versión del programa, a ver si te agrada.
He puesto en lo posible todos los mensajes al final, después de haber hecho los cálculos.

(Si bien el "concepto" de separar "cálculos" de "muestreo de datos en pantalla" es bueno, no es algo que haya que hacer sin más criterio, o sea que mi estrategia aquí es discubible).


#include<stdio.h>
#include<locale.h>

int main(void)
{
    setlocale(LC_CTYPE,"spanish");

    int i,j,num_A,num_C,mayor=0,contador;
    float calificacion[100][100],promedio,suma=0;
    char nombre[20][100];

    /* ========= SECCIÓN DE PRESENTACIÓN E INGRESO DE DATOS ================ */

    puts("Este programa realiza el promedio de calificaciones de una lista de alumnos.\n"
         "Se pedirá al usuario la siguiente información en varios pasos:\n"
         "  -  Número A de alumnos que serán evaluados,\n"
         "  -  Número N de calificaciones por cada alumno,\n"
         "  -  El nombre nombre[i] del alumno i-ésimo.\n"
         "  -  La calificación j del alumno i, que indicaremos calificacion[i][j].\n\n"
         "El programa devolverá en pantalla el promedio de todas las calificaciones de los alumnos.\n\n"
         "Presione [ENTER] para comenzar.\n"
        );

    getchar();

    printf("\n  ¿Alumnos?\n\n\t  A = ");
    scanf("%d",&num_A);

    printf("\n  ¿Calificaciones por alumno?\n\n\t  N = ");
    scanf("%d",&num_C);

    scanf("%*c"); /* Mi versión de: fflush para entrada por teclado */

    printf("\n  Ingrese el nombre de los estudiantes.\n\n");
    for(i=0;i<num_A;i++){
       printf("\t  ¿Nombre[%d]? ",i+1);
       gets(nombre[i]);
    }

    printf("\nIngrese las calificaciones de los estudiantes.\n");
    for(i=0;i<num_A;i++){
        printf("\n   Estudiante %s:\n\n",nombre[i]);
        for(j=0;j<num_C;j++){
            printf("\t   ¿Calificación [%d]?: ",j+1);
            scanf("%f",&calificacion[i][j]);
        }
    }

    /* ==========  SECCIÓN DE CÁLCULOS Y PROCESO DE DATOS  ================ */

    suma = 0.0; /* Inicializar la suma a 0 es muy importante */
    for(i=0;i<num_A;i++)
        for(j=0;j<num_C;j++){
          suma=suma+calificacion[i][j];
        }

    contador = num_A*num_C;
    promedio = suma/contador;

    /* ==============  SECCIÓN DE MUESTREO DE RESULTADOS  =================*/

    printf("\n\n  La lista de calificaciones queda de la siguiente manera:\n");
    for(i=0;i<num_A;i++){
       printf("\n  %s: \n",nombre[i]);
       for(j=0;j<num_C;j++){
           printf("   %3.2f",calificacion[i][j]);
       }
    }
    printf("\n\n");
    printf("La suma de todos los promedios es igual a %.2f.\n",suma);
    printf("Total de datos introducidos: %d.\n",contador);
    printf("El promedio de las calificaciones es igual a %.2f\n\n\n\t",promedio);

    scanf("%*c%*c");  /* fflush() para el teclado. Necesité un par de: "%*c" */

    return 0;
}


25 Noviembre, 2014, 11:31 pm
Respuesta #4

Huxley

  • Junior
  • Mensajes: 35
  • Karma: +0/-0
  • Sexo: Masculino
Hola argentinator!
Antes que nada, quiero agradecerte de antemano el tiempo que te tomaste para poder ayudarme con este programa.
El comentario que me haces al principio es muy enriquecedor ya que, a pesar de que no estudio directamente algo relacionado con la computación, mi carrera me exige conocer un poco a cerca de este tema.
Con esto, me doy cuenta de las deficiencias que estoy presentando y que sé, puedo mejorar...
La única duda que me queda es cómo le hago para poder generar e imprimir los promedios personales, es decir, de cada uno de los alumnos que ingrese... porque el programa que presenté, solamente puede generar el promedio general de todos los alumnos ingresados...
De nuevo, muchísimas gracias por este gran aporte!!!
Saludos!
 

26 Noviembre, 2014, 01:19 am
Respuesta #5

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,292
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
  • Vean mis posts activos en mi página personal
    • Mis posts activos (click aquí)
Pues a mí me extrañó que no calcularas esos promedios.

Te hace falta un array de tipo float para guardar los promedios de los alumnos:

float promedio[100];

Luego, en la sección de cálculos, cambiarías el cálculo de los promedios, poniendo esto:


    for(i=0;i<num_A;i++) {
        suma = 0.0; /* Inicializar la suma a 0 para cada alumno */
        for(j=0;j<num_C;j++){
          suma=suma+calificacion[i][j];
        }
        promedio[i] = suma / num_C;
    }


La variable "suma" no la usé para guardar ningún valor en particular,
sino que sólo la he "reusado" en cada iteración para calcular la suma de las notas,
y luego al final de cada iteración se guarda el promedio de cada alumno.

Un saludo.