Προς το περιεχόμενο

Insert element


panosxry

Προτεινόμενες αναρτήσεις

Δημοσ.

Γεια σας! Θέλω να γράψω μια συνάρτηση σε C που προσθέτει ένα νέο στοίχειο στο τέλος μιας απλα συνδεδεμένης λίστας.

Ο κώδικας μου μέχρι τώρα:

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

typedef struct {
       double x;
       double y;
} point;

typedef struct node {
       point data;
       struct node *next;
} *node_t;

void InsertPoint (node_t *, point);


main(){
      point p;
      char c;
      node_t *head=NULL;


      do{

      printf("Insert the x and y coordinates of your point:\n");
      scanf("%lf %lf", &p.x, &p.y);

      InsertPoint(head, p);

      printf("Will you insert another point?(\'y\'/\'n\')\n");
      scanf("%c", c);

      } while (c!='n');


      system("pause");
      return 0;
}

void InsertPoint (node_t *head, point p) {
    node_t n, temp;

    n=(node_t)malloc(sizeof(*node_t));

    if (n==NULL) exit(1);
    else { 

    n->data = p; 
    n->next=NULL;

    if (*head==NULL) *head=n;
    else {
         temp=*head;

         while (temp->next!=NULL)
         temp=(temp->next);

         temp->next=n;
         }
}
}

 

Το πρόγραμμα δεν τρέχει. Μπορείτε να μου πείτε που έχω κάνει λάθος? Τώρα μαθαίνω τη γλώσσα

Δημοσ.

Από μια γρήγορη ματιά που του ρίχνω τώρα, διακρίνω πολλά και διάφορα προβλήματα.

 

Π.χ. λανθασμένη χρήση του * για τους δείκτες, "if (n=NULL)" αντί για "if (n == NULL)" κλπ... προφανώς θα υπάρχουν κι άλλα.

 

Μια μικρή παράκληση, αφού ξεκινάς τώρα καλό θα ήταν να μάθεις να χρησιμοποιείς καλό & ευδιάκριτο στυλ γραφής του κώδικα.

 

Γιατί ειλικρινά το παραπάνω δείγμα με αποτρέπει από το να το διαβάσω και με αποπροσανατολίζει κιόλας (χάνω τον μπούσουλα με άλλα λόγια... οκ υπερβάλλω, γιατί είναι πολύ λίγος αυτό ο κώδικας, αλλά λίγο να μεγαλώσει με 2-3 συναρτήσεις ακόμα δεν θα απέχει και πολύ ... :P).

Δημοσ.

ok, το "n==NULL", το έφτιαξα (δική μου απροσεξία :whistle: ) και το έκανα πιστεύω λίγο πιο ευδιάκριτο.

Μπορείς να μου εξηγήσεις ποια είναι η λάθος χρήση γιατί αυτό ακριβώς με ενδιαφέρει!

Δημοσ.

Μόλις το έβαλα στο IDE μου και το κοιτάω (στο φτιάχνω).

 

Βασικά γίνεται μύλος, δείχνεις να έχεις κατα-μπερδευτεί με τους δείκτες, ε;

Δημοσ.

ναι αρκετα, και γενικά με την λογικη δεικτη σε δείκτη που έχει η συναρτηση (έτσι πρέπει να το κάνω σύμφωνα με την άσκηση γιατί προφανώς θα υπάρχει και διαφορετική υλοποίηση).

Δημοσ.

"Εισαγωγή σημείων σε απλά συνδεδεμένη λίστα με με τη συνάρτηση InsertPoint. Μετά την εισαγωγή κάθε σημείου, ο χρήστης θα επιλέγει αν θέλει να εισάγει και άλλο στοιχείο ή θέλει να σταματήσει." (και έχω δεδομένα τα typedef και το prototype της συνάρτησης)

Δημοσ.
>
void InsertPoint (node_t *, point);


main(){
  	point p;
  	char c;
       //node_t *head=NULL;
node_t head = NULL;


  	do{

  	printf("Insert the x and y coordinates of your point:\n");
  	scanf("%lf %lf", &p.x, &p.y);

       //InsertPoint(head, p);
InsertPoint(&head,p);

  	printf("Will you insert another point?(\'y\'/\'n\')\n");
  	scanf("%c", c);

  	} while (c!='n');


  	system("pause");
  	return 0;
}

 

Δημοσ.

Με τσάκισες, τα είχα αλλάξει όλα :rolleyes:

 

Φτου κι από την αρχή τώρα :P

 

Καλέ μου φίλε σορρυ, αλλά δεν την παλεύω με την άσκηση. Δεν μου κάθεται με τίποτα, ίσως επειδή είμαι κουρασμένος.

 

Πάντως το 2ο typdef δεν ξέρω τι πιθανότητες έχει να υπάρχει σε real life applications. Ουσιαστικά πάει και μασκαρεύει τον δείκτη μέσα σε custom data type, σαν να τον τρώει ο κώλος του (με το συμπάθιο) για bugs.

 

Εγώ ξέρω πως τους δείκτες πρέπει να τους κάνουμε όσο το δυνατόν πιο ευδιάκριτους κι όχι να τους κρύβουμε μέσα σε πρόσθετους τύπους δεδομένων.

 

Εγώ αυτά τα typedefs πάντως θα τα έκανα έτσι...

 

>
typedef struct {
       double x;
       double y;
} point;

typedef struct node {
       point data;
       struct node *next;
} node_t;

 

και το πρότυπο έτσι...

 

>
void InsertPoint (node_t **, point);

 

έτσι...

 

>
node_t *InsertPoint (node_t *, point);

 

ή ακόμα κι έτσι...

 

>
node_t *InsertPoint (node_t **, point);

 

ΥΓ. Btw, στο scanf που διαβάζεις το c, πρέπει να το βάλεις &c

 

Τέσπα, ορίστε ο κώδικας...

 

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

typedef struct {
       double x;
       double y;
} point;

typedef struct node {
       point data;
       struct node *next;
} *node_t;

void InsertPoint (node_t *, point);
void print_list( node_t );
void destroy_list( node_t *);

// ------------------------------------------------------------------------------
int main( void )
{
point p;
node_t head = NULL;

do{
	printf("\nInsert the x and y coordinates of your point: ");
	fflush(stdin);
	scanf("%lf %lf", &p.x, &p.y);

	InsertPoint(&head, p);
	print_list( head );

	printf("Will you insert another point ( /n)? ");
	fflush(stdin);
} while ( getchar() != 'n');

destroy_list( &head );
return 0;
}

// ------------------------------------------------------------------------------
void InsertPoint( node_t *head, point p )
{
node_t save, temp;
struct node *new;

new = malloc( sizeof( struct node ) );
if ( !new )
	return;

new->data = p; 
new->next = NULL;

if ( !*head  ) {
	*head = new;
	return;
}

save = temp = *head;

while ( save  ) {
	temp = save;
	save = save->next;
}
temp->next = new;

return;
}

// ------------------------------------------------------------------------------
void print_list( node_t head )
{
puts("-----------------------------------");
while ( head ) {
	printf("(%lf,%lf)\n", head->data.x, head->data.y);
	head = head->next;
}

return;
}

// ------------------------------------------------------------------------------
void destroy_list( node_t *head )
{
node_t dummy = *head;
while ( *head  )
{
	dummy = (*head)->next;
	free( *head );
	*head = dummy;
}
}

Δημοσ.

ναι αρκετα, και γενικά με την λογικη δεικτη σε δείκτη που έχει η συναρτηση (έτσι πρέπει να το κάνω σύμφωνα με την άσκηση γιατί προφανώς θα υπάρχει και διαφορετική υλοποίηση).

 

 

Τότε, δες στο άρθρο http://www.insomnia.gr/topic/409154-απορία-ουρές-c/

 

Έχω παραθέσει κάποιο κώδικα μου, που είναι για ουρά, αλλά σου κάνει και εσένα με ελάχιστες τροποποιήσεις.

 

 

Υ.Γ. Νομίζω ότι ο παπι έκανε μία σημαντική διόρθωση στον κώδικά σου.

Δημοσ.

Δεν ήθελε μια οποιαδήποτε υλοποίηση, αλλά τη συγκεκριμένη, με τα typedef και το πρότυπο που παρέθεσε στο αρχικό ποστ.

 

Του τον έγραψα όλο τον κώδικα τελικά, όπως ακριβώς ήταν η άσκησή του... είναι ποσταρισμένος ολόκληρος ακριβώς από πάνω.

 

ΥΓ. Το θέμα είναι πως αυτές οι ασκήσεις είναι πολύ σπαστικές, γιατί τις βάζουν απλά για να τους δυσκολέψουν και όχι να τους εξοικειώσουν με real life τεχνικές & παραδείγματα.

Δημοσ.

Σήμερα που είμαι ξεκούραστος, σου έβαλα σχόλια στον αρχικό σου κώδικα, με τα λάθη που είχες:

 

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

typedef struct {
       double x;
       double y;
} point;

typedef struct node {
       point data;
       struct node *next;
} *node_t;					// !!! αυτό πρέπει να αποφεύγεται !!!!
					// (καμουφλαρισμένος δείκτης σε data type)

void InsertPoint (node_t *, point);		// !!! το γιατί, είναι προφανές εδώ !!!
					// (για να "θυμηθείς" πως πρόκειται για:
					// struct node ** πρέπει να δεις το typedef)

main(){
      point p;
      char c;
      node_t *head=NULL;			// πρέπει να γίνει: node_t head = NULL;


      do{

      printf("Insert the x and y coordinates of your point:\n");
      scanf("%lf %lf", &p.x, &p.y);

      InsertPoint(head, p);			// πρέπει να γίνει: InsertPoint( &head, p );

      printf("Will you insert another point?(\'y\'/\'n\')\n");
      scanf("%c", c);				// πρέπει να γίνει: scanf("%c", &c);

      } while (c!='n');


      system("pause");
      return 0;
}

void InsertPoint (node_t *head, point p) {
    node_t n, temp;				// το n καλύτερα: struct node *n;


    n=(node_t)malloc(sizeof(*node_t));		// n = malloc( sizeof(struct node) );

    if (n==NULL)
	exit(1);			// καλύτερα: return;

//   else					μετά από return ( ή exit() )...
//   {						δεν έχει λόγο ύπαρξης το else
    n->data = p; 
    n->next=NULL;

    if (*head==NULL)
	*head=n;
    else {
         temp=*head;			// χρειαζόμαστε ακόμα έναν προσωρινό δείκτη
				// node_t save = *head;
         while (temp->next!=NULL)	// να γίνει:	while ( save != NULL ) {
         temp=(temp->next);		// 			temp = save;
				//			save = save->next;
				//		}
         temp->next=n;
         }
//   }
}

 

Ολοκληρωμένο κώδικα που εμφανίζει τη λίστα μετά από κάθε εισαγωγή νέου κόμβου, καθώς και την απελευθέρωση της δεσμευμένης μνήμης πριν τον τερματισμό του προγράμματος, σου έχω ποστάρει λίγο παραπάνω. Ότι άλλη απορία έχεις, ρώτα ;)

Δημοσ.

Φίλε, σε ευχαριστώ πολύ για την απασχόλησή σου με το θέμα και σόρρυ αν σε κούρασα :rolleyes:

Το προγραμματάκι δουλεύει μια χαρά τώρα και πιστεύω ότι το έχω πια ^_^ .

 

Θα συμφωνήσω μαζί σου για το typedef, αφού ενώ δεν αλλάζει ουσιαστικά τίποτα, ούτε δυσκολεύει πολύ η χρήση, βλέποντας τον κώδικα αργότερα, μπορεί να δυσκολευτεί κανείς αρκετά μέχρι να καταλάβει τι γίνεται.

 

Μια ερώτηση: είτε πω

> node_t *head=NULL; InsertPoint(head, p);

είτε

>node_t head = NULL; InsertPoint( &head, p );

το ίδιο πράγμα δεν είναι? :huh: Σε κάθε περίπτωση η διεύθυνση του δείκτη δεν περνάει στην InsertPoint?

 

Α και το

>fflush(stdin);

που έβαλες τι ακριβώς κάνει?

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...