如何忽略给定的控制台输入

How to ignore a given console input

我的问题(如标题所示)是如何忽略控制台中的输入。

我的程序将接受代表名字、中间名和姓氏的输入。例如,如果任何人没有中间名,stud.name.mdlename 应该为空,它应该被忽略,这样它就不会接受任何输入。

// write a program to read and display information of a 
// student using a structure within a structure.
#include <stdio.h>

typedef struct studentName
{
    char frstnme[10];
    char mdlenme[10];
    char lstnme[10];
}Name;
typedef struct studentdob
{
    int dd;
    int mm;
    int yy;
}DOB;
typedef struct studentinfo
{
    int r_no;
    Name name;
    char course[10];
    DOB dob;
    float fees;
};
int main()
{
   struct studentinfo stud;
   printf("\nEnter registration number : ");
   scanf("%d",&stud.r_no);
   printf("Enter First name :\n");
   scanf("%s",stud.name.frstnme);
   printf("Enter Middle name :\n");
   scanf("%s",stud.name.mdlenme);
   printf("Enter Last name :\n");
   scanf("%s",stud.name.lstnme);
   printf("\n");
   printf("Enter DOB [dd.mm.yy]:");
   scanf("%d %d %d",&stud.dob.dd,&stud.dob.mm,&stud.dob.yy);
   printf("\nEnter the fees:");
   scanf("%f",&stud.fees);

   printf("\n ***Student's details***");
   printf("\nRegistration number : %d",stud.r_no);
   printf("\nName of student : %s %s %s",stud.name.frstnme,stud.name.mdlenme,stud.name.lstnme);
   printf("\nD.O.B- %d.%d.%d",stud.dob.dd,stud.dob.mm,stud.dob.yy);
   printf("\nTotal Fees :%f",stud.fees);
} 

你的代码应该允许用户跳过输入,比方说,通过按回车键,让缓冲区留空,我的意思是只有 [=13=],你可以为此使用 fgets,但是问题仍然存在,如果输入大于缓冲区的容量,stdin 上的剩余内容将保留在那里,影响未来的读数。

我建议使用更个性化的方法:

// 必需 headers:

#include <stdlib.h>
#include <assert.h>

// 辅助函数:

int clearbuffer() { // helper function to clear buffer
    int c;
    while ((c = getchar()) != '\n' && c != EOF){} 
    if (c == EOF) {
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

int readline(char *buffer, size_t size) { // custom line reading function
    assert(size > 0 && size <= INT_MAX);  // validate size parameter
    size_t i = 0;
    int ch;
    // reads at most size of the buffer - 1, clearing the extra characters
    while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
        if(i < size - 1){
            buffer[i++] = ch;
        }
    }    
    buffer[i] = '[=11=]';
    return i;
}

// 主要代码:

int main(){
    struct studentinfo stud;
    size_t namesize = 0; //keep track of the student name length

    printf("\nEnter registration number : ");
    scanf("%d", &stud.r_no);

    printf("Enter First name(Enter to skip): ");
    if(clearbuffer() == EXIT_FAILURE){
        fprintf(stderr, "Fatal error");
        return EXIT_FAILURE;
    }
    namesize += readline(stud.name.frstnme, sizeof stud.name.frstnme);

    printf("Enter Middle name(Enter to skip): ");
    namesize += readline(stud.name.mdlenme, sizeof stud.name.mdlenme);

    printf("Enter Last name name(Enter to skip): ");
    namesize = readline(stud.name.lstnme, sizeof stud.name.lstnme);

    printf("Enter DOB [dd.mm.yy]: ");
    scanf("%d %d %d", &stud.dob.dd, &stud.dob.mm, &stud.dob.yy);

    printf("\nEnter the fees: ");
    scanf("%f", &stud.fees);

    printf("\n ***Student's details***");
    printf("\nRegistration number : %d", stud.r_no);
    if(namesize > 0) // if all three names are empty, no need to print this
        printf("\nName of student : %s %s %s", stud.name.frstnme, stud.name.mdlenme, stud.name.lstnme);
    printf("\nD.O.B- %d.%d.%d", stud.dob.dd, stud.dob.mm, stud.dob.yy);
    printf("\nTotal Fees :%f", stud.fees);
}

您仍然可以在代码中修复一些问题以使其更健壮,即输入值验证,这很难用 scanf 实现,我建议将输入读取为文本(使用fgets 或上面提供的自定义行 reader 函数)并使用 strtol / strtod.

安全地转换值

或者,您应该记录代码在输入无效时的行为,无论是超出允许范围的值还是无效输入。

我还建议使用更精确的 double 类型,而不是 float

小问题,您在结构中使用 typedef struct studentinfo 没有效果,您忘记给它命名。