user3011439
user3011439

Reputation: 35

C linked list no longer working after using then deleting typedef statement

I have a program here to display the next day of the week from an entered day. It is not a practical or efficient program, I am just using it to test the concepts that I have learned. It worked for a while, but then after learning about typedef statements, I tried to use them for the program's structure "weekday" to declare variables of that type, but then deleted the typedef because it created errors (such as "incompatible pointer" and "incomplete definition"). Now, the file displays errors even though I took out the typedef statements. The strangest part is that the errors don't appear if I copy and paste all of the code into a new file. Does anyone know what might be causing the errors?

#include <stdio.h>
#include <stdbool.h>

    struct weekday {
        char *ptrday;
        struct weekday *next;
    };

void matchtest(char *eday, struct weekday *head, struct weekday *cursor) {
    cursor=head;
    bool equalstring=true;

    while (cursor!=NULL) {
        char *p=cursor->ptrday;
        equalstring=true;

        while (*eday!='\0') {
            if (*eday!=*p) {
                equalstring=false;
                break;
            }
            ++eday; ++p;
        }
        if (equalstring==1) {
            printf("The next day of the week is %s\n", cursor->next->ptrday);
            break;
        }
        cursor=cursor->next;
    }
    if (equalstring==false)
        printf("The next day of the week is Sunday\n");
}

int main (void) {
    char enteredday[80], *ptreday=enteredday;
    struct weekday sunday, monday, tuesday, wednesday, thursday, friday, saturday;
    struct weekday *head=&sunday;
    struct weekday *cursor=NULL;

    sunday.ptrday="Sunday"; monday.ptrday="Monday"; tuesday.ptrday="Tuesday";
        wednesday.ptrday="Wednesday"; thursday.ptrday="Thursday";
        friday.ptrday="Friday"; saturday.ptrday="Saturday";

    sunday.next=&monday; monday.next=&tuesday; tuesday.next=&wednesday;
        wednesday.next=&thursday; thursday.next=&friday; friday.next=&saturday;
        saturday.next=NULL;


    printf("This is a test for the next day of the week.\n\n");
    printf("Enter a day ");

    scanf("%s", enteredday);
    matchtest(ptreday, head, cursor);

    return 0;
}

Upvotes: 2

Views: 74

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 755016

One problem you have is that you modify eday in the comparator function, but if the comparison fails, you have no way to set the search to start at the beginning of the string, because you don't know where the string started any more. This afflicts 'Thursday', which reports the 'next day' is Sunday. For some other tests, this worked OK. The next day after Saturday was reported as Sunday because of the kludge.

You also have a problem that the day after Saturday is undefined.

Here is sensibly working code. I use strcmp() (and hence <string.h> too) to do the comparison. I converted the while (cursor != NULL) loop into a do { ... } while (cursor != head); loop so that the circular linked list works correctly. I also print the input as it is read, and again in the formal output. This allows me to test using bash's Here String notation (<<< string) which is convenient. Note that the input checks for EOF and also limits the input string to 79 characters, preventing buffer overruns (aka stack overflows). The 'cursor' parameter to the function was unnecessary; it was set to null in the calling code, but the called function immediately set it to head. So that parameter is no more, but the variable is still needed, so it is purely local to the function.

Code

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

struct weekday
{
    char *ptrday;
    struct weekday *next;
};

static void matchtest(char *eday, struct weekday *head)
{
    struct weekday *cursor = head;

    do
    {
        if (strcmp(eday, cursor->ptrday) == 0)
        {
            printf("The next day of the week after %s is %s\n", eday, cursor->next->ptrday);
            return;
        }
        cursor = cursor->next;
    } while (cursor != head);

    printf("The 'day of the week' %s does not match any day of the week!\n", eday);
}

int main(void)
{
    char enteredday[80];
    struct weekday sunday, monday, tuesday, wednesday, thursday, friday, saturday;
    struct weekday *head = &sunday;

    sunday.ptrday = "Sunday";
    monday.ptrday = "Monday";
    tuesday.ptrday = "Tuesday";
    wednesday.ptrday = "Wednesday";
    thursday.ptrday = "Thursday";
    friday.ptrday = "Friday";
    saturday.ptrday = "Saturday";

    sunday.next = &monday;
    monday.next = &tuesday;
    tuesday.next = &wednesday;
    wednesday.next = &thursday;
    thursday.next = &friday;
    friday.next = &saturday;
    saturday.next = &sunday;

    printf("This is a test for the next day of the week.\n\n");
    printf("Enter a day ");

    if (scanf("%79s", enteredday) == 1)
    {
        printf("Got: [%s]\n", enteredday);
        matchtest(enteredday, head);
    }

    return 0;
}

Example runs

$ for d in Sunday Monday Tuesday Wednesday Thursday Friday Saturday Otherday; do ./nwd <<< $d; done
This is a test for the next day of the week.

Enter a day Got: [Sunday]
The next day of the week after Sunday is Monday
This is a test for the next day of the week.

Enter a day Got: [Monday]
The next day of the week after Monday is Tuesday
This is a test for the next day of the week.

Enter a day Got: [Tuesday]
The next day of the week after Tuesday is Wednesday
This is a test for the next day of the week.

Enter a day Got: [Wednesday]
The next day of the week after Wednesday is Thursday
This is a test for the next day of the week.

Enter a day Got: [Thursday]
The next day of the week after Thursday is Friday
This is a test for the next day of the week.

Enter a day Got: [Friday]
The next day of the week after Friday is Saturday
This is a test for the next day of the week.

Enter a day Got: [Saturday]
The next day of the week after Saturday is Sunday
This is a test for the next day of the week.

Enter a day Got: [Otherday]
The 'day of the week' Otherday does not match any day of the week!
$

As you can tell, I don't like having to type inputs more than once.


Code using a typedef

Also using a linked list in an array (though you could perfectly well just use an array of day names too).

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

typedef struct Weekday Weekday;
struct Weekday
{
    char *ptrday;
    Weekday *next;
};

Weekday days_of_the_week[7] =
{
    { "Sunday",    &days_of_the_week[1] },
    { "Monday",    &days_of_the_week[2] },
    { "Tuesday",   &days_of_the_week[3] },
    { "Wednesday", &days_of_the_week[4] },
    { "Thursday",  &days_of_the_week[5] },
    { "Friday",    &days_of_the_week[6] },
    { "Saturday",  &days_of_the_week[0] },
};

static void matchtest(char *eday, Weekday *head)
{
    Weekday *cursor = head;

    do
    {
        if (strcmp(eday, cursor->ptrday) == 0)
        {
            printf("The next day of the week after %s is %s\n", eday, cursor->next->ptrday);
            return;
        }
        cursor = cursor->next;
    } while (cursor != head);

    printf("The 'day of the week' %s does not match any day of the week!\n", eday);
}

int main(void)
{
    char enteredday[80];

    printf("This is a test for the next day of the week.\n\n");
    printf("Enter a day ");

    if (scanf("%79s", enteredday) == 1)
    {
        printf("Got: [%s]\n", enteredday);
        matchtest(enteredday, days_of_the_week);
    }

    return 0;
}

Upvotes: 1

Related Questions