Ich habe ein Programm geschrieben, das einen gewissen Wert erhält und es in eine sortierte verknüpfte Liste einfügt. Das Problem ist, dass das Programm nach Eingabe des ersten Werts stoppt und nicht einmal die Einfügefunktion ausführt

Ich weiß, dass das Problem darin besteht, Argumente an die Einfügefunktion zu übergeben, aber ich weiß nicht, wie ich es beheben soll.

    #include <stdio.h>
#include <stdlib.h>
struct record{
    int data;
    struct record *nextptr;
};
void insert (struct record *ptr,int value);
void printList(struct record *ptr);

int main() {
    struct record *headptr = NULL;
    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value");
        scanf("%d", &data);
        insert(headptr, data);
    }
    printList(headptr);


    return 0;
}
void insert (struct record *ptr,int value){
    printf("WE ARE IN THE INSERT FUNCTION");
    struct record *newptr = (struct record *) malloc(sizeof(struct record));
    newptr->data=value;
    newptr->nextptr=NULL;
    struct record *curptr;
    curptr=ptr;

    while(value >= (curptr->data)){
        curptr=curptr->nextptr;
    }
    if (curptr==NULL){
        ptr=newptr;
    }
    else{
        newptr->nextptr=curptr;
    }

}
void printList(struct record *ptr){
    while((*ptr).nextptr != NULL){
        printf("%d", ptr->data);
        ptr=ptr->nextptr;
    }
}

Ergebnis:

/ Users / Danial / CLionProjects / Beispiel / cmake-build-debug / Beispiel Geben Sie Ihren Wert ein3

Prozess mit Exit-Code 11 beendet

1
Danialz 18 Jän. 2019 im 11:41

4 Antworten

Beste Antwort

Sie haben zwei große Probleme mit insert. Zuerst übergeben Sie ptr als Zeiger struct record. In diesem Fall erhält Ihre insert -Funktion eine Kopie des Zeigers , die auf denselben Speicherort im Speicher verweist, jedoch selbst eine eindeutige Adresse hat, die sich stark von dem übergebenen Zeiger unterscheidet main(). Was dies bedeutet, spielt keine Rolle, was Sie mit der Kopie des Zeigers in insert tun. Diese Änderungen werden in main() nie wieder angezeigt, da Sie eine Kopie bearbeiten und ansonsten keinen Wert zurückgeben. Um dieses Problem zu beheben, geben Sie Ihren Parameter struct record ** ein und übergeben Sie die Adresse des Zeigers von main().

Das nächstgrößere Problem in insert besteht darin, dass Sie nicht überprüfen können, ob curptr NULL ist (wie beim ersten Aufruf von insert), bevor Sie mit der Dereferenzierung beginnen { {X4}} - führt wahrscheinlich zu einem Segfault oder einem anderen Lauf der Mühle Undefiniertes Verhalten.

Beim Erstellen einer verknüpften Liste müssen Sie zwei unterschiedliche Testbedingungen erfüllen:

  1. Füge ich den ersten Knoten ein? (wenn ja, weisen Sie einfach `* ptr = newptr zu); und
  2. Bei allen anderen Einfügungen müssen Sie iterieren, um die richtigen 2-Knoten zum Einfügen Ihrer Daten basierend auf dem value des data zu finden.

Sie können beide Fälle einfach behandeln:

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */

In jedem Programm, das Sie schreiben und das Speicher zuweist, müssen Sie einen Zeiger auf den Anfang jedes zugewiesenen Blocks beibehalten, damit er freigegeben werden kann, wenn dieser Speicher nicht mehr benötigt wird. Im Allgemeinen möchten Sie eine listfree - Funktion schreiben, um dies für Sie zu erledigen. Sie könnten etwas Einfaches wie das Folgende schreiben:

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

( Hinweis: wie der freizugebende Knoten in einem temporären Zeiger victim gespeichert wird, bevor die Liste zum nächsten Knoten weitergeleitet wird).

Alles in allem könnten Sie Folgendes tun:

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

typedef struct record {
    int data;
    struct record *nextptr;
} rec_t;

void insert (rec_t **ptr, int value);
void printList (rec_t *ptr);
void freelist (rec_t *head);

int main (void) {
    rec_t *headptr = NULL;

    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value: ");
        scanf("%d", &data);
        insert (&headptr, data);
    }
    printList(headptr);
    freelist (headptr);

    return 0;
}

void insert (rec_t **ptr, int value) 
{
    if ( ptr == NULL ) {
        return;  
    } 

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);  /* don't cast the return */
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */
}

void printList(struct record *ptr)
{
    while (ptr != NULL) {
        printf(" %d", ptr->data);
        ptr = ptr->nextptr;
    }
    putchar ('\n');
}

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

Beispiel für Verwendung / Ausgabe

$ ./bin/lltcmpl
Enter your value: 1
Enter your value: 8
Enter your value: 5
Enter your value: 7
 1 5 7 8

$ ./bin/lltcmpl
Enter your value: 2
Enter your value: 1
Enter your value: 4
Enter your value: 3
 1 2 3 4

Schauen Sie sich die Dinge an und lassen Sie mich wissen, wenn Sie Fragen haben.

0
David C. Rankin 18 Jän. 2019 im 19:14

Hier deklarieren Sie headptr und setzen es auf NULL:

struct record *headptr = NULL;

Dann übergeben Sie es an insert:

insert(headptr, data);

Also ist ptr in insert NULL:

void insert(struct record *ptr, int value)

Sie setzen dann curptr = ptr;, also ist curptr NULL. Es stürzt dann in dieser Zeile ab:

while (value >= (curptr->data)) {

Weil Sie versuchen, auf den Speicher zuzugreifen, auf den curptr zeigt, der zu diesem Zeitpunkt NULL ist.

Ich vermute, Sie wollten headptr Speicher zuweisen, bevor Sie ihn an insert übergeben. Oder behandeln Sie den Fall, dass der Zeiger NULL in insert ist.

0
Blaze 18 Jän. 2019 im 08:47

Wenn Sie einen Zeiger an eine Funktion übergeben, können Sie den Zeiger nicht ändern, obwohl Sie den Inhalt dessen ändern können, auf den der Zeiger zeigt. Um dies zu erreichen, müssen Sie einen Zeiger an den Zeiger übergeben:

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

struct record{
    int data;
    struct record *nextptr;
};

void insert (struct record** ptr, int value);
void printList(struct record *ptr);

int main() {
    struct record *headptr = NULL;
    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value");
        scanf("%d", &data);
        insert(&headptr, data);
    }
    printList(headptr);
    return 0;
}

void insert (struct record** ptr, int value) {
    if ( ptr == NULL ) {
    //Do nothing ptr is invalid
        return;  
    } 
    printf("WE ARE IN THE INSERT FUNCTION");
    struct record* curptr = *ptr
                ,* newptr = (struct record *) malloc(sizeof(struct record));
    newptr->data = value;
    //Check curptr isn't NULL
    while(curptr != NULL && value >= (curptr->data)){
        curptr = curptr->nextptr;
    }
    if (curptr == NULL) {
        newptr->nextptr = NULL;
        *ptr = newptr;
    } else {
        newptr->nextptr = curptr;
    }
}

void printList(struct record *ptr){
    while(ptr->nextptr != NULL) {
        printf("%d", ptr->data);
        ptr = ptr->nextptr;
    }
}
0
SPlatten 18 Jän. 2019 im 08:55

Verwenden Sie zunächst setbuf(stdout, NULL);, wenn Ihre Ausdrucke geleert werden sollen, bevor Ihr Programm unerwartet beendet wird.

Zweitens greifen Sie, wie bereits erwähnt, auf ein NULL Zeigerelement in while (value >= (curptr->data)) zu, das den Absturz verursacht.

Drittens ist auch Ihre insert und print Logik falsch.

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

struct record{
    int data;
    struct record *nextptr;
};

void insert (struct record **ptr,int value);
void printList(struct record *ptr);

int main() {
    setbuf(stdout, NULL);
    struct record *headptr = NULL;
    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value");
        scanf("%d", &data);
        insert(&headptr, data);
    }
    printList(headptr);


    return 0;
}
void insert (struct record **head,int value){
    printf("WE ARE IN THE INSERT FUNCTION");
    struct record *newptr = (struct record *) malloc(sizeof(struct record));
    newptr->data=value;
    newptr->nextptr=NULL;
    struct record *curptr=*head;
    struct record *prevcurptr=NULL;

    while(curptr!=NULL && value >= (curptr->data)){
        prevcurptr=curptr;
        curptr=curptr->nextptr;
    }
    if (curptr==NULL){
        if (prevcurptr==NULL) {         
            *head=newptr;
        } else {
            newptr->nextptr=prevcurptr->nextptr;
            prevcurptr->nextptr=newptr;
        }
    }
    else{
        newptr->nextptr=curptr;
        if (prevcurptr==NULL)       
            *head=newptr;
        else
            prevcurptr->nextptr=newptr;
    }

}
void printList(struct record *ptr){
    while(ptr != NULL){
        printf("\n %d", ptr->data);
        ptr=ptr->nextptr;
    }
}
0
d9ngle 18 Jän. 2019 im 10:09