Thread: wats the fault...

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    73

    wats the fault...

    guys this my code of a singly linked sorted list.....
    this means whenever you enter a new node the node is automatically inserted into the list and sorted...

    this code has two problems
    1) whenever the user enter an alphabet instead of number the output echoes invalid choice infinite times... why???
    i know that the problem is with scanf but how to get rid of it......

    2) is my code portable(except for scanf)....???
    or do i need to make any changes so that it is portable to the max extent....


    Code:
    #include<stdio.h>
    #include<conio.h>
    struct list
    {
    	int num;
    	struct list *nxt;  /*pointing to next node*/
    };
    void ins_nd(void);
    void del_nd(void);
    void print_list(void);
    typedef struct list node;
    node *head=NULL;  /*pointing to the head of the list */
    int main()
    {
    	int choice;
    	clrscr();
    	do           /*to recursively take inputs*/
    	{
    		printf("\n1.ins\n2.del\n3.print\n4.exit\nenter choice:");
    		scanf("%d",&choice);
    		switch(choice)
    		{
    			case 1:  ins_nd();break;
    			case 2:  del_nd();break;
    			case 3:	 print_list();break;
    			case 4:  exit(1);break;
    			default: printf("invalid choice");
    		}
    	}
    	while(choice!=4); /*to exit program*/
    	return 0;
    }
    void ins_nd(void)
    {
    	node *nu,*temp,*prev;int success=0;
    	nu=(node*)malloc(sizeof(node)); /*new node created*/
    	printf("enter data:");scanf("%d",&nu->num);
    	if (head==NULL)   /*list is empty*/
    	{
    		nu->nxt=head;
    		head=nu;
    	}
    	else
    	{
    		temp=head;prev=head;
    		/*temp is a temporary pointer to a node*/
    		/*prev is pointer pointing to previous node where temp was before*/
    		while(temp!=NULL && success!=1)
    		{
    			if(nu->num<head->num)
    			/*if new number is the least in the list it goes before the head*/
    			{
    				nu->nxt=head;
    				head=nu;
    				success=1;
    			}
    			else
    			/*if new num is between  first and last then sort is done here*/
    			{
    				if(temp->num > nu->num)
    				{
    					nu->nxt=temp;
    					success=1;
    					prev->nxt=nu;
    				}
    				else
    				{
    					prev=temp;
    					temp=temp->nxt;
    				}
    			}
    		}
    		if(temp==NULL)  /*if new is max then at last of list*/
    		{
    			prev->nxt=nu;
    			nu->nxt=temp;
    		}
    	}
    }
    void del_nd(void)
    {
    	node *temp,*prev,*nu;int success=0,req_num;
    	printf("enter num to be deleted");scanf("%d",&req_num);
    	temp=head;prev=head;
    	if(head==NULL)
    	{
    		printf("list empty");
    	}
    	else
    	{
    		/*checks list till a delete or list end*/
    		while(head!=NULL && temp!=NULL)
    		{
    			do  /*delete recursing elements*/
    			{
    				if(head->num==req_num)/*first element*/
    				{
    					nu=head;
    					head=head->nxt;
    					free(nu);
    					success=1;
    				}
    				else
    				{
    					if(temp->num==req_num)
    					{
    						nu=temp;
    						temp=temp->nxt;
    						prev->nxt=temp;
    						free(nu);
    						success=1;
    					}
    					else
    					{
    						prev=temp;
    						temp=temp->nxt;
    					}
    				}
    				if(success!=0)
    					printf("element deleted\n");
    			}
    			while(temp->num==req_num);
    		}
    		if(success==0)
    			printf("element not found");
    	}
    }
    void print_list(void)
    {
    	node *temp;
    	temp=head;
    	if(head==NULL)
    		printf("list empty");
    	else
    		printf("list is:");
    	while(temp!=NULL)
    	{
    		 printf("%d\t",temp->num);
    		 temp=temp->nxt;
    	}
    }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    1. Well, the simple solution would be "don't use scanf", but assuming that's not really what you want to do, then you should do something like this:
    Code:
    void clear_input_buffer() 
    {
        int ch;
        while((ch = getc()) != '\n' && ch != EOF) ;
    }
    
    ...
    
    if (scanf("%d", &x) != 1)
        clear_input_buffer();

    2. Your code is not portable, because it uses "conio.h", which is not part of the standard. You are also calling malloc, free and exit without including the relevant header file (stdlib.h). The function scanf() is definitely portable, and the way you use it is fine. As far as I can see, only clrscr() is used.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    25
    do you use DEV C++ compiler?

  4. #4
    Registered User
    Join Date
    Dec 2007
    Posts
    25
    i have the same problem here

    Code:
    int main ( void )
    {
    	sudokuPtr sudoku_list;      // δείκτης στην αρχή της λίστας
    	sudokuPtr current_sudoku;   // δείκτης στο τρέχων sudoku
    
    	sudoku_list = NULL;         // αρχικοποιήσεις δεικτών
    	current_sudoku = NULL;
    
    	FILE *input, *output;      // δείκτες αρχείων εισόδου-εξόδου
    	char sudoku_open[ LEN ];   // εδώ αποθηκεύεται το όνομα του αρχείου εισόδου
    	char sudoku_save[ LEN ];   // εδώ αποθηκεύεται το όνομα του αρχείου εξόδου
    	int selection;             // εδώ αποθηκεύεται η επιλογή (απο το μενού) του παίκτη
    	int sudoku_id;             // εδω αποθηκεύεται το id  του επιλεγέντος (από τον παίκτη)sudoku
    
    	do
    	{
    		menu();
    		scanf( "%d", &selection );
    
    		switch( selection )
    		{
    			case 1:
    				printf ( "enter a file name\n" );
    				scanf ( "%s", sudoku_open );       // εισαγωγή ονόματος αρχείου εισόδου
    				printf ( "\n\n" );
    				input = fopen ( sudoku_open, "r" );
    
    				if ( input  == NULL )  // έλεγχος ανοίγματος αρχείου εισόδου
    				{
    					printf ( "cant open %s file\nexit programm\n\n", sudoku_open );
    					exit ( 1 );
    				}
    
    				if ( !read_puzzle ( &sudoku_list, &current_sudoku, input ) ) // έλεγχος διαβάσματος αρχείου εισόδου
    				{
    					printf( "cant read %s file\nfile close and exit programm\n\n", sudoku_open );
    					fclose ( input );
    					exit ( 1 );
    				}
    				printf( "%s is loaded\n\n", sudoku_open );
    				fclose ( input );                           // κλείσιμο αρχείου εισόδου
    				break;
    
    			case 2:
    				printf ( "select a sudoku\n(enter a valid id)\n" );
    				scanf ( "%d", &sudoku_id );     // επιλογή sudoku με βάση το id του.
    				printf ( "\n\n" );
    				search ( sudoku_list, &current_sudoku, sudoku_id );
    				break;
    
    			case 3:
    				display_puzzle ( current_sudoku );  //εμφάνιση τρέχοντος sudoku
    				break;
    
    			case 4:
    				play ( current_sudoku );   // παιχνίδι τρέχοντος sudoku
    				break;
    
    			case 5:
    				printf( "enter a file name to save\n" );
    				scanf( "%s", sudoku_save );           // εισαγωγή ονόματος αρχείου εξόδου
    				printf ( "\n\n" );
    				output = fopen ( sudoku_save, "w" );
    				if ( output == NULL )                // έλεγχος ανοίγματος αρχείου εξόδου
    				{
    					printf ( "cant open %s file,\nexit programm\n\n", sudoku_save );
    					system ( "pause" );
    					exit ( 1 );
    				}
    
    
    				// έλεγχος σφάλματος γραφής αρχείου, διακοπή προγράμματος
    				if ( !write_puzzle ( current_sudoku, output ) )
    				{
    					printf ( "cant write %s file,\nfile close and exit programm\n\n", sudoku_save );
    					fclose ( output );
    					system ( "pause" );
    					exit ( 1 );
    				}
    
    				// κλείσιμο αρχείου εξόδου
    				fclose ( output );
    				break;
    
    			case 6:
    
    				printf ( "\n" );
    				delete_sudoku ( &sudoku_list, &current_sudoku );  // διαγραφή τρέχοντος sudoku
    				break;
    
    			default:
    				if ( selection == 7 )
    					printf ( "thank you for playing, good bye!\n\n" );
    				else
    					printf ( "invalid choise\n\n" );
    				break;
    
    		}
    
    
    	}while ( selection != 7 );
    
    	delete_everythink ( &sudoku_list, &current_sudoku ); // διαγραφή ΟΛΟΚΛΗΡΗΣ της λίστας
    
    	system ( "pause" );
    	return 0;          // τέλος προγράμματος
    }

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Which problem do you mean is "the same"? Whether your code is portable, or the problem with scanf() "locking up" when you enter non-digits? The latter is a known problem and can be solved with the code I suggested above. Or if you want to call a function to read a "choice", you could do something like this:
    Code:
    int read_choice()
    {
        int choice;
        while (scanf("%d", &choice) != 1)
        {
                int ch;
                while((ch = getc()) != '\n' && ch != EOF) ;
        }
        return choice;
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Dec 2007
    Posts
    25
    Quote Originally Posted by matsp View Post
    Which problem do you mean is "the same"? Whether your code is portable, or the problem with scanf() "locking up" when you enter non-digits? The latter is a known problem and can be solved with the code I suggested above. Or if you want to call a function to read a "choice", you could do something like this:
    Code:
    int read_choice()
    {
        int choice;
        while (scanf("%d", &choice) != 1)
        {
                int ch;
                while((ch = getc()) != '\n' && ch != EOF) ;
        }
        return choice;
    }
    --
    Mats
    i' sorry for confusing you, this infinite loop is (was) my problem. My teacher also suggest to do this
    Code:
    do
    	{
    		menu();
    		scanf( "%d", &selection );
                    if (scanf( "%d", &selection )!= 1) selection =0;
    		switch( selection )
    but i dont know why the problem appears in first place

    ps. i' sorry ,my english are not so good

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Also:
    Code:
    			default:
    				if ( selection == 7 )
    					printf ( "thank you for playing, good bye!\n\n" );
    				else
    					printf ( "invalid choise\n\n" );
    				break;
    This is a bit "strange". Why not just have:

    Code:
    			case 7:
    				printf ( "thank you for playing, good bye!\n\n" );
    			        break;
    
    			default:
    			        printf ( "invalid choise\n\n" );
    				break;
    And note that the correct spelling is "choice", even tho' it's "choose".

    Also, perhaps if you want to use either 0 or 9 as exit, you don't have to "renumber" everything when you add another menu item.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, the original problem is that scanf() has pretty poor error management, and particularly s*cks at "handling bad input". Basically how scanf works is this:
    Code:
        switch(format)
        {
            ...
            case 'd':
               while(1) {
                   ch = getc();
                   if (isdigit(ch))
                       update_number(ch);
                   else {
                       ungetc(ch);
                       break;
                   }
                 }
                 break;
             ....
         }
    What that means is that if there is anything "non-digit" in the input, it will put it back to the input buffer. Next time you get a call to scanf to read a number, it will getc() the same non-digit, put it back there again, and exit.

    Checking the return value from scanf will help, but you still need to get rid of the offending "bad data" too.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    25
    the "menu" function looks like this
    Code:
    void menu ( void )
    {
    	printf( "please, enter your choise\n\n"
    			"1 to load a sudoku (from file)\n"
    			"2 to select a sudoku\n"
    			"3 to display selected sudoku\n"
    			"4 to play selected sudoku\n"
    			"5 to save selected sudoku to file\n"
    			"6 to delete selected sudoku\n"
    			"  ( selected sudoku will automaticly deleted )\n"
    			"7 to exit program\n\n?" );
    }
    so, i guess is "strange" the "if else" option. I' m learning C (first language) for 3 months, and i have more to learn (English also!). Thank you for instant reply

  10. #10
    Registered User
    Join Date
    Nov 2007
    Posts
    73
    ok MATSP thanxx for that... it works fine.... noww...

    and coming to the issue of portability i used conio.h for clrscr()... can u tell me to introduce clrscr() and yet have my code portable....
    sorry for malloc ... actually it works fine without stdlib.h .... but ill remember to include...
    anything else



    and FRACTAL i use TURBOC++

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by fractal View Post
    the "menu" function looks like this
    Code:
    void menu ( void )
    {
    	printf( "please, enter your choise\n\n"
    			"1 to load a sudoku (from file)\n"
    			"2 to select a sudoku\n"
    			"3 to display selected sudoku\n"
    			"4 to play selected sudoku\n"
    			"5 to save selected sudoku to file\n"
    			"6 to delete selected sudoku\n"
    			"  ( selected sudoku will automaticly deleted )\n"
    			"7 to exit program\n\n?" );
    }
    so, i guess is "strange" the "if else" option. I' m learning C (first language) for 3 months, and i have more to learn (English also!). Thank you for instant reply
    Yes, and what I'm trying to say is that if you choose 9 to exit, you can easily add a 7 and 8 option. If you use 0 to indicate exit, you can also use 9 as an option for other purposes.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by ElemenT.usha View Post
    ok MATSP thanxx for that... it works fine.... noww...

    and coming to the issue of portability i used conio.h for clrscr()... can u tell me to introduce clrscr() and yet have my code portable....
    sorry for malloc ... actually it works fine without stdlib.h .... but ill remember to include...
    anything else



    and FRACTAL i use TURBOC++
    Yes, not including the right header file is "ok" in some circumstances - it just makes it more likely to fail if you try to port to other systems.

    There is no way that you can do clear screen in a portable way - it's just not part of the specification for standard C. But I don't actually see why you have to do that for a program like yours. Just "don't clear the screen", and it will work just fine.

    Of course, Turbo C is so ancient that you probably should consider getting a slightly newer compiler.... One that at least supports the C89 standard, perhaps?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Dec 2007
    Posts
    25

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Just some small tips on your English: " ( selected sudoku will be automatically deleted )\n"
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  15. #15
    Registered User
    Join Date
    Nov 2007
    Posts
    73
    can you suggest me a good compiler ? >matsp

    by the way which one do you use???

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. weird seg fault
    By Vermelho in forum C Programming
    Replies: 3
    Last Post: 05-10-2008, 08:27 PM
  2. Segmentation fault
    By NoUse in forum C Programming
    Replies: 4
    Last Post: 03-26-2005, 03:29 PM
  3. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  4. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM
  5. segmentation fault and memory fault
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 04-02-2002, 11:09 PM