Получает / fgets перепрыгнул через шаги ввода в C - PullRequest
0 голосов
/ 07 января 2020

У меня есть упражнение, которое мне нужно, чтобы создать программу для ввода всей информации о студентах в виде отчета о студентах в виде исходного кода ниже. У меня проблема, что я не могу получить полный поток ввода. Он перешагнул через ввод оценок и перешел к другому ученику, чтобы ввести идентификатор следующего ученика. Я поставил getchar(), чтобы получить \n, но это не помогает. Моя проблема в случае 1 коммутатора, поэтому вам нужно только позаботиться об этом, остальные случаи не имеют никакого смысла в моем вопросе.

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

#define MAX 1000
typedef struct 
{
    char id[10];
    char name[50];
    float grade;
    char assess;
}student;
char assess(int a)
{
    if(a<4.00)
    return 'F';
    if(4.00<=a<6.00)
    return 'D';
    if(6.00<=a<7.00)
    return 'C';
    if(7.00<=a<8.50)
    return 'B';
    if(8.50<=a<10.00)
    return 'A';
}
int main()
{
    int choice;
    int i=0, num=0; 
    int a=0, j=0;
    student std[MAX], temp;
    char search[50];
    do
    {
        printf("Student Report\n");
        printf("1.Input data\n2.Append data\n3.Sort data and print\n4.Search by names5.Quit\n");
        printf("Your choice is: ");
        scanf("%d", &choice);
        switch(choice)
      {
            case 1:
            {
                do{
                printf("How many students you want to add?\n");
                scanf("%d", &num);
                if(num<0 || num>50)
                printf("Your number must be positive or smaller than or equal to 50!\n");
                }while(num<0||num>50);
                for(i=a; i<num; i++)
                {
                    printf("Student's id No.%d:", i);
                    fgets(std[i].id, 10, stdin);
                    getchar();
                    printf("Student's name No.%d:", i);
                    fgets(std[i].name, 50, stdin);
                    getchar();
                    printf("Student's grade No.%d:", i);
                    scanf("%f", &std[i].grade);
                    std[i].assess=assess(std[i].grade);
                }
                a=num;
            }
            case 2:
            {
                do
        {
          printf("How many students you want to append?[0; %d]\n", MAX-num);
          scanf("%d", &num);
                }while(num<0||num>50-a);
                for(i=a; i<num+a; i++)
                {
                    printf("Student's id No.%d:", i);
                    fgets(std[i].id, MAX, stdin);
                    getchar();
                    printf("Student's name No.%d:", i);
                    fgets(std[i].name, MAX, stdin);
                    getchar();
                    printf("Student's grade No.%d:", i);
                    do
            {
              scanf("%f", &std[i].grade);
              if(std[i].grade<0||std[i].grade>10)
            printf("Please re-input grade, it must be between 0 and 10\n");
                    }while(std[i].grade<0||std[i].grade>10);
                    std[i].assess=assess(std[i].grade);
                }
                a=num+a;
            }
            case 3: 
            {
                for(i=0; i<a; i++)
                for(j=0; j<a; j++)
                {
                    if(std[i].grade<std[j].grade)
                    {
                        temp=std[i];
                        std[i]=std[j];
                        std[j]=temp;
                    }
                }
                printf("ID\tName\t\t\tGrade\t\tAssessment\n");
                for(i=0; i<a; i++)
                printf("%-10s%-50s%-10.2f%-10c\n", std[i].id, std[i].name, std[i].grade, std[i].assess);
            }
            case 4:
            {
                printf("Student's name who you want to search: ");
                fgets(search, MAX, stdin);
                getchar();
                for(i=0; i<a; i++)
                if(strcasecmp(search, std[i].name)==0)
                printf("%-10s%-50s%-10.2f%-10c\n", std[i].id, std[i].name, std[i].grade, std[i].assess);
            }
            case 5:
            break;
            default:
            {
                printf("Please reinsert your choice again\n");
                break;
        }
      }
    }while(choice!=5);
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 07 января 2020

Исходя из рекомендации, которую я нашел здесь - Я не могу грипп sh stdin

Мы можем использовать приведенный ниже фрагмент, чтобы избавиться от мусора в буфере.

int c;
while ((c = getchar()) != '\n' && c != EOF);

Теперь вопрос - куда поместить это в вашей программе?

Ну, я положил его в for l oop и заставил программу работать и прочитать все три params - а именно Удостоверение личности, имя, оценка; для нескольких записей о студентах.

Проверьте приведенный ниже измененный фрагмент из вашей программы.

                for(i=a; i<num; i++)
                {
                    int c; // line 1 added
                    while ((c = getchar()) != '\n' && c != EOF); // line 2 added
                    printf("Student's id No.%d:", i);
                    fgets(std[i].id, 10, stdin);
                    printf("Student's name No.%d:", i);
                    fgets(std[i].name, 50, stdin);
                    printf("Student's grade No.%d:", i);
                    scanf("%f", &std[i].grade);
                    std[i].assess=assess(std[i].grade);
                }
0 голосов
/ 07 января 2020

Проблема связана с тем, что \n сначала не используется scanf. Чтобы преодолеть случай, я добавил while ((c = getchar()) != '\n' && c != EOF);.

Чтобы избавиться от символа \n после использования fgets, я бы предпочел использовать strcspn .

case 1:
{
    do{
    printf("How many students you want to add?\n");
    scanf("%d", &num);
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
    if(num<0 || num>50)
    printf("Your number must be positive or smaller than or equal to 50!\n");
    }while(num<0||num>50);

    for(i=a; i<num; i++)
    {
        printf("Student's id No.%d:", i);
        fgets(std[i].id, 10, stdin);
        std[i].id[strcspn(std[i].id, "\n")] = 0;
        printf("Student's name No.%d:", i);
        fgets(std[i].name, 50, stdin);
        std[i].name[strcspn(std[i].name, "\n")] = 0;
        printf("Student's grade No.%d:", i);
        scanf("%f", &std[i].grade);
        std[i].assess=assess(std[i].grade);
    }
    a=num;
    break;
}

Более того, функцию asses можно упростить следующим образом:

char assess(double a)
{
    if(a < 4.00)
        return 'F';
    if(a < 6.00)
        return 'D';
    if(a < 7.00)
        return 'C';
    if(a < 8.50)
        return 'B';
    if(a < 10.00)
        return 'A';
    else
        return -1; // the error indicator to be handled.
}

Далее, после каждого case следует ставить операторы break. Посмотрите на переключатель использование.

...