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

linked list in C....almost there...


InDiO

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

Δημοσ.

Μαντεψτε...υλοποίηση Linked list(oxi doubly) με structs. Πιατευω πως η σχεδίαση της ολης δομής είναι σωστή, καθώς και η συναρτηση εισαγωγής κόμβου.

Το πρόβλημα:

 

Όταν τυπώνω μέσα απο την συναρτηση της εισαγωγής το node->name παίρνω την σωστή τιμή του string που έχω αποθηκέυσει εκει.Όμως όταν τυπώνω πριν τελειώσει το πρόγραμμα όλα τα names απο όλους τουσ κόμβους με την σειρά, ΠΑΙΡΝΩ ΣΥΝΕΧΩΣ ΤΙΣ ΙΔΙΕΣ ΤΙΜΕΣ. Ειναι σίγουρα κάτι με pointers και scope..

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

struct node					//ORISMOS NODE THS LINKED LIST
{
	char *name;
	struct node * next;
}files;
typedef struct node Node;	//ORISMOS OS TYPO ANTI GIA STRUCT

Node *start=&files;			//H ARXI THS LISTAS
Node *head=&files;			//TO TELOS

void insNode(char *name)
{
	Node *new;
	new=(Node *)malloc(sizeof(Node));
	if(new==NULL)
		return;
	head->next=new;
	new->name=name;
	new->next=NULL;
	head=new;
	printf("OFF:%d inside insNode: %s \n",new,new->name);
}
void main(int argc,char *argv[])
{
        files.next=NULL;
        files.name="riza";
        Node *ptr;
        ptr=start;

	/*KYRIOS PROGRAMMA*/

	int i;
		//EISAGOGI DIERGASION STHN LINKED LIST
	for(i=1;i<argc;i++)	//Elegxos kai Eisagogi ton arxeion stin linked list
	{
		FILE *fin;
		if((fin=fopen(argv[i],"r"))==NULL)		//Apotyxia anoigmatos arxeiou
		{
			printf("File name \"%s\" was not found, discarding argument...\n",argv[i]);
			break;
		}
		char pr_name[15];
		while (fscanf(fin,"%s",pr_name) != EOF)
		{
			insNode(pr_name);
		}
		fclose(fin);
	}

	/*EKTYPOSH APO LISTA*/
	ptr=&files;
	while(ptr)
	{
		printf(" %d - %s\n",ptr->next,ptr->name);
		ptr=ptr->next;
	}


}
 

 

Ζητώ συγνώμη για τον τεράστιο κώδικα. Απλα αρχικά όποιος θέλει να βοηθήσει, αν κοιτάξει πρώτα τον ορισμό της insNode, και γενικώς τι παίζει με την εμβέλεια των μεταβλητών... Δεν περιμένω πολλά πράγματα, ξέρω ότι φαίνεται πολύ περίπλοκο! Συγνώμη και πάλι!

Δημοσ.

Kαι το output..Μεσα και εξω από την insNode. Αυτα παρήχθησαν δίνοντας για όρισμα ένα αρχείο που περιέχει τις λέξεις που τυπώνονται πιο κάτω(αρχικά ειναι και η διεύθυνση μνήμης).

 

OFF:1329920 inside insNode: ooox

OFF:1329936 inside insNode: mporei

OFF:1329952 inside insNode: mmakia

OFF:1329968 inside insNode: les?

----ekso apo tin synartisi

1328656 - riza

1329256 - les?

1329920 - les?

1329936 - les?

1329952 - les?

 

Αν μπορει καποιος να τσεκάρει αν απλα κανω μαλακία με την τελική εκτύπωση...

 

Το προγραμμα υποτίθεται οτι παίρνει αρχεία, και παίρνει 1-1 τις λέξεις τους και τις βάζει σε μια linked list...

Δημοσ.

Εγώ γιατι το έτρεξα και μου τα τύπωσε σωστα;

 

> 
OFF:8735844 inside insNode: fillo1 
OFF:8736268 inside insNode: fillo2 
OFF:8736284 inside insNode: fillo3 
OFF:8736300 inside insNode: fillo4 
OFF:8736316 inside insNode: fillo5 
 8735844 - riza
 8736268 - fillo1
 8736284 - fillo2
 8736300 - fillo3
 8736316 - fillo4
 0 - fillo5
 

 

Αυτο ειναι το output ισως κάτι δεν κατάλαβα σωστα

Δημοσ.

Εγώ έτρεξα αυτόν τον κώδικα:

 

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

struct node					//ORISMOS NODE THS LINKED LIST
{
	char *name;
	struct node * next;
}files;

typedef struct node Node;	//ORISMOS OS TYPO ANTI GIA STRUCT

Node *start=&files;			//H ARXI THS LISTAS
Node *head=&files;			//TO TELOS

void insNode(char *name)
{
	Node *new_node;
	new_node=(Node *)malloc(sizeof(Node));
	if(new_node==NULL)
		return;
	head->next=new_node;
	new_node->name=name;
	new_node->next=NULL;
	head=new_node;
	printf("OFF:%d inside insNode: %s \n",new_node,new_node->name);
}

void main(int argc,char *argv[])
{
        files.next=NULL;
        files.name="riza";
        Node *ptr;
        ptr=start;

	/*KYRIOS PROGRAMMA*/

	int i;
		//EISAGOGI DIERGASION STHN LINKED LIST
    insNode("fillo1");
    insNode("fillo2");
    insNode("fillo3");
    insNode("fillo4");
    insNode("fillo5");

	/*EKTYPOSH APO LISTA*/
	ptr=&files;
	while(ptr)
	{
		printf(" %d - %s\n",ptr->next,ptr->name);
		ptr=ptr->next;
	}

    scanf("asdf");
}
 

 

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

 

Δημοσ.

Το έκανα με τον τρόπο που κάνεις και εσύ , και έχω το ίδιο λάθος output.

Το λαθος βέβαια ειναι προφανές.

Στο insNode περνάς ένα pointer char * name

Το συγκεκριμένο την στιγμή που το περνάς δείχνει σε μια διευθυνση.

Όταν αλλάξει την διευθυνση η fscanf, ο pointer που έχεις δείχνει και αυτός στην καινούργια διευθυνση.

Για αυτό τα υπολοιπα στοιχεία σου δείχνουν τον τελευταίο name.

Οπότε η λύση ειναι να αντιγράφεις τον char και μετά να το περνάς.

 

Ελπίζω να βοήθησα.

 

>void main(int argc,char *argv[])
{

files.next=NULL;
files.name="riza";
Node *ptr;
ptr=start;

/*KYRIOS PROGRAMMA*/

int i;
//EISAGOGI DIERGASION STHN LINKED LIST
for(i=1;i<argc;i++) //Elegxos kai Eisagogi ton arxeion stin linked list
{
    FILE *fin;
    if((fin=fopen(argv[i],"r"))==NULL) //Apotyxia anoigmatos arxeiou
    {
        printf("File name \"%s\" was not found, discarding argument...\n",argv[i]);
        break;
    }

    char * pr_name;
    while (fscanf(fin,"%s",pr_name) != EOF)
    {
        insNode(pr_name);
        pr_name=&pr_name[strlen(pr_name)+1];
    }
    fclose(fin);
}

    /*EKTYPOSH APO LISTA*/
    ptr=&files;
    while(ptr)
    {
        printf(" %d - %s\n",ptr->next,ptr->name);
        ptr=ptr->next;
    }

    scanf("dfsdf");
}  

 

Το παραπάνω παίζει σωστά και δίνει output

 

> OFF:8736768 inside insNode: 1 
OFF:8736784 inside insNode: 2 
OFF:8736800 inside insNode: 3 
OFF:8736816 inside insNode: op 
OFF:8736832 inside insNode: to 
OFF:8736848 inside insNode: erixa 
OFF:8736864 inside insNode: sto 
OFF:8736880 inside insNode: sorolo 
 8736768 - riza
 8736784 - 1
 8736800 - 2
 8736816 - 3
 8736832 - op
 8736848 - to
 8736864 - erixa
 8736880 - sto
 0 - sorolo 

Δημοσ.

Φίλε μου πραγματικά σε ευχαριστώ για το -άμεσο- ενδιαφέρον σου!

 

>
char *pr_name;
	while (fscanf(fin,"%s",pr_name) != EOF)
	{
		insNode(pr_name);
        pr_name=&pr_name[strlen(pr_name)+1];
    }

 

Κατάλαβα τι λες. Νομίζω πως η μόνη αλλαγή που προτείνεις στον κώδικά μου ειναι στο παραπάνω σημείο. Πρεπει να σου πω ότι στο δικό μου PC, αυτος ο κώδικας κάνει runtime error! Τι παίζει;;;

Έχω τον lcc 3.x για win, λινουξ δεν παιζει τωρα στις γιορτές...

Δημοσ.

Λοιπόν ο παρακάτω κώδικας λειτουργεί σε Windows 2000, C/C++ Builder 5 και εκτυπώνει τα εξείς (αν δώσουμε σε ένα αρχείο το κείμενο THIS IS NAME 1):

 

>
OFF:7949348 inside insNode: THIS
OFF:7949372 inside insNode: IS
OFF:7949396 inside insNode: NAME
OFF:7949420 inside insNode: 1
 7949348 - riza
 7949372 - THIS
 7949396 - IS
 7949420 - NAME
 0  1

---

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

struct node					//ORISMOS NODE THS LINKED LIST
{
        /* directx changes */
	char name[15];
        /* end of directx changes */

	struct node * next;
}files;
typedef struct node Node;	//ORISMOS OS TYPO ANTI GIA STRUCT

Node *start=&files;			//H ARXI THS LISTAS
Node *head=&files;			//TO TELOS

 /* directx changes */
 Node *ptr;
 int i;
 char pr_name[15];
 /* end of directx changes */

void insNode(char *name)	// dx change: new renamed to NewNode for better reading
{
	Node *NewNode;
	NewNode=(Node *)malloc(sizeof(Node));
	if(NewNode==NULL)
		return;
	head->next=NewNode;

	//NewNode->name=name;
        strcpy(NewNode->name,name); // <- dx. change!

	NewNode->next=NULL;
	head=NewNode;
	printf("OFF:%d inside insNode: %s \n",NewNode,NewNode->name);
}
void main(int argc,char *argv[])
{
        files.next=NULL;
        strcpy(files.name,"riza"); // <- dx. change!
        //files.name="riza";
        ptr=start;

	/*KYRIOS PROGRAMMA*/

		//EISAGOGI DIERGASION STHN LINKED LIST
	for(i=1;i<argc;i++)	//Elegxos kai Eisagogi ton arxeion stin linked list
	{
		FILE *fin;
		if((fin=fopen(argv[i],"r"))==NULL)		//Apotyxia anoigmatos arxeiou
		{
			printf("File name \"%s\" was not found, discarding argument...\n",argv[i]);
			break;
		}
		while (fscanf(fin,"%s",pr_name) != EOF)
		{
			insNode(pr_name);
		}
		fclose(fin);
	}

	/*EKTYPOSH APO LISTA*/
	ptr=&files;
	while(ptr)
	{
		printf(" %d - %s\n",ptr->next,ptr->name);
		ptr=ptr->next;
	}
}

 

Η αλλαγή που έκανα είναι ότι όρισα σταθερό μέγεθος στο node typedef έτσι ώστε το NewNode=(Node *)malloc(sizeof(Node)); Να έχει νόημα αφού διαφορετικά δεν λέει τίποτα στον compiler μιας και το char* πρακτικά δεν έχει κανένα μέγεθος!

 

Φυσικά αν έχεις διάθεση μπορείς να προσθέσεις κώδικα που να δεσμεύει την απαιτούμενη μνήμη στο char* name δυναμικά..

 

* Με βάση τα παραπάνω καταλαβαίνεις γιατί άλλαξα το *=κάτι σε strcpy..

 

* Κάποιες αλλαγές στην ονομασία ήταν απαραίτητες για να διαβάσω καλύτερα τον κώδικα αφ ετέρου για να γίνει compile το πρόγραμμα από τον C/C++ Builder.

 

Ελπίζω κάτι από τα παραπάνω να δουλέψει στο μηχάνημα σου, όπως και να έχει

 

Καλή τύχη.

 

Δημοσ.

Το ίδιο περίπου με τον DirectX

>
void insNode(char *name){
Node *new;
new=(Node *)malloc(sizeof(Node));
if(new==NULL)
  return;
head->next=new;                         
new->name=(char*)malloc(strlen(name)+1);   /*        EDW        */
strcpy(new->name,name);                    /*     kai edw       */
new->next=NULL; 
head=new;
printf("OFF:%d inside insNode: %s \n",new,new->name);
}


 

Δημοσ.

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

 

Θα ήθελα να ρωτήσω όμως, για καθαρά εκπαιδευτικούς σκοπούς. Πως θα μπορούσα να κάνω το char[15] να δίνεται δυναμικά, αναλογα με το πόσο μεγάλο όνομα διαβάζεται; Θέλω να πω ότι γνωρίζω ότι υπάρχει η malloc, αλλά λόγω της ενασχόλησης με Java(και κυρίως λόγω ελλιπούς πρακτικής <img src="http://www.insomnia.gr/ubbthreads/images/graemlins/smile.gif" alt="" />) δεν έχω καταλάβει ακριβώς πότε δεν χρειάζεται και πότε όχι.

Όταν ας πούμε, λέμε:

>
Node *new;
new=(Node *)malloc(sizeof(Node));

Φτιάχνουμε δηλαδή ένα δείκτη που δείχνει σε δεδομενα τυπου Node, και μετα δημιουργούμε, χωρίς να δώσουμε όνομα κτλ, μια instance του Node, η οποία είναι προσβάσιμη μόνο μέσω του δείκτη. Κάνω λάθος;

Δημοσ.

Ναι Indio αυτό που λες, αυτό κάνει η malloc. Δεσμεύει τόση μνήμη όσο το μέγεθος της μεταβλητής και σου επιστρέφει τον pointer.

Αυτό που ζητάς με μεταβλητή δέσμευση μνήμης ανάλογα με το μήκος του name είναι αυτό που έγραψα εγώ πιο πάνω. Δηλαδή κάνω δύο malloc, ένα για τον node και ένα για το name. Το strlen(name)+1 που έχω βάλει είναι το μέγεθος σε bytes που πιάνει το string. Σε αυτήν την περίπτωση όταν καταστρέφεις την λίστα πρέπει να κάνεις δύο free, δηλαδή πριν κάνεις free τον node κάνε free το name. Κανόνας είναι σε κάθε malloc να αντιστοιχεί και από ένα free......

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

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

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