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

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

Δημοσ.

Γεια σας φίλοι του insomnia! :lol:

Έχω ένα θεματάκι με την εξής άσκηση στην C. Οταν λοιπόν επιλέγω το ( 4 ) εμφανίζει κάτι περίεργο. Αν π.χ έχω δώσει σαν είσοδο τα στοιχεία 3 βιβλίων, θα μου εμφανίσει απο 3ς φορές το ονομα συγγραφέα και το όνομα του τελευταίου βιβλίου, ωστόσο, τον αριθμο των αντίτυπων θα μου τον εμφανίσει κανονικά.

Επίσης έχω άλλο ένα θεματάκι με το 2ο ερώτημα. Έστω ότι δίνω τα στοιχεία για ένα βιβλιο. Εάν επιλέξω το (2) ότι όνομα βιβλιου και να το βάλω να ψάξει θα μου εμφανίσει οτι υπάρχει και ότι είναι αυτο που έχω βάλει. Να δώσω ένα παράδειγμα για να γίνω πιο κατανοητός. Έστω ότι δίνω για στοιχεια "coelho", "alchemist", 5. Μετά αν επιλέξω το 2 θα μου ζητήσει να του δώσω ένα όνομα βιβλιού και να μου εκτυπώσει τα στοιχεία του( συγγραφέας, αντίτυπα ) αν υπάρχει. Οποιοδήποτε όνομα βιβλίου και να του δώσω θα μου εμφανίσει(έστω ότι δίνω το "bla" )

O/h sigrafeas tou bla vivliou einai o/h coelho

Ta diathesima antitipa aftou tou vivliou einai 5

 

 

Να υλοιποιήσετε ένα πρόγραμμα που να διαχειρίζεται τα στοιχεία μιας βιβλιοθήκης που περιέχει ένα πλήθος βιβλίων που δεν είναι εκ των προτέρων προσδιορισμένος. Το πρόγραμμα θα πρέπει να παρέχει τις εξής δυνατότητες :

1. Ένθεση ενός καινούργιου βιβλίου στην βιβλιοθήκη.

2. Παρουσίαση στην οθόνη των στοιχείων ενός βιβλίου δοθέντος του τίτλου του.

3. Δανεισμός ενός βιβλίου δοθέντος του τίτλου του. Στη περίπτωση που δεν μπορεί να πραγματοποιηθεί δανεισμός θα πρέπει να υπάρχει πληροφορία αν αυτο συμβαίνει διότι το βιβλίο δεν υπάρχει ή γιατί δεν υπάρχουν διαθέσιμα αντίτυπα.

4. Παρουσίαση στην οθόνη όλων των βιβλίων της βιβλιοθήκης.

5. Εξοδος απο το πρόγραμμα

 

 

Να και ο κωδικάς μου :

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

typedef struct node
{
char *book_name;
char *author_name;
int copies;
struct node *next;
} Node;

void instructions( void );
void list_insert( Node **list, char *vivlio, char *sigrafeas, int copies );
void list_print( Node *list );
void borrow_book( Node *list, char *vivlio );
void book_data( Node *list, char * vivlio );
void list_destroy( Node *list );

int main( void )
{
char *sigrafeas = "", *vivlio = "";
int choice, copies;
Node *list = NULL;

sigrafeas = ( char * )malloc( 20 * sizeof( char ) );
vivlio = ( char * )malloc( 20 * sizeof( char ) );

instructions( );
printf( " ? : " );
scanf( "%d", &choice );

while ( choice != 5 )
{
	switch ( choice ) {

		case 1:
			printf( "Dialekse onoma siggrafea : " );
			fflush( stdin );
			gets( sigrafeas );
			printf( "Dialekse onoma vivliou : " );
			fflush( stdin );
			gets( vivlio );
			printf( "Dialekse arithmo antiypwn : " );
			scanf( "%d", &copies );
			list_insert( &list, vivlio, sigrafeas, copies );
			printf( "To vivlio eisixthei me epitixia stin vivliothiki\n" );
			break;

		case 2:
			printf( "Dialekse to vivlio pou thes na deis ta stoixeia tou : " );
			fflush( stdin );
			gets( vivlio );
			book_data( list, vivlio );
			break;

		case 3:
			printf( "Dialekse to vivlio pou thes na danisteis : " );
			fflush( stdin );
			gets( vivlio );
			borrow_book( list, vivlio );
			break;
		
		case 4:
			list_print( list );
			break;		
	}

	instructions( );
	printf( " ? : " );
	scanf( "%d", &choice );
}

// Αποδεσμευση μνημης
list_destroy( list );
}

void instructions( void )
{
printf( "========================\n" );
printf(  "Epelekse apo 1 - 5 : \n"
	" 1) Enthesi enos kainourgiou vivliou stin vivliothiki.\n"
	" 2) Parasousiasi enos vivlio dothentos tou titlou tou.\n"
	" 3) Daneismos enos vivliou.\n"
	" 4) Parousiasi stin othoni olon ton vivlio tis vivliothikis.\n"
	" 5) Eksodos apo to programa.\n"
	" ====================================\n" );
}

void list_insert( Node **list, char *vivlio, char *sigrafeas, int copies )
{
Node *newnode = calloc( 1, sizeof( Node ) );

if ( newnode == NULL )
{
	printf( "Ipirxe sfalma stin desmeusi tis mnimis. To programa tha kleisei. \n" );
	abort();
}

newnode->author_name = sigrafeas;
newnode->book_name = vivlio;
newnode->copies = copies;
newnode->next = ( * list );
( *list ) = newnode;
}

void list_print( Node *list )
{
while ( list != NULL )
{
	printf( "%s\n", list->author_name );
	printf( "%s\n", list->book_name );
	printf( "Iparxoun %d diathesi antytipa \n", list->copies );
	list = list->next;
}
}

void borrow_book( Node *list, char *vivlio )
{
if ( list == NULL )
{
	printf( "I lista einai adia. den periexei kanena vivlio.\n" );
	return;
}

if ( strcmp( vivlio, list->book_name ) == 0 )
{
	if ( list->copies > 0 )
	{
		printf( "Iparxei diathesimo antitipo. Sigxaritiria to danistikate\n" );
		list->copies--;
		printf( "%d\n", list->copies );
	}
	else
	{
		printf( "Den iparxoun diathesima antitipa tou vivliou pou zitises\n" );
	}
}
else
{
	printf( "To vivlio pou zitises den iparxei\n" );
}
} 

void book_data( Node *list, char *vivlio )
{
if ( list == NULL )
{
	return;
}

if ( strcmp( vivlio, list->book_name ) == 0 )
{
	printf( "O/h sigrafeas tou %s vivliou einai o/h %s\n", vivlio, list->author_name );
	printf( "Ta diathesi antitipa aftou tou vivliou einai %d\n", list->copies );
}
else
{
	printf( "To vivlio tou opoiou zitises ta stoixeia den iparxei stin vivliothiki mas. \n" );
}
}

void list_destroy( Node *list )
{
if ( list == NULL )
{
	return ;
}

Node *dummy = NULL;
while ( list != NULL )
{
	dummy = list->next;
	free( list );
	list = dummy;
}
}

 

 

Υ.Γ : θέλω να ευχαριστήσω τον migf1 για τις καταπληκτικές σημειώσεις του ;)

Δημοσ.

άλλαξε στην list_insert τον κώδικα σου με βάση αυτό

 

>
....
       newnode->author_name =( char * )malloc( 20 * sizeof( char ) );
       strcpy(newnode->author_name,sigrafeas);
       newnode->book_name=( char * )malloc( 20 * sizeof( char ) );
       strcpy(newnode->book_name , vivlio);
....

Δημοσ.

άλλαξε στην list_insert τον κώδικα σου με βάση αυτό

 

>
....
       newnode->author_name =( char * )malloc( 20 * sizeof( char ) );
       strcpy(newnode->author_name,sigrafeas);
       newnode->book_name=( char * )malloc( 20 * sizeof( char ) );
       strcpy(newnode->book_name , vivlio);
....

 

Ευχαριστώ για την βοήθεια. Τώρα μαζί με κάποιες άλλες διορθώσεις που έκανα το πρόγραμμα τρέχει μια χαρά! :-D

Να 'σαι καλά φίλε! :)

Δημοσ.

Ευχαριστώ για την βοήθεια. Τώρα μαζί με κάποιες άλλες διορθώσεις που έκανα το πρόγραμμα τρέχει μια χαρά! :-D

 

 

δηλαδή διορθωσες τον κώδικα σου έτσι ώστε

όταν έχεις π.χ. 3 βιβλία και χρησιμοποιήσεις την επιλογή 2 του προγράμματος σου

να σου βρίσκει π.χ το 1ο βιβλίο και όχι μόνο το τελευταίο?

Δημοσ.

δηλαδή διορθωσες τον κώδικα σου έτσι ώστε

όταν έχεις π.χ. 3 βιβλία και χρησιμοποιήσεις την επιλογή 2 του προγράμματος σου

να σου βρίσκει π.χ το 1ο βιβλίο και όχι μόνο το τελευταίο?

 

Ναι δεν είχα υλοποιήσει σωστά τις συναρτήσεις borrow_book kai book_data και έλεγχαν μονο το 1 βιβλίο στην λίστα( δηλαδή αυτό που μπήκε τελευταίο καθώς κάθε νέο βιβλίο το βάζω στην αρχή της λίστας ) και οχι όλη την λίστα :P

Δημοσ.

Υ.Γ : θέλω να ευχαριστήσω τον migf1 για τις καταπληκτικές σημειώσεις του ;)

Ευχαριστώ κι εγώ με τη σειρά μου για τα καλά λόγια, και χαίρομαι που σου φάνηκαν χρήσιμες :)

 

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

 

  • Από τα πιο σημαντικά είναι πως δεν απελευθερώνεις πουθενά τη μνήμη που δεσμεύεις για τα: siggrafeas και vivlio στην main(). Μη ξεχνάς πως για ΚΑΘΕ malloc()/calloc() ΠΡΕΠΕΙ να υπάρχει αντίστοιχο free(). Αυτό κανονικά πρέπει να το κάνεις μέσα στην list_destroy() ξεχωριστά για ΚΑΘΕ κόμβο της λίστας σου. Βασικά δεν υπάρχει λόγος να τα διαχειρίζεσαι κι αυτά δυναμικά, αφού από ότι βλέπω στον κώδικα πάντα τα δουλεύεις με μέγιστο μήκος 19+1 (=20). Οπότε για να γλιτώσεις τα έξτρα free() όρισέ τα εξαρχής στατικά με μέγιστο μήκος 19+1. Έτσι όπως το έχεις τώρα το πρόγραμμά σου έχει memory leaks.
    __
  • Εξακολουθείς να χρησιμοποιείς την άκρως επικίνδυνη: gets() η οποία όπως έχουμε ξαναπεί έχει καταργηθεί και υπάρχει απλά και μόνο για συμβατότητα παμπάλαιου κώδικα. Στη θέση της μπορείς (συνιστάται και πρέπει) να χρησιμοποιείς την fgets() συνδυασμένη είτε με την sscanf() είτε με κάποια από τις ato*() συναρτήσεις της <stdlib> για μεταβλητές που δεν είναι strings. Με αυτό τον τρόπο αφενός αποκτάς έλεγχο στο μέγιστο μήκος που διαβάζεις κι αφετέρου καταπολεμάς και το πρόβλημα των "σκουπιδιών" στο buffer της κύριας εισόδου. Η fflush(stdin) που χρησιμοποιείς λειτουργεί μόνο σε Windows. Tο πρότυπο της γλώσσας ορίζει ως απροσδιόριστη τη συμπεριφορά της fflush() για input streams

Στον παρακάτω κώδικα καταπολεμώ τα 2 αυτά προβλήματα και υλοποιώ καλύτερο error-cheeking συγκριτικά με τον δικό σου κώδικα. Δεν ξέρω σε τι επίπεδο βρίσκεστε στη σχολή, ίσως σου φανεί πολύπλοκος. Είναι πιο δομημένος, ανεπτυγμένος (μερικώς) σε αφηρημένα επίπεδα (abstract layers) Οι συναρτήσεις list_*() αποτελούν το χαμηλότερο επίπεδο και οι do_*() το αμέσως επόμενο.

 

ΟΙ συναρτήσεις prompt_for_*() εξαλείφουν τα προβλήματα με τα σκουπίδια της κύριας εισόδου και αποτρέπουν πιθανό buffer-overflow στο διάβασμα των strings.

 

 

 

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

#define SPITERROR( text )	\
fprintf(stderr, "\n*** ERROR in %s(): %s\n\n", __func__, text )

/* Ορισμός σταθερών --------------------------------------- */
#define MAXSTRSIZE	(19+1)
#define MAXINPUT	(1023+1)

/* Ορισμός Πρόσθετων Τύπων -------------------------------- */
typedef enum { FALSE=0, TRUE=1 } Bool;
typedef struct node
{
   	char book_name[ MAXSTRSIZE ];
   	char author_name[ MAXSTRSIZE ];
   	int copies;
   	struct node *next;
} Node;

/* Πρότυπα συναρτήσεων ----------------------------------- */
int 	menu_choice( void );

Bool 	prompt_for_string( const char *prompt, char *string );
Bool	prompt_for_int   ( const char *prompt, int *integer );

void 	do_insert_book ( Node **list );
void 	do_search_book ( Node *list );
void 	do_borrow_book ( Node **list );
void 	do_print_all   ( Node *list );

Bool 	book_print( const Node *booknode );

Bool 	list_insert   	( Node **list, const Node *data );
void 	list_print    	( Node *list );
Node 	*list_lookup_title( Node *list, const char *title );
void 	list_destroy  	( Node *list );

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
int main( void )
{
int 	choice = 5;
Node 	*list = NULL;

for (;						/* infinite loop 		*/
{
	choice = menu_choice( );

	if ( choice == 5 )
		break;					/* break out of the loop */

	if ( choice == 1 )
		do_insert_book( &list );

	else if ( choice == 2 )
		do_search_book( list );

	else if ( choice == 3 )
		do_borrow_book( &list );

	else if ( choice == 4 )
		do_print_all( list );
}

list_destroy( list );
exit( EXIT_SUCCESS );
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
int menu_choice( void )
{
int retval = 5;

   	printf( "\n ====================================\n" );
   	printf( " ΠΡΟΓΡΑΜΜΑ ΒΙΒΛΙΟΘΗΚΗΣ \n\n"
           	" 1) Εισαγωγή  βιβλίου\n"
           	" 2) Αναζήτηση βιβλίου (βάση τίτλου)\n"
           	" 3) Δανεισμός βιβλίου\n"
           	" 4) Παρουσίαση όλων\n"
           	" 5) ΕΞΟΔΟΣ\n"
           	" ====================================\n"
);

prompt_for_int( " ? : ", &retval );

return retval;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
Bool prompt_for_string( const char *prompt, char *string )
{
if ( !string ) {
	SPITERROR("string is undefined!");
	return FALSE;
}

if ( prompt )
	printf("%s", prompt);

fgets( string, MAXSTRSIZE, stdin );
string[ strlen(string)-1 ] = '\0';		/* afairesh toy '\n' */

return TRUE;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
Bool prompt_for_int( const char *prompt, int *integer )
{
char input[ MAXINPUT ] = {'\0'};
if ( !integer ) {
	SPITERROR( "integer is undefined!" );
	return FALSE;
}

if ( prompt )
	printf("%s", prompt);

fgets( input, MAXINPUT, stdin );
*integer = atoi( input );

return TRUE;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
void do_insert_book( Node **list )
{
Node temp = { {'\0'}, {'\0'}, 0, NULL };

if ( !list ) {
	SPITERROR( "list is undefined!" );
	return;
}

puts("\nΕισαγωγή Βιβλίου ------------------\n");
prompt_for_string( "\tτίτλος 	: ", temp.book_name );
prompt_for_string( "\tσυγγραφέας : ", temp.author_name );
prompt_for_int( "\tαντίτυπα	: ", &temp.copies );

if ( !list_insert( list, &temp ) ) {
	puts("\n--- εσωτερικό πρόβλημα, η εισαγωγή ακυρώθηκε ---\n");
	return;
}

puts("\n--- το βιβλίο εισήχθει επιτυχώς ---\n" );

return;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
void do_search_book( Node *list )
{
char title[ MAXSTRSIZE ] = {'\0'};
Node *booknode = NULL;

if ( !list ) {
	puts("\n--- η βιβλιοθήκη είναι κενή ---\n" );
	return;
}

puts("\nΑναζήτηση Βιβλίου ----------------------");
prompt_for_string( "τίτλος: ", title );
putchar('\n');

booknode = list_lookup_title(list, title);
if ( booknode == NULL )
	puts("\n--- το βιβλίο δεν βρέθηκε στη βιβλιοθήκη ---\n");
else {
	book_print( booknode );
	puts("\n----- το βιβλίο βρέθηκε στη βιβλιοθήκη -----\n" );
}

return;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
void do_borrow_book( Node **list )
{
char title[ MAXSTRSIZE ] = {'\0'};
Node *booknode = NULL;

if ( !(*list) ) {
	puts("\n--- η βιβλιοθήκη είναι κενή ---\n" );
	return;
}

puts("\nΔανεισμός Βιβλίου ------------------------------------");
prompt_for_string( "τίτλος: ", title );
putchar('\n');

/* τοποθέτηση του booknode στον κόμβο που περιέχει το βιβλίο */
booknode = list_lookup_title(*list, title);
if ( booknode == NULL ) {
	puts("\n--- το βιβλίο δεν βρέθηκε στη βιβλιοθήκη ---\n");
	return;
}

/* ο booknode βρέθηκε, υπάρχουν όμως διαθέσιμα αντίτυπα? */
if ( booknode->copies < 1 ) {
	printf( "--- δεν υπάρχουν διαθέσιμα αντίτυπα αυτή τη στιγμή ---\n" );
}
else {
	(booknode->copies)--;
	printf( "-- επιτυχής δανεισμός, απομένουν: %d αντίτυπα ---\n",
		booknode->copies );
}

return;
} 

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
void do_print_all( Node *list )
{
int i = 0;

if ( !list ) {
	puts("\n--- η βιβλιοθήκη είναι κενή ---\n" );
	return;
}

puts("\nΠαρουσίαση Ολων των Βιβλίων ----------------------");
   	while ( list != NULL )
   	{
	printf("\nΒιβλίο #%d\n", ++i);
	book_print( list );
           	list = list->next;
   	}

return;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
Bool book_print( const Node *booknode )
{
if ( booknode == NULL ) {
	SPITERROR( "booknode is undefined!" );
	return FALSE;
}

printf( "\tΤίτλος	: %s\n", booknode->book_name );
printf( "\tΣυγγραφέας: %s\n", booknode->author_name );
printf( "\tΑντίτυπα  : %d\n", booknode->copies );

return TRUE;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
Bool list_insert( Node **list, const Node *data )
{
/* δημιουργία νέου κόμβου στη μνήμη */
Node *newnode = calloc( 1, sizeof( Node ) );
if ( newnode == NULL )
	return FALSE;

/* αντιγραφή των στοιχείων του ορίσματος-κόμβου data στον νέο κόμβο */
strncpy( newnode->author_name, data->author_name, MAXSTRSIZE-1 );
strncpy( newnode->book_name, data->book_name, MAXSTRSIZE-1 );
newnode->copies = data->copies;

/* τοποθέτηση του νέου κόμβου στην αρχή της λίστας */
newnode->next = ( *list );
( *list ) = newnode;

return TRUE;
}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
Node *list_lookup_title( Node *list, const char *title )
{
if ( !title ) {
	SPITERROR( "title is undefined!" );
	return NULL;
}

while ( list != NULL && strcmp( title, list->book_name ) != 0 )
	list = list->next;

return list;

}

/* ------------------------------------------------------
*
* ------------------------------------------------------
*/
void list_destroy( Node *list )
{
   	Node *dummy = NULL;

   	while ( list != NULL )
   	{
           	dummy = list->next;
           	free( list );
           	list = dummy;
   	}

return;
}

 

 

 

EDIT: Στην do_insert_book() καλό είναι να μπει κι ένας έλεγχος να μην επιτρέπει ορισμό αντίτυπων μικρότερο του 1 (κι ακόμα καλύτερα να να ψάχνει να δει αν υπάρχει ήδη το βιβλίο στη λίστα κι αν υπάρχει να του αυξάνει το copies, αλλιώς να ζητάει πλήθος αντιτύπων από την κύρια είσοδο ;) )

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

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...