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

[C] Eπιστροφή στο πρώτο βήμα αν υπάρξει εισαγωγή λάθος δεδομένων


WordUp

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

Δημοσ.

Έστω ότι έχουμε ένα πρόγραμμα το οποίο σου δίνει 3 επιλογές.

Αν κάποιος πληκτρολογήσει κάτι άκυρο, που δεν υπάρχει ως επιλογή, πώς μπορώ να ξαναφέρω τη ροή στην αρχή; Δοκίμασα με goto αλλά έφαγα κράξιμο για ευνόητους λόγους:-)

 

>printf("Diale3te\n"
         "1) A\n"
         "2) B\n"
         "3) C\n");
scanf("%d", &epilogi);

switch (epilogi)
{
         case 1: blablaaa; break;
         case 2: blablllaaa; break;
         case 3: blablaa; break;
         default: [b]Γύρνα πίσω στο μενού επιλογών[/b];
}

 

Ευχαριστώ προκαταβολικά.

Δημοσ.

int value=100;

 

while(value!=0){

printf("enter number:");

scanf("%d",&value);

switch(value)

..............

}

 

Αν ο χρήστης βάλει 0 τελειώνει το πρόγραμμα. Αν βάλει λάθος τιμή, του ζητείται να ξαναβάλει τιμή.

Δημοσ.

Κάνε κάτι σαν αυτό που λέει ο RubiksCube και απέφυγε την πρόταση του Blondeamon.

 

Πάντως νομίζω πως άμα κάποιος κράζει το goto πρέπει να φάει flame. Δεν είναι ότι προσπαθέις να μπείς στην μέση ενός loop... Αν και προφανώς πρέπει να ξέρεις να προγραματίζεις χωρίς αυτό.

Δημοσ.
Κάνε κάτι σαν αυτό που λέει ο RubiksCube και απέφυγε την πρόταση του Blondeamon.

 

Πάντως νομίζω πως άμα κάποιος κράζει το goto πρέπει να φάει flame. Δεν είναι ότι προσπαθέις να μπείς στην μέση ενός loop... Αν και προφανώς πρέπει να ξέρεις να προγραματίζεις χωρίς αυτό.

 

Moυ αρέσει που άνετα του λές να αποφύγει την πρόταση μου χωρίς ο ίδιος να δώσεις λύση και παραπέμποντας σε ένα παράδειγμα που είναι προφανώς λάθος. Είπε θέλει 3 περιπτώσεις όχι απλά διάφορο του μηδενός, αν δεν είναι Α,Β,Γ να κάνει κάτι άλλο.

 

Μια άλλη λύση είναι

 

int value=100;

 

while(value!=Α&value!=B&value!=Γ){

printf("enter number:");

scanf("%d",&value);

switch(value)

..............

}

Δημοσ.
Είπε θέλει 3 περιπτώσεις όχι απλά διάφορο του μηδενός, αν δεν είναι Α,Β,Γ να κάνει κάτι άλλο.

 

Είπε, αν βάλει κάτι άσχετο να ξαναπηγαίνει στην αρχη. Αυτό ακριβώς κάνει το while. To 0 είναι απλώς escape value για να μπορείς βγεις από το loop. Οι 3 περιπτώεις που λες εξυπηρετούνται από το switch μέσα στο while. Προφανώς δεν έκατσα να γράψω όλο το switch αλλά έβαλα ......(τελείες). Πού είναι το λάθος???

Δημοσ.

Ρε παιδιά το παλικάρι το είπε ρητά , να μπορείς να βάλεις ΜΟΝΟ τα Α,Β,Γ και οτιδήποτε άλλο βάλεις να σε ξαναζητάει είσοδο.

 

Εσυ του πρότεινες:

 

int value=100;

 

while(value!=0){

printf("enter number:");

scanf("%d",&value);

switch(value)

..............

}

Δηλαδή ακόμη και όταν βάζει Α,Β,Γ η while συνεχίζει να τρέχει κανονικά ζητώντας του συνέχεια εισόδους.

 

 

Η πρώτη μου λύση επιμένω οτι είναι και η πιο σωστή. Ορίστε και ένας πλήρως λειτουργικός κώδικας απλός και απέριττος.

 

 

>#include <iostream.h>
//δήλωση της συνάρτηση και ορισμός
int jesus()
{
int epilogi;
printf("Diale3te\n A) 1\nB) 2\nC) 3\n");
scanf("%d", &epilogi);

switch (epilogi)
{
         case 1: printf("lol"); break;
         case 2: printf("lol2"); break;
         case 3: printf("lol3"); break;
         default: jesus();
}
}//end jesus
//η main απλά καλεί την jesus
int main()
{
jesus();


system("pause");
}



}

Δημοσ.

Κάποιες παρατηρήσεις BD.

1)Δεν πρότεινα τη λύση του άλλου όπως ήταν.. είπα κάτι σαν.

2)η iostream.h είναι depreciated c++ lib

3)άμα ο χρήστης ξανακάνει λάθος στο πρόγραμμά σου τι γίνεται;

4)η main σου έχει type (int) αλλά δεν επιστρέφει κάτι

5)υπάρχει μια αδέσποτη αγκύλη

6)μόνο με /* */ ορίζουμε σχόλια στη C. το // είναι C++ comments

7)ο κώδικάς σου δεν είναι ούτε απλός, ούτε απέριττος

Αυτό εδώ κάνει compile (good) και δουλεύει (perfect). Με τη μόνο πρόβλημα το ότι ζητά char αντί για int.

>
#include <stdio.h>

int
main()
{
int i=1;
char a;

printf("Give a Character-> ");
while(i)
{
	scanf("%c",&a);
	switch(a)
	{
		case 'a': printf("hi\n"); i=0; break;			
		case 'b': printf("hib\n"); i=0; break;
		case 'c': printf("hic\n"); i=0; break;		
		case '\n': break;
		default:  printf("Give a, b or c-> ");break;
	}
}

return 0;
}


Δημοσ.

Η πρώτη μου λύση επιμένω οτι είναι και η πιο σωστή. Ορίστε και ένας πλήρως λειτουργικός κώδικας απλός και απέριττος.

 

Η λύση σου μετά από μερικές χιλιάδες επαναλήψεις (51.686 -αφορά την εκτέλεση σε Windows) οδηγεί σε υπερχείλιση στοίβας (stack overflow) οπότε καλύτερα να την ξεχάσεις. Το stack overflow μπορεί να παρουσιαστεί πιο σύντομα ή πιο αργά εξαρτωμένου του compiler στον οποίο εκτελείται (ρύθμιση χωρητικότητας stack) και του κώδικα που περιέχει (ρουτίνες με πολλές εντολές θα αποτύχουν συντομότερα). Ο λόγος που συμβαίνει αυτό είναι ότι η ρουτίνα δεν κάνει exit αλλά αντίθετα καλεί συνεχώς εκ νέου τον εαυτό της.

--

 

Καλή λύση (τυπική απέναντι στο γνωστό αυτό πρόβλημα) εκείνη του ippo00.

 

--

 

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

Δημοσ.

Παιδιά δουλεύει, αλλά αντί για char έβαλα int. Τώρα όμως, όταν πληκτρολογήσω κατά λάθος έναν char, δημιουργεί infinite loop.

 

>
short choose;
short k =1;
while(k)
   {
       scanf("%hd", &choose);

       switch (choose)
       {
           case 1:
               blabla;
               k--;
               break;

           case 2:
               fblabla;
               k--;
               break;

           case 3:
             jblabla;
               k--;
               break;

           case 4:
              jblablad;
               k--;
               break;

           default:
               printf("Eisagwgi 3ana\n");
               choose = 0;
               break;
       }
   }

:(

Δημοσ.

Στις cases, βάλε single quotes γύρω από την εκάστοτε «τιμή»:

 

>case '1':
...
case '2':
...
//κλπ

 

Επίσης, δε γνωρίζω κατά πόσο η switch δέχεται ως όρισμα short integers. Δε γλυτώνεις και κανένα σημαντικό ποσό μνήμης αν ορίσεις ως short δύο int variables (choose, k)...

Δημοσ.
Στις cases, βάλε single quotes γύρω από την εκάστοτε «τιμή»:

 

>case '1':
...
case '2':
...
//κλπ

 

Επίσης, δε γνωρίζω κατά πόσο η switch δέχεται ως όρισμα short integers. Δε γλυτώνεις και κανένα σημαντικό ποσό μνήμης αν ορίσεις ως short δύο int variables (choose, k)...

 

Τις δήλωσα ως int και έβαλα και quotes. Όλα καλά τώρα, με μόνη εξαίρεση αν πληκτρολογήσω έναν τέτοιο συνδυασμό "gvfdgdf" θα με πάει στο επόμενο βήμα.

Τέλος πάντων, θα ρωτήσω τον καθηγητή μου. Ευχαριστώ και πάλι.

Δημοσ.
Imo άμα είναι σε Windows ίσως καλύτερα να μην παίρνεις input me scanf.

 

Με ποιά συνάρτηση τότε αδερφέ;

Βοήθησέ μας, τους newbies:mrgreen:

Δημοσ.

Όλα καλά τώρα, με μόνη εξαίρεση αν πληκτρολογήσω έναν τέτοιο συνδυασμό "gvfdgdf" θα με πάει στο επόμενο βήμα.

Τέλος πάντων, θα ρωτήσω τον καθηγητή μου. Ευχαριστώ και πάλι.

 

Αυτό συμβαίνει διότι αν δώσεις για παράδειγμα “ab” αλλά αφού η scanf περιμένει ένα char και εσύ περνάς δυο τότε παρουσιάζεται scanf “overflow” και έτσι έχουμε αυτό το φαινόμενο. Για παράδειγμα μπορείς να δώσεις “ya” οπότε η scanf θα αποθηκεύσει το y, το πρόγραμμα θα δει ότι δεν αντιστοιχεί σε κάποια επιλογή και ύστερα επειδή το stdin (keyboard buffer) έχει έναν ακόμη χαρακτήρα (τον “a”) θα τον διαβάσει κατευθείαν η scanf και το πρόγραμμα θα συνεχίσει κανονικά με επιλογή “a”.

 

Ένα αδόκιμο κόλπο για να καθαρίζουμε το stdin είναι η χρήση της fflush. Προσοχή όμως όπως λέω, αυτό είναι ένα αδόκιμο τρικ διότι με βάση το ANSI-C πρότυπο η χρήση του fflush για τα stdio streams (stdin, stdout, stderr) δεν προβλέπεται όποτε είναι στην κρίση κάθε λειτουργικού συστήματος πως θα το ερμηνεύσει. Σε MS-DOS και MS-Windows το fflush (ή η ανάλογη Console API εντολή) καθαρίζει το keyboard input buffer (το stdin) αλλά σε άλλα λειτουργικά συστήματα αυτό δεν είναι δεδομένο.

 

>
[..]
		default:  printf("Give a, b or c-> ");break;
	}

	fflush(stdin); /* Παλίο DOS hack */
}

 

Δυστυχώς τέτοιου είδους προβλήματα προέρχονται από την χρήση των stdio C functions που δεν είναι σχεδιασμένες για «πολλά – πολλά» σε αυτούς τους τομείς (user interface) για αυτό σε πραγματικά προγράμματα χρησιμοποιούνται άλλες βιβλιοθήκες που βασίζονται σε άμεση πρόσβαση στο keyboard (για παράδειγμα η getch του conio.h που υπάρχει σε αρκετούς Windows compilers αλλά ΔΕΝ είναι ANSI-C οπότε δεν υπάρχει σε όλους ή σε άλλα λειτουργικά συστήματα κτλ.).

 

Συνεπώς αν θες μεγαλύτερο έλεγχο στο keyboard input από αυτών που προσφέρουν οι stdio.h functions θα πρέπει να βασισθείς σε ειδικές εντολές / βιβλιοθήκες του compiler σου & λειτουργικού σου συστήματος.

 

Υ.Γ.

Φυσικά υπάρχουν και άλλες λύσεις για να στηθεί αυτός ο βρόγχος, αλλά νομίζω ότι παρούσα λύση για τις ανάγκες σου (καμία άσκηση υποθέτω) είναι μάλλον αρκετή ;)

 

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

 

>
#include <stdio.h>

int
main()
{
int i=1;
char szInput[bUFSIZ]; /* BUFSIZ ένα stdio.h constant μεγάλου αριθμού για να χωρά τεράστια strings!! */

while(i)
{
	/* Παρουσίασε το prompt */
	printf("\nGive a Character-> ");
	/* Διάβασε μέχρι το μέγεθος του szInput array από το stdin */
	fgets(&szInput, sizeof(szInput), stdin);
	/* Το fgets προσθέτει πάντα ένα \n στο τέλος του string */
	if(strlen(szInput))
		/* Ας το αφαιρέσουμε */
		szInput[strlen(szInput) - 1] = '\0';
	/* Η απάντηση πρέπει να είναι 1 char μόνο */
	if(strlen(szInput) != 1)
	 {
		/* Λάθος! */
		printf("Give a, b or c-> ");
		/* Πάμε από την αρχή */
		continue;
	 }

	/* Έλεγχος szInput char */
	switch(szInput[0])
	{
		case 'a': printf("hi\n"); i = 0; break;
		case 'b': printf("hib\n"); i = 0; break;
		case 'c': printf("hic\n"); i = 0; break;
		case '\n': break;
		default:  printf("Give a, b or c-> ");break;
	}
}

return 0;
}

 

Αν ψάξεις σε παλαιότερα posts μπορείς να βρεις και άλλα, νομίζω ότι είχαμε ξανά ασχοληθεί κάποτε με ένα παρόμοιο ερώτημα..

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

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

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