0
#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.

Simon Sultana
  • 235
  • 1
  • 2
  • 13

1 Answers1

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);
//     ^
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • `scanf("%19[^\n]", aRecord.surname);` reads nothing into `aRecord.surname` if the first character is `'\n'`, leaving it uninitialized and the offending `'\n'` in `stdin`. This would certainly happen as a previous `scanf("%19[^\n]", aRecord.name);` does not consume the `'\n'`. Best to use `fgets()`. – chux - Reinstate Monica Apr 06 '16 at 18:03
  • @chux My only reservation about `fgets` is its keeping the `\n` in my string. Of course it's easy to get rid of that string, but it's better to not have it there in the first place. – Sergey Kalinichenko Apr 06 '16 at 18:13
  • I disagree is is _easier_ using `scanf()` and not get the `'\n'` than `fgets()`. YMMV. – chux - Reinstate Monica Apr 06 '16 at 18:19
  • 1
    Basically the only way to do sensible line-based input in C is to write your own function for it, which does it the way you want (using `fgets` or `scanf` or `getchar` or whatever internally). If you use `scanf` or `fgets` directly, your code gets cluttered with error, long line and buffer size handling (or, more commonly, these aren't really handled, and things go haywire on unexpected input). Or just use [`getline`](http://linux.die.net/man/3/getline) if you are programming for recent POSIX or GNU OS... – hyde Apr 06 '16 at 18:20
  • 1
    @chux You are right, this would mess up the prompts. I agree with hyde, by the way, that if one wants to do it right, he needs to do it himself, i.e. use `fgets` to read line-by-line, and then parse the data manually. – Sergey Kalinichenko Apr 06 '16 at 18:25
  • Agree with you and @hyde. User input is _evil_ and needs handling better than direct use of C standard input functions. – chux - Reinstate Monica Apr 06 '16 at 18:31
  • @dasblinkenlight Why Did You Left a space before " %19[^\n]" – Suraj Jain Feb 24 '17 at 07:21