Почему моя программа резко прерывается? - PullRequest
0 голосов
/ 27 марта 2020
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

static int COUNT = 1;
typedef struct node NODE;
struct node
{
    int data;
    NODE *next;
};

NODE *START = NULL;

NODE *create_node() {
    NODE *n = malloc(sizeof(NODE));
    n->data = 0;
    n->next = NULL;
    return n;
}

void insert_at_beginning() {
    NODE *n, *temp;
    n = create_node();
    printf("Enter a number: ");
    scanf("%d",&n->data);
    if(START == NULL) {
        START = n;
    } else {
        temp = START;
        START = n;
        n->next = temp;
    }

    COUNT++;
    printf("Successfully Inserted!\n");    
}

void insert_at_a_position() {
    int position, count;
    NODE *n, *temp, *t;
    printf("Enter position at which you want to insert: ");
    scanf("%d", &position);

    if(COUNT<position) {
        printf("Out of Bound! Please try again.\n");
    } else
    {
        count = 1;
        n = create_node();
        printf("Enter a number: ");
        scanf("%d",&n->data);
        temp = START;
        while(count != position) {
            count++;                    //To stoping the variable at given position
            t = temp;                   //Getting Previous node where we will set link to  n
            temp = temp->next;          //getting next element whose link will be attached to n to form complete linked list
        }
        n->next = temp;
        t->next = n; 
        COUNT++;
        printf("Successfully Inserted!\n");  
    }
}

void insert_at_end() {
    NODE *n, *temp;
    temp = START;
    n = create_node();
    printf("Enter a number: ");
    scanf("%d", &n->data);
    while(temp!=NULL) {
        printf("I am here!");
        temp = temp->next;
    }
    temp->next = n;
    COUNT++;
    printf("Successfully Inserted!\n");  
}
void display() {
    NODE *temp;
    temp = START;

    while (temp!=NULL)
    {
        printf("%d", temp->data);
        temp = temp->next;
    }


}

int main() {
    int ch;
    printf("1.Insert at beginning\n2.Insert at mid\n3.Insert at end\n4.Delete from beginning\n5.Delete from position\n6.Delete from end\n7.Display");
    printf("\nEnter your choice: ");
    scanf("%d", &ch);
    while (ch!=0)
    {
        switch(ch) {
            case 1:
                insert_at_beginning();
                break;
            case 2:
                insert_at_a_position();
                break;
            case 3:
                insert_at_end();
                break;
            case 4:
                display();
                break;
            default:
                printf("Wrong Choice!!");
        }
        printf("Enter Your Choice: ");
        scanf("%d",&ch);
    }


    return 0;
}

insert_at_beginning и insert_at_end работают отлично, но функция insert_at_end и display показывает проблему

В display функция: программа идет бесконечно l oop

В insert_at_end: программа проходит, пока l oop (т. Е. Печатает номер узла «Я здесь»), но затем она внезапно завершается без назначения значения в данной позиции.

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Для начала плохая идея объявлять начальный указатель на узлы как глобальную переменную, и когда функция зависит от глобальных переменных.

Также неясно, почему переменная stati c COUNT инициализируется 1 вместо 0, когда изначально список пуст.

static int COUNT = 1;

Он должен быть инициализирован нулем

static int COUNT = 0;

insert_at_beginning и insert_at_end работает отлично

Вы не правы. Функция insert_at_end недействительна.

void insert_at_end() {
    NODE *n, *temp;
    temp = START;
    n = create_node();
    printf("Enter a number: ");
    scanf("%d", &n->data);
    while(temp!=NULL) {
        printf("I am here!");
        temp = temp->next;
    }
    temp->next = n;
    COUNT++;
    printf("Successfully Inserted!\n");  
}

Например, функцию можно вызывать, когда список пуст, то есть когда указатель START равен NULL. В этом случае указатель START не изменяется в функции.

Более того, даже если указатель START не равен NULL, после этого l oop

    while(temp!=NULL) {
        printf("I am here!");
        temp = temp->next;
    }

температура указателя равна равно NULL. Поэтому следующий оператор

    temp->next = n;

вызывает неопределенное поведение.

Функция может быть записана как минимум следующим образом

void insert_at_end() {
    NODE *n;
    n = create_node();
    printf("Enter a number: ");
    scanf("%d", &n->data);

    if ( START == NULL )
    {
        START = n;
    }
    else
    {
        NODE *temp = START;

        while ( temp->next !=NULL ) 
        {
            printf("I am here!");
            temp = temp->next;
        }

        temp->next = n;
        COUNT++;
        printf("Successfully Inserted!\n");  
    }
}

Что касается функции insert_at_a_position, то Существует путаница относительно глобальной переменной COUNT. Как я указывал изначально, когда список пуст, COUNT равен 1. Таким образом, действительная позиция может быть меньше, чем COUNT. Учтите, что пользователь может ввести, например, значение позиции, равное 0.

Так, например, это, если оператор

if(COUNT<position) {
    printf("Out of Bound! Please try again.\n");
} else

должен быть переписан как

if ( !( position < COUNT ) ) {
    printf("Out of Bound! Please try again.\n");
} else

Также, когда пользователь введет 0, тогда l oop

    count = 1;
    //...
    while(count != position) {
    //...

может вызвать неопределенное поведение.

И снова, если список пуст, то START равен NULL, тогда START не изменяется в функции.

Также, если пользователь ввел позицию, равную 1, тогда в этом случае значение l oop не будет выполнено. В этом случае указатель t имеет неопределенное значение, поскольку он не был инициализирован за пределами l oop. Так что это утверждение

    t->next = n; 

снова вызывает неопределенное поведение.

Функция может быть определена следующим образом

void insert_at_a_position() {
    int position;

    printf("Enter position at which you want to insert: ");
    scanf("%d", &position);

    if( !( position < COUNT ) ) {
        printf("Out of Bound! Please try again.\n");
    } else
    {
        NODE *n = create_node();
        printf("Enter a number: ");
        scanf("%d",&n->data);

        NODE *temp = START;
        NODE *prev = START;

        while( position-- != 0 ) 
        {
            prev = temp;
            temp = temp->next;        
        }

        n->next = temp;
        if ( prev == NULL ) START = n;
        else prev->next = n;

        COUNT++;
        printf("Successfully Inserted!\n");  
    }
}
1 голос
/ 27 марта 2020

Вы разыменовываете нулевой указатель.

while(temp!=NULL) {
    printf("I am here!");
    temp = temp->next;
}
temp->next = n;  // temp is NULL here!!

Вы можете изменить условие l oop на:

while (temp->next != NULL) {

Но прежде чем сделать это, вы должны проверить эту температуру не NULL:

temp = START;
if (temp == NULL) {
    insert_at_beginning();
    return;
}

В сторону: более стандартно просто написать:

if (!temp)

, чем

if (temp == NULL)
...