migf1 Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 @migf1 Κοίτα, για να μην είμαστε "ελέω ύπαρξης mixed data types" θα μπορούσε η php να φρόντισει η strpos() να επιστρέφει (int) -1 όταν δεν βρίσκει το αναζητούμενο string και τιμές (int) >= 0 όταν βρίσκει αποτέλεσμα. Παντού int, εύκολο, απλό. Δυστυχώς έχει επικρατήσει οι συναρτήσεις που δεν έχουν επιτελέσει τον σκοπό τους να επιστρέφουν τιμές boolean (!!!). Δεν ξέρω γιατί αλλά εγώ το βρίσκω παράλογο. Δεν είναι καθόλου παράλογο, διότι 0 σημαίνει OFF και 1 σημαίνει ON, που με τη σειρά του σε κώδικα μηχανής "σβήνει" ή "ανάβει" ένα bit, το οποίο επίσης με τη σειρά του εκτελείται ΤΑΧΙΣΤΑ! [snip] ΜΗΝ ΤΟ ΔΙΑΒΑΣΕΙΣ ΑΥΤΟ -> Εγώ όμως θα επιμένω ότι επειδή οι τιμές που περιλαμβάνει (# define false 0 # define true 1) είναι αριθμητικές και με αυτές γίνονται όλες οι συγκρίσεις, ισότητες, πράξεις, κ.λπ., αυτές έχουν σημασία. [snip] Βασικά το γενικότερο abstract assumption είναι: > #define FALSE 0 #define TRUE !FALSE Με αυτό το assumption γλιτώνεις από ακόμα περισσότερους ενδεχόμενους "πονοκεφάλους" κι εκτελείται ακόμα πιο γρήγορα, αφού συγκρίνει μονάχα με το 0 (και όχι με το 0 ή με το 1).
defacer Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 @defacer Να υπενθυμίσω ότι ήδη έγραψα στο αρχικό post ότι καλό είναι να χρησιμοποιηθεί το if ($pos !== false), για να είναι όλοι ευτυχισμένοι. Το σχόλιο είναι από εδώ από κάποιον Symbol και πιστεύω ότι άν ήταν εντελώς λάθος αυτό που έγραψε θα τον είχαν κράξει εκεί που το έγραψε. Υποθέτεις ότι θα καθόταν κάποιος να ασχοληθεί μαζί του Μη ξεχνάς ότι εκεί δεν είναι forum. Επίσης, δες π.χ. λίγο παραπάνω το σχόλιο από τον "mobil dot boty at no dot spam..." ο οποίος δεν ξέρει τι του γίνεται (έχει μέχρι και typo FASE αντί για FALSE στον κώδικά του και κανείς δεν ασχολήθηκε μαζί του). Anyway, όπως σου είπα το 99% από τα σχόλια εκεί τα θεωρώ ανάξια σχολιασμού πολύ απλά γιατί το επίπεδο των συγγραφέων τους δεν έχει καμία σχέση με το δικό μου (sorry για το πως ακούγεται αυτό αλλά έτσι είναι τα πράγματα). Το άρθρο για την C λέει απλά ότι "αν φτιάχνεις με το χέρι boolean τύπο, όπως ο migf1, καλό είναι τον φτιάχνεις με unsigned char". Δεν έχω καμία αντίρρηση σ' αυτό -- θεωρώ ότι υπάρχει και καλύτερη προσέγγιση, αλλά η διαφορά θα φανεί ως επι το πλείστον μόνο αν αυτός που γράφει κώδικα χρησιμοποιώντας τον boolean τύπο κάνει πράγματα που καταδικάζω. Οπότε (με δεδομένο ότι δεν θα τα κάνει), και ο unsigned char είναι OK. Πάντως, μην κάνεις quote άρθρα αν δεν μπορείς να επιχειρηματολογήσεις και ο ίδιος σχετικά με τα υπέρ και τα κατά της κάθε προσέγγισης (γενική συμβουλή). "ο τύπος boolean είναι boolean", τυπικά ναι ώς τύπος μεταβλητής. ΜΗΝ ΤΟ ΔΙΑΒΑΣΕΙΣ ΑΥΤΟ -> Εγώ όμως θα επιμένω ότι επειδή οι τιμές που περιλαμβάνει (# define false 0 # define true 1) είναι αριθμητικές και με αυτές γίνονται όλες οι συγκρίσεις, ισότητες, πράξεις, κ.λπ., αυτές έχουν σημασία. Έχω και ένα κενό από προηγούμενο post σου. "Αυτό μπορείς να το δείς στη δεύτερη γραμμή αυτού του πίνακα, που λέει στην ουσία πως όταν σε έναν comparison operator ο ένας τελεστέος είναι boolean, τότε και ο άλλος μετατρέπεται σε boolean και γίνεται ordered comparison ανάμεσα σε booleans (!!!!) στην οποία ισχύει false < true." Αυτό το ordered comparision τι σημαίνει όταν ο boolean στην php είναι φτιαγμενος ώς εξής: #ifndef _STDBOOL_H #define _STDBOOL_H #if !defined(__BOOL_DEFINED) # define bool short /* The other macros must be usable in preprocessor directives. */ # define false 0 # define true 1 # define __bool_true_false_are_defined 1 # endif #endif /* _STDBOOL_H */ Προσπαθώ να σου εξηγήσω ότι σκέφτεσαι πώς μπορεί να ορίζεται ο boolean στην C, ενώ θα έπρεπε να σκέφτεσαι πώς ορίζεται ο boolean στην PHP. Αν λοιπόν κατεβάσεις το source, θα δεις (zend_types.h): >typedef unsigned char zend_bool; και όσον αφορά το ποιές τιμές του unsigned char αντιστοιχούν σε boolean true και false (zend_API.h): >#define RETVAL_FALSE ZVAL_BOOL(return_value, 0) #define RETVAL_TRUE ZVAL_BOOL(return_value, 1) (παραλείπω επιπλέον σχετικά macros από το zend_operators.h γιατί δεν αλλάζουν αυτό που ήδη κατάλαβες) Αυτά όμως δεν έχει καμία σημασία! Όταν γράφεις κώδικα σε PHP, είναι ξεκάθαρο από το... manual της γλώσσας ότι "υπάρχει κάτι που είναι boolean κι αυτό μόνο πρέπει να σε νοιάζει" (αυτό το zend_bool). Το γεγονός ότι αυτό το zend_bool που χρησιμοποιείς είναι unsigned char, και ότι οι τιμές του uchar είναι 0 = false και 1 = true δεν είναι δικιά σου δουλεία και (τελείως θεωρητικά) μπορεί να αλλάξει χωρίς προειδοποίηση. Αν καταλαβαίνεις την έννοια του abstraction δε χρειάζεται να επεκταθώ περισσότερο.
migf1 Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Γιατί συμφωνείτε και οι δυο πως είναι καλύτερα να δηλωθεί ως unsigned char ο πρόσθετος τύπος Boolean; Αντιτίθεται στο abstract assumption που ανέφερα παραπάνω.
defacer Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Γιατί συμφωνείτε και οι δυο πως είναι καλύτερα να δηλωθεί ως unsigned char ο πρόσθετος τύπος Boolean; Αντιτίθεται στο abstract assumption που ανέφερα παραπάνω. Τα #define που αναφέρεις παραπάνω νομίζω πως δεν είναι abstraction, είναι implementation. Επίσης θα τον όριζαν σαν signed int. Είναι καλύτερος ο signed int από τον unsigned char; Eν δυνάμει είναι καλύτερος στο ότι παίζει τα operations σε 32-bit values να εκτελούνται από τη CPU σε λιγότερα clocks απ' ότι αυτά σε 8-bit values, αλλά αν αυτό δεν είναι premature optimization δεν ξέρω και γω τι είναι. Επίσης, έχουμε ξεφύγει τελείως από την PHP και έχουμε περάσει στο "πώς να ορίσω έναν boolean type στη C"...
migf1 Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Μπερδευτήκαμε (και φταίω εγώ για αυτό). Δεν έχουμε ξεφύγει από το θέμα (ή τουλάχιστον έτσι πιστεύω) γιατί προσωπικά δεν αναφέρομαι ειδικά στη C. Ναι μεν χρησιμοποίησα C syntax για το abstract assumption πιο πάνω, αλλά το έκανα επειδή βαρέθηκα εκείνη τη στιγμή να γράψω λέξεις. Στο δια ταύτα, αυτό που ήθελα και θέλω να πω είναι πως σε όλες τις γλώσσες (αν όχι σε όλες, τουλάχιστον στη συντριπτική τους πλειοψηφία) είναι πάντα χρήσιμο να θεωρούμε ως γενική υπόθεση (abstract assumption) πως το λογικό ψεύδος (boolean false) ισοδυναμεί με 0 και πως η λογική αλήθεια (boolean true) ισοδυναμεί με οτιδήποτε ΔΕΝ είναι λογικό ψεύδος. Αν δεν έχουμε κάποιον ειδικό λόγο για implementation dependent κώδικα, η παραπάνω υπόθεση μας γλιτώνει από "πονοκεφάλους" όπως αυτός που περιγράφεται σε αυτό το νήμα, γιατί μεταξύ άλλων υπονοεί (implies) πως δεν μπορούμε να χρησιμοποιήσουμε σύγκριση μεγαλύτερου ή μικρότερου ανάμεσα σε δυο λογικές τιμές. ΥΓ. Σημείωση, ούτε το δικό μου παράδειγμα ( typedef enum {FALSE=0, TRUE} ) ακολουθεί το abstract assumption, αλλά αυτό εγώ το κάνω συνειδητά
defacer Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Στο δια ταύτα, αυτό που ήθελα και θέλω να πω είναι πως σε όλες τις γλώσσες (αν όχι σε όλες, τουλάχιστον στη συντριπτική τους πλειοψηφία) είναι πάντα χρήσιμο να θεωρούμε ως γενική υπόθεση (abstract assumption) πως το λογικό ψεύδος (boolean false) ισοδυναμεί με 0 και πως η λογική αλήθεια (boolean true) ισοδυναμεί με οτιδήποτε ΔΕΝ είναι λογικό ψεύδος. Αν δεν έχουμε κάποιον ειδικό λόγο για implementation dependent κώδικα, η παραπάνω υπόθεση μας γλιτώνει από "πονοκεφάλους" όπως αυτός που περιγράφεται σε αυτό το νήμα, γιατί μεταξύ άλλων υπονοεί (implies) πως δεν μπορούμε να χρησιμοποιήσουμε σύγκριση μεγαλύτερου ή μικρότερου ανάμεσα σε δυο λογικές τιμές. Έχω να κάνω μια διόρθωση στην πρώτη παράγραφο: το ότι το boolean false ισοδυναμεί με 0 δεν έχει να κάνει με την έννοια του boolean (μαθηματικά) αλλά με το ότι επειδή μας αρέσει και μπορούμε ορίζουμε συναρτήσεις (μαθηματικές) από το πεδίο του bool στο πεδίο των ακεραίων και το αντίθετο. Όμως η ύπαρξη αυτών των συναρτήσεων και ο ορισμός τους είναι ανεξάρτητος της abstract έννοιας του "bool". Το θέμα είναι ότι εδώ μπερδεύονται πολλές έννοιες: Αν το δεις μαθηματικά (που είναι ο Smirnov? ) κάλλιστα μπορείς να πεις ότι μια μεταβλητή boolean μπορεί να πάρει τιμές μέσα από το σύνολο { true, false } και επίσης μπορείς να ορίσεις total order μέσα στο σύνολο (true < false ή false < true, μαθηματικά είναι ό,τι θέλεις κάνεις). Αν το δεις προγραμματιστικά και γενικευμένα, το να ορίσεις ordering μέσα στο σύνολο δεν έχει πολύ νόημα και μπορεί να μπερδέψει. Επιπλέον, αν θέλεις να ταξινομήσεις boolean τιμές μπορείς εύκολα να το κάνεις με κώδικα χωρίς να χρειάζεται η έννοια του ordering να εμπεριέχεται στον τύπο boolean. Ας πούμε στη C# η έκφραση false < true δεν κάνει compile. Δυστυχώς πριν από τη C# υπήρχε η C και έτσι καθαρά και μόνο λόγω ενός implementation detail (ότι δηλαδή το bool είναι int στο παρασκήνιο -- και enum να το κάνεις, πάλι int είναι αλλά πιο καλά κρυμμένο) καταλήξαμε να είναι legal εκτρώματα όπως if(false < 15) κλπ κλπ. Και λέω εκτρώματα γιατί έτσι καταλήγουμε στη C (και στη C++) αυτό: >if (booleanVar) δεν είναι ισοδύναμο με αυτό: >if (booleanVar == TRUE) // ή τελος πάντων == 1 ή == true ή όπως αλλιώς το πεις και επομένως μπορείς να γράψεις (συνήθως επίτηδες, ομολογουμένως) διάφορα expressions τα οποία θα στείλουν ακόμα και έμπειρους προγραμματιστές αδιάβαστους στο debugging επειδή είτε δεν ικανοποιούν το abstract assumption που λες είτε το ικανοποιούν αλλά δείχνουν πως δέν το κάνουν. Παράδειγμα: >bool sneaky1 = TRUE; // και πάλι, πες το όπως θες bool sneaky2 = TRUE + 500; // legal δυστυχώς if(sneaky1 == sneaky2) { // WTF??? Αυτό το +500 τι έγινε? } if(sneaky1 && sneaky2 && sneaky1 != sneaky2) { // WTF??? Πώς είναι δυνατόν αυτά τα 2 "booleans" να μην είναι ίσα? } Ανάλογα με τον compiler και το implementation του bool, ένα από τα 2 WTF θα ισχύει. Συνοψίζοντας: Οι C, C++ μας έχουν μάθει όλους να σκεφτόμαστε ότι το abstract assumption που λες είναι "φυσικό" και πρέπει πάντα να ισχύει. Δεν πρέπει να ισχύει, δεν το βρίσκω φυσικό, και δεν υπάρχει τίποτα στη μαθηματική έννοια της λογικής τιμής που να δείχνει προς τα εκεί. Στη C# πήραν τη σωστή απόφαση να μην ορίσουν μετατροπές int <=> bool κι έτσι η γλώσσα δεν έχει αυτό το πρόβλημα. Η παραπάνω παράγραφος επίσης ισχύει αυτούσια αλλάζοντας "το abstract assumption που λες" με "το ordering false < true". Διαφορετικό "πρόβλημα", ίδια αιτία. Αυτό ακριβώς είναι που θέλουμε και οι 2 να πούμε στον At0m0 παραπάνω: πως αυτά που βλέπει στην πράξη είναι (ατυχείς) συνέπειες του τρόπου με τον οποίο υλοποιήθηκε ο bool στη C (και μετά μας πήρε η κατηφόρα), και όχι συνυφασμένα με την έννοια της λογικής τιμής.
migf1 Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Δεν είμαι σίγουρος ότι λέμε το ίδιο πράγμα φίλε defacer! Αυτό που λέω εγώ είναι πως όποιος τηρεί ως γενικό κανόνα ότι το TRUE δεν ισούται απαραίτητα με μια τιμή (1) αλλά ισούται με οποιαδήποτε τιμή ΔΕΝ είναι FALSE, τότε σπάνια (έως ποτέ) θα αντιμετωπίσει πρόβλημα όταν γράφει κώδικα, σε οποιαδήποτε γλώσσα! Προσθέτω τώρα, πως αν επιπλέον όλες του οι boolean συγκρίσεις γίνονται με το FALSE (και ποτέ με το TRUE) τότε η παραπάνω μου πρόταση ενισχύεται ακόμα περισσότερο σε: "τότε ποτέ δεν θα αντιμετωπίσει πρόβλημα ..." Π.χ. το... (θα χρησιμοποιήσω C-syntax, ok? ) > bool full = FALSE; if ( full ) ... ή if ( !full ) ... είναι αδύνατον να του δημιουργήσει πρόβλημα, οποτεδήποτε, οπουδήποτε και σε οποιαδήποτε γλώσσα χωρίς να τον ενδιαφέρει πως είναι υλοποιημένος ο τύπος boolean! Και για να το φέρω στην περίπτωση της strpos(), η νοοτροπία της boolean σύγκρισης πάντα με FALSE ... > $found = strpos($haystack , $needle); if ( $found === false ) echo "$needle was not found"; else echo "$needle was found at position $found"; // do whatever you want to do with $needle and $found δεν υπάρχει περίπτωση να του δημιουργήσει ποτέ (μα ποτέ) πρόβλημα, χωρίς να χρειάζεται καν να ξέρει λεπτομέρειες για το implementation του τύπου boolean. Χωρίς να είμαι σαΐνι στην PHP πιστεύω πως αυτός ακριβώς είναι ο λόγος που η strpos() δεν επιστρέφει ποτέ boolean TRUE, αλλά μόνο boolean FALSE. Τα υπόλοιπα παραδείγματα που δίνεις (προφανώς τα δίνεις ως παραδείγματα προς αποφυγή) δεν έχουν καμία θέση σε πράξεις και συγκρίσεις μεταξύ boolean μεταβλητών. Όποιος για παράδειγμα γράφει στον κωδικά του αυτό που έδωσες: >bool sneaky2 = TRUE + 500; // legal δυστυχώς legal, ξε-legal στην όποια γλώσσα δείχνει προγραμματιστή που είναι τελείως -αλλά τελείως- άσχετος με το τι σημαίνει boolean! Ομοίως κι όποιος γράφει... > boolean x = true, y = false; if ( x > y ) ... ή if (x < y ) ... κλπ Τα παραπάνω, προσωπικά τα κατατάσσω σε μια εκ των εξής 2 κατηγοριών: 1. άσχετοι 2. παπατζήδες ΥΓ. Δεν έχω πρόχειρα links, αλλά αν ψαχτεί κάποιος θα συναντήσει πολύ συχνά φράσεις όπως αυτή: "always validate booleans against false"
defacer Δημοσ. 22 Ιουλίου 2011 Δημοσ. 22 Ιουλίου 2011 Δεν είμαι σίγουρος ότι λέμε το ίδιο πράγμα φίλε defacer! Δεν είχα καταλάβει ακριβώς τι εννοούσες φίλε μου. Συμφωνώ πλήρως με την παραπάνω απάντησή σου.
At0m0 Δημοσ. 24 Ιουλίου 2011 Δημοσ. 24 Ιουλίου 2011 Αν και το έχουμε παρατραβήξει το θέμα για 2 διορθώσεις σε 10 γραμμές κώδικα, επειδή ... α) αυτός που άνοιξε το θέμα μάλλον δεν θα το διαβάσει ποτέ ξανά, β) δεν φαίνεται να ενοχλούμε και κανέναν άλλον, ... Δεν είναι καθόλου παράλογο, διότι 0 σημαίνει OFF και 1 σημαίνει ON, που με τη σειρά του σε κώδικα μηχανής "σβήνει" ή "ανάβει" ένα bit, το οποίο επίσης με τη σειρά του εκτελείται ΤΑΧΙΣΤΑ! Εχμ, αν και το πήγες πολύ μακρυά, δεν νομίζω ότι ισχύει αυτό που γράφεις. Αφού έφαγα λίγο καρπούζι, νομίζω ότι κατάλαβα γιατί έγραψες το παραπάνω. Εσύ έχεις στο μυαλό σου αυτό: "typedef enum { FALSE=0, TRUE} Bool;", ενώ εγώ έχω στο μυαλό μου αυτό: "typedef unsigned char zend_bool;" Στην δική μου περίπτωση ο κώδικας μηχανής δεν έχει περιθώρια επιλογής. Το γεγονός ότι αυτό το zend_bool που χρησιμοποιείς είναι unsigned char, και ότι οι τιμές του uchar είναι 0 = false και 1 = true δεν είναι δικιά σου δουλεία και (τελείως θεωρητικά) μπορεί να αλλάξει χωρίς προειδοποίηση. Εγώ αυτό το κομμάτι είχα πάντα στο μυαλό μου (unsigned min length type και 0,1). Κατά τα άλλα, όταν και άμα αλλάξει αυτό, σε οποιαδήποτε γλώσσα προγραμματισμού, εγώ θα είμαι 5 feet under και θα μετράω upside-down radishes. Παρόλα αυτά, εφόσον γίνει, εκεί που θα είμαι, θα αλλάξω πλευρό bool sneaky2 = TRUE + 500; // legal δυστυχώς Πώπω με έσιαξες !!! Τον ξανασκέφτηκα τον αρχικό κώδικα και μου φαίνεται ότι την επόμενη φορά που θα γράψω κάποιον κώδικα "για να βοηθήσω κάποιον", θα τον γράψω ώς: if (($pos + 0) > -1) και while ((int)$pos <> (int)'') , οπότε θα είμαι (δυστυχώς) εντελώς legal !!!, σωστά; lol
defacer Δημοσ. 25 Ιουλίου 2011 Δημοσ. 25 Ιουλίου 2011 Δε νομίζω ότι περιμένεις σοβαρή απάντηση στο παραπάνω, αλλά μια τελευταία δεν κάνει κακό. Για το αρχικό μας θέμα (strpos), νομίζω το γεγονός ότι δεν είχες καν διαβάσει τι ακριβώς επιστρέφει η συνάρτηση μιλάει από μόνο του. Η αναπαράσταση του bool στη μνήμη δεν πρόκειται να αλλάξει. Το θέμα δεν είναι αυτό, αλλά ότι μ' αυτή τη νοοτροπία θα συνεχίσεις να υποθέτεις το ίδιο και για πράγματα που όντως κάποια στιγμή θα αλλάξουν. Υπάρχουν άπειρα παραδείγματα εφαρμογών το έκαναν ενώ ποτέ κανείς δεν υποσχέθηκε ότι το εκάστοτε ΧΥΖ θα παραμείνει σταθερό, οπότε οι δικές σου δε θα είναι οι μόνες που θα χτυπήσουν tilt όταν γίνει κάτι τέτοιο. Νομίζω ότι μπορείς να γράψεις και πιο δυσνόητο κώδικα αν το θέλεις. Πάρε ιδέες από εδώ.
migf1 Δημοσ. 25 Ιουλίου 2011 Δημοσ. 25 Ιουλίου 2011 Φίλε At0m0, προσπαθούμε να σου εξηγήσουμε τα τι, πως και γιατί που διασφαλίζουν σε πολύ μεγάλο βαθμό πως ο κώδικάς σου θα είναι ευανάγνωστος, συμβατός και αποτελεσματικός, μέσα από την εμπειρία μας. Αν θες κράτα τα, αν δεν θες πέτα τα! Όσο για την ερώτηση του topic starter, ένας γενικός τρόπος να κάνεις αυτό που θέλεις είναι ο παρακάτω: > <?php $str = "insomnia1 kai insomnia2"; // όλο το string $needle = "insomnia"; // το substring που αναζητάμε $ntimes = 2; // επιθυμητή εμφάνιση του substring $offset = 0; // δες το εγχειρίδιο της strpos() $leneedle = strlen( $needle ); // το μήκος του substring που αναζητάμε // μέχρι να φτάσουμε στην επιθυμητή εμφάνιση && όσο υπάρχει substring στο string for ($i=0; $i < $ntimes && ($pos=strpos($str, $needle, $offset)) !== FALSE; $i++) $offset += ($pos + $leneedle); // !! ΕΧΕΙ BUG, ΒΛΕΠΕ 2 POSTS ΠΑΡΑΚΑΤΩ !!! if ( $pos === FALSE ) echo "$needle was not found<br />"; else echo "#$i: " . substr($str, $pos, $leneedle+1) . "<br />"; // Εναλλακτικός τρόπος για το if-else... // echo ($pos === FALSE) ? "$needle was not found<br />" : substr($str, $pos, $leneedle+1); ?> Αλλάζοντας τιμές στις 3 πρώτες μεταβλητές μπορείς να τον παραμετροποιήσεις κατά βούληση! Σημείωση: το +1 που έχω βάλει στο $leneedle στο τελευταίο echo είναι για να σου τυπώνει και τον χαρακτήρα που ακολουθεί μετά το substring που αναζητάς... αν θες να σου τυπώνει μονάχα το substring σβήσε το +1. EDIT: Προσθήκη σχολίων στον κώδικα
At0m0 Δημοσ. 26 Ιουλίου 2011 Δημοσ. 26 Ιουλίου 2011 > <?php $str = "insomnia1 kai insomnia2"; // όλο το string $needle = "insomnia"; // το substring που αναζητάμε $ntimes = 2; // επιθυμητή εμφάνιση του substring $offset = 0; // δες το εγχειρίδιο της strpos() $leneedle = strlen( $needle ); // το μήκος του substring που αναζητάμε // μέχρι να φτάσουμε στην επιθυμητή εμφάνιση && όσο υπάρχει substring στο string for ($i=0; $i < $ntimes && ($pos=strpos($str, $needle, $offset)) !== FALSE; $i++) $offset += ($pos + $leneedle); // offset στο τέλος της προηγ/νης εμφάνισης if ( $pos === FALSE ) echo "$needle was not found<br />"; else echo "#$i: " . substr($str, $pos, $leneedle+1) . "<br />"; // Εναλλακτικός τρόπος για το if-else... // echo ($pos === FALSE) ? "$needle was not found<br />" : substr($str, $pos, $leneedle+1); ?> Εχμ, για $ntimes = 3; βγάζει Warning. Warning: strpos() [function.strpos]: Offset not contained in string in /opt/lampp/htdocs/insomnia/testcode.php on line 10 line 10: -> for ($i=0; $i < $ntimes && ($pos=strpos($str, $needle, $offset)) !== FALSE; $i++)
migf1 Δημοσ. 26 Ιουλίου 2011 Δημοσ. 26 Ιουλίου 2011 Ναι, γιατί δεν ελέγχω για overflow του $offset. Εδώ διορθωμένο... > <?php $str = "insomnia1 kai insomnia2"; // όλο το string $needle = "insomnia"; // το substring που αναζητάμε $ntimes = 3; // επιθυμητή εμφάνιση του substring $leneedle = strlen( $needle ); // το μήκος του substring που αναζητάμε $lenstr = strlen( $str ); // το μήκος ολόκληρου του string $offset = 0; // δες το εγχειρίδιο της strpos() // μέχρι να φτάσουμε στην επιθυμητή εμφάνιση && όσο υπάρχει substring στο string for ($i=0; $i < $ntimes && ($pos=strpos($str, $needle, $offset)) !== FALSE; $i++) if ( ($offset += ($pos + $leneedle)) > $lenstr ) // calc new $offset $offset = $lenstr; // fix any overflow if ( $pos === FALSE ) echo "$needle was not found<br />"; else echo "#$i: " . substr($str, $pos, $leneedle) . "<br />"; // Εναλλακτικός τρόπος για το if-else... // echo ($pos === FALSE) ? "$needle was not found<br />" : substr($str, $pos, $leneedle+1); ?>
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.