C: gets() skips the first input [closed]

2019-03-04 07:45发布

问题:

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


typedef struct record
{   
    char name[20];
    char surname[20];
    char telephone[20];

}Record;

typedef struct node
{
    Record data;
    struct node *next;
}Node;

Node *head = NULL;

void addRecord(Record s)
{
    Node *newNode;
    Node *n;

    newNode = (Node*)malloc(sizeof(Node));
    newNode->data = s;
    newNode->next = NULL;

    if (head == NULL)
    {
        // The linked list is empty
        head = newNode;
    }
    else
    {
        // Traverse the whole list until we arrive at the last node
        n = head;
        while (n->next != NULL)
        {
            n = n->next;
    }
        n->next = newNode;
    }
}

Record enterRecordDetails()
{
    Record aRecord;
    int len;
    int valid = 0;
    int valid2 = 0;
    printf("ENTER THE FOLLOWING RECORD DETAILS:\n");

    printf("   NAME      : ");
    gets(aRecord.name);
    printf("   SURNAME   : ");
    gets(aRecord.surname);  
    do {
        valid = 0;
        valid2 = 0;
        printf("  TELEPHONE NO. (8 digits): ");
        gets(aRecord.telephone);
        len = strlen(aRecord.telephone);
        for (int i = 0; i < len; i++)
        {
            if (!isdigit(aRecord.telephone[i])) {
                printf("You enterred an invalid number\n");
                valid = 1; break;
            }
        }
        Node *p = head;         
            while (p != NULL)
            {
                Node *next = p->next;
                for (; next; p = next, next = next->next) {
                    if (strcmp(p->data.telephone, aRecord.telephone) == 0)
                    {
                        valid2 = 1; break;
                    }
                }
                if(p = NULL)break;
            }

    } while((valid == 1) || (len != 8) || (valid2 == 1));
    getchar();
    fflush(stdin);
    return aRecord;
}


int main(void)
{
    char menuOption;

    do
    {
        system("cls");
        printf("~~~ MAIN MENU ~~~\n");
        printf("1. Add Telephone Record\n");
        printf("2. Delete Telephone Record\n");
        printf("3. Search\n");
        printf("4. Display All Records\n");
        printf("5. Exit\n\n");
        menuOption = getchar();
        fflush(stdin);
        switch (menuOption)
     {
    case '1':
        addRecordToList();
        break;
    case '4':
        displayList();
        break;
    }

} while (menuOption != '5');

getchar();
return 0;

}

When adding a student, the computer asks the user to enter the surname rather than the name. Why is the program skipping 'Name' ? 'Name' is displayed, however the user is expected to write the surname instead.

回答1:

First, do not use gets, it's unsafe. Use fgets instead.

The reason why the first call to gets skips a line is that there is a '\n' in the buffer at the time that you are making a call to enterRecordDetails(). Typically, the '\n' is a leftover from an earlier input operation, for example, from reading an int with scanf.

One way to fix this problem is to read the string to the end when reading the int, so that the consecutive call of fgets would get the actual data. You can do it in your enterRecordDetails() function:

Record enterRecordDetails()
{
    Record aRecord;
    printf("ENTER THE FOLLOWING RECORD DETAILS:\n");
    printf("   NAME      : ");
    fscanf(stdin, " "); // Skip whitespace, if any
    fgets(aRecord.name, 20, stdin);
    printf("   SURNAME   : ");
    fgets(aRecord.surname, 20, stdin);  
}

Note, however, that fgets keeps '\n' in the string, as long as it fits in the buffer. A better approach would be using scanf, and passing a format specifier that limits the length of input and stops at '\n':

scanf(" %19[^\n]", aRecord.name);
//     ^