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

Συνάρτηση που επιστρέφει τη θέση του στοιχείου ενός πίνακα


lektikos

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

λεκτικος ο κωδικας που εδωσα ειναι προχειροδουλειά αλλα για την ασκηση που τον θες ειναι ενταξει. Δηλαδη αμα ο χρηστης δωσει παραπανω αριθμους υπάρχει θεμα με το προγραμμα παρολαυτα με το return 0 αν ο χρηστης δωσει ενα στοιχειο που δεν υπαρχει θα του εμφανισει οτι ο ταδε αριθμος ειναι στην θέση 0 ακριβως επειδη η συναρτηση επιστρέφει 0 σε καθε αλλη περιπτωση (αν δηλαδη ο αριθμος δεν υπάρχει) καλυτερα χρησιμοποιησε την exit(0) να τερματιζεις επιτοπου το προγραμμα και προσθεσε και το #include <stdlib.h>

 
#include<stdio.h>
#include<stdlib.h>
#define LEN 5
int arr_pos(int arr[LEN] , int elem);
 
int main(void)
{
   int arr[LEN]={0};
 
   int i=0 , elem;
 
   printf("Give the element: \n");  
   scanf("%d" , &elem);
 
   printf("Give 5 elements: ");
 
   for(; i<LEN; i++)
   scanf("%d" , &arr[i]);
 
   printf("Position of %d is %d " , elem , arr_pos(arr,elem) );
 
   return 0;
}
int arr_pos(int arr[LEN] , int elem)
{
 
    int i;
 
    for(i=0; i<LEN; i++)
        if( arr[i] == elem) return i;
 
    printf("There is no such element");
    exit(0);
 
}

FIXED.

Ευχαριστώ πολύ Star_Light, θα το αλλάξω σε exit(0), διότι πράγματι, τυπώνει το μήνυμα που είπες κι όταν δοθεί ένα στοιχείο που δεν υπάρχει μέσα στον πίνακα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 70
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοφιλείς Ημέρες

Συχνή συμμετοχή στο θέμα

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

Μπορεί απλά άν δεν βρίσκει το στοιχείο μέσα στον πίνακα να επιστρέφει -1 και να κάνει τον έλεγχο στην main όπου αν η τιμή που επιστρέφει η συνάρτηση είναι αρνητική να βγάζει κάποιο μήνυμα ενώ αν εχει βρει τη θέση να την τυπώνει...

 

Oταν έχεις ολοκληρωσει την αναζήτηση και δεν έχεις βρει τιποτα που ειναι το προβλημα? 

 
// inside main 
 
 if( arr_pos(arr,elem) > 0 )
   printf("Position of %d is %d " , elem , arr_pos(arr,elem) );
 
 else
     printf("There is no such element");
 
// inside arr_pos 
 
    for(i=0; i<LEN; i++)
        if( arr[i] == elem) return i;
 
    return -1;
 

H προταση του bird. Τεχνικα προκυπτει καποιο θεμα απο αυτο που προτεινω εγω? Καταλαβα πως το λες.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

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

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

  • Like 4
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θέλω να τυπώνει τη θέση του στοιχείου ως εξής:

π.χ. δίνω τις τιμές :5, 5, 6, 1, 2

 

και αν επιλέξω την 5, να εκτυπώνεται ότι βρέθηκε η τιμή 5 στην θέση [0] του πίνακα nums.

Βέβαια, το 5 εμφανίζεται 2 φόρες και καλό θα ήταν να εμφάνιζε και τη θέση [1], αλλά τέλοςπαντων ας τυπώνει την πρώτη θέση στην οποία συναντάμε τον αριθμό(εφόσον αυτός επαναλαμβάνεται).

 

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

 

Π.χ...

#define MAXELEMS	5

/*********************************************************//**
 * Lookup for elem in elems[] and if found, store its positions in posfound[].
 * Return false on error, true otherwise.
 ************************************************************/
bool lookup_element( int elem, int elems[MAXELEMS], bool posfound[MAXELEMS] )
{
	int i;
	if ( !elems || !posfound )
		return false;

	// reset posfound[]
	for (i=0; i < MAXELEMS; i++)
		posfound[i] = false;

	// update posfound[]
	for (i=0; i < MAXELEMS; i++)
		if ( INT_MAX != elem && elem == elems[i] )
			posfound[i] = true;
	return true;
}
Επίσης, για να αποφύγεις τα προβλήματα της scanf() με το line-buffering όταν διαβάζεις μεμονωμένους int, μπορείς να χρησιμοποιήσεις συνδυασμό fgets() με sscanf(), ενδεχομένως σε ξεχωριστή συνάρτηση...

#define MAXINPUT	(80+1)

/*********************************************************//**
 * Read an int from stdin, return INT_MAX on error
 ************************************************************/
int read_int( void )
{
	char input[MAXINPUT] = {'\0'};
	int ret = INT_MAX;

	if ( !fgets(input, MAXINPUT, stdin) )
		return INT_MAX;

	if ( '\n' == input[MAXINPUT-2] ) {
		input[MAXINPUT-2] = '\0';
	}
	// if more than MAXELEMS characters given on input, flush any extra from stdin
	else if ( '\0' != input[MAXINPUT-2] ) {
		int c = '\0';
		while ('\n' != (c=getchar()) && EOF != c )
			; /* void */
	}

	if ( 1 != sscanf(input, "%d", &ret) )
		return INT_MAX;

	return ret;
}
Η συγκεκριμένη υλοποίηση χρησιμοποιεί την τιμή INT_MAX (του limits.h) ως ένδειξη αποτυχίας, για αυτό και τη συγκεκριμένη τιμή την εξαιρώ και από τις έγκυρες τιμές του elem στην lookup_element() πιο πάνω.

 

Οπότε μπορείς τώρα να διαβάσεις ένα-ένα τα στοιχεία του elems από την κύρια είσοδο, χωρίς προβλήματα με το line-buffering, κάπως έτσι...

...
	// read MAXELEMS elements into elems[]
	for (i=0; i < MAXELEMS; i++) {
		do {
			printf( "Enter element #%d: ", i );
			fflush(stdout);
			elems[i] = read_int();
		} while ( INT_MAX == elems[i] );
	}
...
  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Να πω και εγω μερικα πράγματα συμπληρωματικά ως προς τους κώδικες που έδωσε ο migf1 κυριως πιο επεξηγηματικα γιατι ειμαι σχεδον σιγουρος οτι ο λεκτικος ειτε θα έχει καποιες αποριες ειτε δεν θα τους κοιτάξει. Ο λογος ειναι οτι ειναι πιο advanced programming αυτη η προσεγγιση οπως και να το κάνεις. Καταρχην στην lookup_element o migf1 χρησιμοποιεί οπως έγραψε και ο ιδιος εναν ακομη πινακα τον posfound[] στον οποίο αρχικά θέτει ολες τις τιμές του σε false ωστε μετα για κάθε αντιστοιχια στον original  elems[] να θέτει true στον posfound[] αυτη ειναι μια προσεγγιση που εχω δει και σε αλλους κωδικες και ουσιαστικα σου λεει οτι το στοιχειο υπάρχει ηδη. Εχω μια απορια ομως εδω για ποιο λογο να χρησιμοποιήσεις μια προσθετη ανακυκλωση και να μην βαλεις απευθειας ολες τις τιμες του πινακα αυτου σε 0 κατα την δηλωση του? 

 

Επισης κατι ακομα τον INT_MAX τον χρησιμοποιει και για την αποφυγη υπερχειλισης με αλλα λογια αν ο χρηστης δωσει εναν αριθμο πολυ μεγαλυτερο απο οτι μπορει να συγκρατησει ο τύπος int ενδεχεται να υπάρξει υπερχειλιση αυτο προσπαθει να αποφευχθει μεσα στον ελεγχο. 

 

Τωρα πέρα απο κάποιους προσθετους ελεγχους που έχει βαλει μεσα στην συνάρτηση read_int το ζουμι πιστευω οτι ειναι εδω :

 
if ( 1 != sscanf(input, "%d", &ret) )
        return INT_MAX;
 
return ret;
 

Αν δηλαδη η sscanf ΔΕΝ επιστρέψει την τιμή 1 τοτε επιστρεφεις αποτυχια (INT_MAX) και ουσιαστικα συνεχιζει το do ... while που εχει στην main. Φανταζομαι αυτο το κανει επειδη στην αρχικη scanf την απλη αμα δωσεις και χαρακτηρα εκει που περιμενει αριθμους θα γινει πανικός και το προγραμμα δεν θα δουλέψει σωστά οποτε δέχεται την εισοδο σαν ενα string και μετα μεσα απο αυτο το string "τραβάει" τιμές μεσω της sscanf και τις βάζεις εκει που υποδεικνυει το τριτο ορισμα στην προκειμενη θα τραβήξει μια τιμή και θα την βάλει στην μεταβλητή ret. Δεν μπορω να το ελεγξω ακριβως με εισοδους αυτη την στιγμη σε γενικές γραμμές παντως η προσεγγιση ειναι πχ αν έχω 2 ακεραιους αριθμούς και θελω να τους διαβάσω απο την κυρια εισοδο τοτε διαβάζω ολη την γραμμη πρωτα την αποθηκεύω στον πινακα χαρακτήρων και στην συνέχεια μεσα απο αυτο τον πινακα θα τραβηξω τις 2 τιμές και θα τις αποθηκεύσεω στις 2 μεταβλητές :

 
int x, y
 
sscanf(input , "%d%d" , &x , &y); /* Επιστρεφομενη τιμή το 
2 αν εγιναν επιτυχως οι 2 εκχωρήσεις.*/
 

Εννοειται πιο πριν έχω διαβάσει με την fgets η οποια εκτος απο τον '\0' θα κρατήσει και τον '\n' που ειναι ο ENTER για αυτο και ο migf1 πιο πάνω παιζει με -2.   :)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλημέρα,

 

...

Καταρχην στην lookup_element o migf1 χρησιμοποιεί οπως έγραψε και ο ιδιος εναν ακομη πινακα τον posfound[] στον οποίο αρχικά θέτει ολες τις τιμές του σε false ωστε μετα για κάθε αντιστοιχια στον original elems[] να θέτει true στον posfound[] αυτη ειναι μια προσεγγιση που εχω δει και σε αλλους κωδικες και ουσιαστικα σου λεει οτι το στοιχειο υπάρχει ηδη. Εχω μια απορια ομως εδω για ποιο λογο να χρησιμοποιήσεις μια προσθετη ανακυκλωση και να μην βαλεις απευθειας ολες τις τιμες του πινακα αυτου σε 0 κατα την δηλωση του?

Διότι αν για παράδειγμα καλέσουμε τη συνάρτηση μέσα σε ένα loop (ενδεχομένως επειδή θέλουμε να "ρωτήσουμε" για τις θέσεις περισσότερων του ενός στοιχείου) θέλουμε να γίνεται reset o posfound[] σε κάθε επανάληψη της λούπας. Αλλιώς θα περιέχει μέσα του true στις θέσεις που είχε βρεθεί το εκάστοτε προηγούμενο στοιχείο.

 

Η συνάρτηση είναι γραμμένη έτσι για να είναι re-usable.

 

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

 

...

Επισης κατι ακομα τον INT_MAX τον χρησιμοποιει και για την αποφυγη υπερχειλισης με αλλα λογια αν ο χρηστης δωσει εναν αριθμο πολυ μεγαλυτερο απο οτι μπορει να συγκρατησει ο τύπος int ενδεχεται να υπάρξει υπερχειλιση αυτο προσπαθει να αποφευχθει μεσα στον ελεγχο.

Όχι, όχι! Την περίπτωση που μας δώσουν ακέραια τιμή μεγαλύτερη από ότι μπορεί να συγκρατήσει ένας int την ελέγχει αυτόματα η sscanf(), η οποία θα μας επιστρέψει 0 (ή EOF αν υπάρχει πρόβλημα με το stdin stream).

 

Ο έλεγχος για την περίπτωση που μας δώσει ο χρήστης περισσότερα από MAXINPUT-1 χαρακτήρες στην κύρια είσοδο, γίνεται για να προβλεφθεί πρόβλημα με το line-buffering και να κάνουμε stdin flushing όταν χρειάζεται.

 

Αν επιχειρήσουν να μας κάνουν oveflow την κύρια είσοδο, η fgets() ΔΕΝ βάζει '\n' στο προτελευταίο στοιχείο του input[]. Για αυτό και ο έλεγχος για input[MAXINPUT-2] και το μετέπειτα stdin flushing αν χρειάζεται.

 

...

Εννοειται πιο πριν έχω διαβάσει με την fgets η οποια εκτος απο τον '\0' θα κρατήσει και τον '\n' που ειναι ο ENTER για αυτο και ο migf1 πιο πάνω παιζει με -2. :)

Είναι σημαντικό να θυμάσαι πως σε περίπτωση επιχειρούμενου overflow, η fgets() ΔΕΝ βάζει '\n' στο προτελευταίο στοιχείο του input[].

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

 

	if ( '\n' == input[MAXINPUT-2] ) {
		input[MAXINPUT-2] = '\0';
	}

 

nitpick αλλά για να αφαιρείται το newline δεν θα έπρεπε αντί για MAXINPUT-2 να γίνεται χρήση της strlen ώστε να αφαιρείται και όταν δοθεί μικρότερο string ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

nitpick αλλά για να αφαιρείται το newline δεν θα έπρεπε αντί για MAXINPUT-2 να γίνεται χρήση της strlen ώστε να αφαιρείται και όταν δοθεί μικρότερο string ?

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

Γιατί βάζουμε [MAXINPUT-2], επίσης η δήλωση char input[MAXINPUT] = {'\0'}; γιατί παίρνει όρισμα το μηδενικό χαρακτήρα?

 

// update posfound[]
    for (i=0; i < MAXELEMS; i++)
        if ( INT_MAX != elem && elem == elems[i] ) // το μέρος με έντονη γραφή τι έλεγχο κάνει?
            posfound[i] = true;
    return true;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ελέγχει αν το στοιχείο βρισκεται ήδη μεσα στον πίνακα elems αν βρισκεται ειναι ήδη true απο πριν οποτε δεν εκτελείται η posfound=true ξανά.

 

Η δηλωση θέτει ολα τα bit του string input σε 0. Το αρχικοποιεί. Το [MAXINPUT - 2 ] ΕΙΝΑΙ για να καλυφθουν οι 2 τελευταιες θέσεις με τους ENTER και τον '\0' αν καταλαβα καλα απλα ο '\n' δεν μπαινει σε περιπτωση overflow. Για να ειμαι ειλικρινης αυτους τους ελεγχους χθες δεν τους διαβασα καλά.

 

Θα σου πω τι καταλαβαινω εγω εδώ :

 
if ( '\n' == input[MAXINPUT-2] ) {
        input[MAXINPUT-2] = '\0';
    }
 

Έστω οτι έχεις εναν πινακα τον αρχικο σου με 10 θέσεις μεσα και θες να του ζητησεις εισοδο απο τον χρήστη λοιπον αν ο χρηστης δώσει Helloo!! και πατήσει ENTER τοτε έχεις [0] = 'Η' , [1]='e' κ.ο.κ με [8]='\n' και [9]='\0'. Αν η θέση [8] λοιπον ειναι για το ENTER τοτε στην θέση εκεινη απλα βάζει τον null character ουσιαστικα το string δεν θα έχει μεσα τον χαρακτηρα αλλαγής γραμμής.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Γιατί βάζουμε [MAXINPUT-2], επίσης η δήλωση char input[MAXINPUT] = {'\0'}; γιατί παίρνει όρισμα το μηδενικό χαρακτήρα?

Η fgets() διαβάζει και το ENTER που πατάει χρήστης, εκτός αν η είσοδος περιέχει περισσότερους από MAXINPUT-1 χαρακτήρες (δες το link). Σε αυτή την τελευταία περίπτωση, ΔΕΝ βάζει ENTER στη θέση MAXINPUT-2, αφού ο χρήστης δεν το έχει πατήσει μέχρι τότε (το πατάει αργότερα, αφού έχει κάνει overflow τους MAXINPUT-1 χαρακτήρες).

 

Ανεξάρτητα από το ENTER στη θέση MAXINPUT-2, σε περίπτωση overflow βάζει στη θέση MAXINPUT-1 τον μηδενικό χαρακτήρα: '\0' (κόβει δηλαδή τους υπόλοιπους χαρακτήρες από το 1o της όρισμα, αλλά δεν τους αφαιρεί από την stdin... για αυτό τους κάνουμε εμείς flush χειροκίνητα, για να μην τροφοδοτήσουν το επόμενο διάβασμα που θα κάνουμε στην κύρια είσοδο).

 

Δες κι αυτό το πολύ ωραίο link για τα προβλήματα διαβάσματος της κύριας εισόδου: http://home.datacomm.ch/t_wolf/tw/c/getting_input.html. Καθώς και αυτό εδώ για το line-buffering: http://x-karagiannis.gr/prog/libs/content/misc/other/prompt_for/doc/html/index.html#LnBuf .

 

// update posfound[]

    for (i=0; i < MAXELEMS; i++)

        if ( INT_MAX != elem && elem == elems ) // το μέρος με έντονη γραφή τι έλεγχο κάνει?

            posfound = true;

    return true;

Αν σε μπερδεύει, τον έλεγχο για INT_MAX αγνόησε τον προσωρινά. Ο άλλος έλεγχος κοιτάει αν o χαρακτήρας elem ισούται με τον elems (με τον χαρακτήρα δηλαδή που υπάρχει στη θέση i του πίνακα elems[].

 

To && απλώς προσθέτει και 2ο έλεγχο (αυτόν για τον INT_MAX)... σημαίνει: ΚΑΙ ... δηλαδή, αν ισχύει αυτό ΚΑΙ αυτό.

 

Αν ήθελες Ή αντί για ΚΑΙ θα έβαζες: ||

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Υπάρχει περίπτωση, να χρειάζεται κάποια δήλωση #define ή κάτι άλλο?

Μου "χτυπάει" στη bool lookup_element( int elem, int elems[MAXELEMS], bool posfound[MAXELEMS] ) και βγάζει μήνυμα

error: expected '=', ',' , ' ; ', 'asm' or___'attribute___'  before 'lookup element'

 

Ευχαριστώ.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Λογικά δεν καταλαβαίνει τον "τύπο" bool. Ενσωμάτωσες το stdbool.h ?

Ευχαριστώ, αυτό έλειπε.

Κάτι άλλο τώρα, τη συνάρτηση lookup_element, πως την καλώ στη main? Εννοώ, τι ορίσματα πρέπει να έχει για να τρέξει?

Άν για παράδειγμα, δώσω 5 elements από το πληκτρολόγιο (π.χ. 5, 4, 2, 5, 1), δουλειά της είναι να μου βρει τις θέσεις των στοιχείων που πληκτρολόγησα. Ένα παράδειγμα κλήσης της στη main, πως θα μπορούσε να είναι?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα

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