2

I was tasked to do a program to read the name of one student, 4 of their subjects and their respective grades. I have worked with for and while loops, also with if statements and here is my code so far:

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

main() {
    printf("Este programa captura el nombre de un alumno \n");
    printf  ("y cuatro de sus materias y sus respectivas notas\n");
    printf      ("Nota: El programa solo toma en cuenta los dos primeros\n");
    printf          ("decimales de la notas expresada.\n\n");
    
    char alumno[40] = {'\0'};
    char mat[4][20] = {'\0', '\0', '\0', '\0'};
    float calif[4] = {-1, -1, -1, -1};
    int i;
    
    while (alumno[0] == '\0') {
        printf("Ingresa el nombre del alumno: ");
        gets(alumno);
        if (alumno[0] == '\0') {
            printf("\nError. El alumno debe de llevar un nombre.");
            printf  ("\nTrata nuevamente\n\n");
        };
    };
    for (i = 0; i < 4; ++i) {
        while (mat[i][0] == '\0') {
            printf("Ingresa el nombre de la materia %d: ", i+1);
            gets(mat[i]);
            if (mat[i][0] == '\0') {
                printf("\nError. Las materias deben ser declaradas.");
                printf  ("\nTrata nuevamente.\n\n");
            };
        };
        while (calif[i] < 0 || calif[i] > 10) {
            printf("Ingrese la nota correspondiente a esta materia (0-10): ");
            scanf("%2.2f", calif[i]);
            if (calif[i] < 0 || calif[i] > 10) {
                printf("\nError. Debe ingresar una nota válidad entre 0 y 10.");
                printf  ("\nTrata nuevamente.\n\n");
            };
        };
    };
    
    return 0;
};

The program seems to be working fine until it gets to the point to ask the grade of the first subject. Any grade I put it causes an infinite loop. I have searched about this problem to no avail. So please, let me know what I am doing wrong here.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 4
    Change `scanf("%2.2f", calif[i]);` to `scanf("%2.2f", &calif[i]);`. Or, better, `scanf("%f", &calif[i]);` since you're scanning interactive input. – John Bollinger Aug 07 '20 at 05:39
  • Hi, John. Thanks for your answer. A quick question though. How do you recommend to control the number of decimals that the grade admits, since the task asks specifically that only two decimals must be taken into consideration. Thanks. – Rodolfo Barrientos Acosta Aug 07 '20 at 05:51
  • 1
    `"%2.2f"` seems not work on [`scanf`](http://www.cplusplus.com/reference/cstdio/scanf/). – yao99 Aug 07 '20 at 07:29
  • 2
    I would suggest not trying to control it, @RodolfoBarrientosAcosta, at least not via a `scanf` format. If you must validate the form prior to converting to float, then read the data as a string, and validate that representation. Simpler, though, would be to round or truncate the input value after you read it. – John Bollinger Aug 07 '20 at 11:32
  • Rodolfo Barrientos Acosta "How do you recommend to control the number of decimals that the grade admits" --> As you cannot reach out to the user and prevent typing "2.34567", what do you want to do with input that does not meet your input criteria? – chux - Reinstate Monica Aug 07 '20 at 12:31
  • Please read [this](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings). – n. m. could be an AI Aug 07 '20 at 22:37
  • "the task asks specifically that only two decimals must be taken into consideration". This is a rather ill-posed requirement. See [this](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). If you need to deal with decimal fractions, you need a data type that can represent decimal fractions. This is well beyond any beginner-level C course. Lo siento. – n. m. could be an AI Aug 07 '20 at 22:43

1 Answers1

1

There are multiple problems in your code:

  • [major] you read the mark with scanf("%2.2f", calif[i]): the format string is incorrect, the first 2 means read at most 2 bytes and the .2 is an error as scanf() does not support the precision syntax at all. It should just be "%f" and you should pass the address of the destination variable &calif[i] instead of its value. Furthermore, you should test the return value to check for invalid or missing input.

  • the prototype for main is int main(), int main(void) or int main(int argc, char *argv[]), the missing return type is an obsolete syntax.

  • reading input with gets() is risky as there is no way to prevent buffer overflow with sufficiently long input strings. You should instead use scanf("%39s", alumno) or fgets(alumno, sizeof alumno, stdin) and test the return value to detect premature end of input stream. Same remark for the second instance of gets().

chqrlie
  • 131,814
  • 10
  • 121
  • 189