1

I'm currently learning C, and my assignment is to create a structure that holds in records, and I am supposed to use linked-list. One of my functions is to delete a record by entering the last name. Code stops working after I use fgets(no crash just stops).

struct students
{
char firstname[21];
char lastname[21];
double score;
int zip;
struct students* next;
};
struct students* head;
void add()
{
    struct students* new_node=(struct students*)malloc(sizeof(struct students));
    struct students *past=head;
    fflush(stdin);
    new_node->next=NULL;
    printf("Enter data: \n");
    printf("First name: ");
    fgets(new_node->firstname, 21, stdin);
    printf("Last name: ");
    fgets(new_node->lastname, 21, stdin);
    printf("Score: ");
    scanf("%lf", &new_node->score);
    printf("ZIP code: ");
    scanf("%d", &new_node->zip);
    if(head==NULL)
    {
        head=new_node;
        return;
    }
    while(past->next!=NULL)
    {
        past=past->next;
    }
    past->next=new_node;
    return;
}
void delrec()
{
    char last[21];
    printf("Enter last name: ");
    fflush(stdin);
    fgets(last, 21, stdin);
    struct students* temp=head;
    last[strcspn(last, "\n")]=0;
    if(strcmp(temp->lastname, last)==0)
    {
        struct students *next=temp->next;
        free(temp);
        temp=next;
    }
    while(temp!=NULL)
    {
        if(temp->next==NULL)
        {
            return;
        }
        if(strcmp(temp->next->lastname, last)==0)
        {
            struct students *next=temp->next->next;
            free(temp->next);
            temp->next=next;
        }
        temp=temp->next;
    }
}
int main()
{
    head=NULL;
    int i, x, y;
    printf("Enter 5 records:\n");
    for(i=0; i<5; i++)
    {
        add();
    }
    print();
    printf("What would you like to do?\n");
    y=1;
    while(y)
    {
        printf("Print records (press 1)\n");
        printf("Add new record (press 2)\n");
        printf("Delete record (press 3)\n");
        printf("Exit the program (press 0)\n");
        scanf("%d", &x);
        switch(x)
        {
        case 0:
            y=0;
            break;
        case 1:
            print();
            break;
        case 2:
            add();
            break;
        case 3:
            delrec();
            break;
        }
    }
    return 0;
}

I don't think it has to do with linked-list though, but maybe my inputs or something.

EDIT1: I have found that the error is I forgot to provide temp=temp->next; on the while loop for delrec. My current problem now is that even though I type the exact last name, it will not delete the record/unlink the structure from the list. I have edited the code to show my progress.

EDIT2: No big reason to edit, but just so I don't get unwanted answers, I have been able to figure out how to delete the structure from the linked-list. However, if I delete the structure from the head, it will print very weird text, edited code again to show progress.

Hele
  • 23
  • 3

2 Answers2

2

fgets() will read in the trailing \n as well. So with

fgets(last, 21, stdin);

if you gave "Doe" as input, what is being stored is "Doe\n".

You are comparing this string with a \n at the end with your records.

You need to remove the trailing \n. It might be done with

last[strlen(last)-1] = '\0';

Edit: As joop pointed out, strlen() could return 0 if the string is empty. If strlen(last) gives 0, then last[strlen(last)-1]. As was said, you could use strcspn() instead like

last[strcspn(last, "\n")] = '\0';

strcspn(char *dest, char *src) returns the length of the maximum initial segment of the string pointed by its first argument which consists exclusively of characters which are not in the string pointed to by the second argument.

Also note that the effect of fflush(stdin) is undefined. The standard says (as per this answer),

If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

Have a look at the question and also this.

J...S
  • 5,079
  • 1
  • 20
  • 35
  • added that part after 'struct students* temp=head;', it does help delete a structure, but it deletes the last structure instead of what I want. – Hele Apr 24 '18 at 08:31
  • 2
    Note: `strlen(last)` can be zero, causing `last[strlen(last)-1)] = 0;` to write beyond lasts boundaries. `last[strcspn(last,"\r\n")] = 0;` is the preferred way. – joop Apr 24 '18 at 10:48
-2

Here in your code line

printf("Enter data: \n");

in add() is creating problem, since printf() leaves whitespace in the input buffer from where fgets() will read it.

One solution is put fflush(stdin) after printf() like below :

printf("Enter data: \n");
fflush(stdin);

or you can use scanf() for taking characters with space, like this :

scanf("%[^\n]",new_node->firstname);
Saawaj
  • 41
  • 9
  • Problem persists in the delrec() function even if I change the add() function – Hele Apr 24 '18 at 07:43
  • 3
    Printf leaves whitespace in the input buffer? What a load of rubbish! – John3136 Apr 24 '18 at 07:59
  • 1
    [`fflush(stdin)`](https://stackoverflow.com/questions/2979209/using-fflushstdin) is undefined behavior. You'd better avoid that. – Bob__ Apr 24 '18 at 08:19