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

next occurrence string (php)


Konsul

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

Δημοσ.

Γεια σας,

Θα ήθελα να ρωτήσω πως γίνεται το ακόλουθο: π.χ έχουμε ένα string $msg = " insomnia=1 kai insomnia=2 " ;

 

θέλω ας πούμε να εκτυπώσω την δευτερη φορά που βρίσκεται το ίδιο string, δηλαδή το insomnia=2. Δηλαδή πρέπει να φτάσει μέχρι τη δεύτερη φορά που βρίσκει το ίδιο string. Πώς γίνεται αυτό στην php ?

Δημοσ.

Δεν ξερω αν εχω καταλαβει σωστα αυτο που θες αλλα δοκιμασε αυτο.

 

>
<?php

$msg = " insomnia1 kai insomnia2 " ;
  echo strstr($msg, "insomnia2") ; 

?>

Δημοσ.

Ευχαριστώ για την απάντηση. Αλλά ψάχνω κάτι πιο σύνθετο., μάλλον δεν το διατύπωσα σωστά.

Με την strstr νομίζω βρίσκεις το 1ο occurrence. Aν ήταν το string $msg = " insomnia kai insomnia "; πώς γίνεται να πάει στο 2ο insomnia και όχι στο 1ο ?

Πιστεύω ότι θα χρειαστώ και την strpos και substr ή/και την explode απλά δεν ξέρω πως να κάνω την σύνταξη.

Δημοσ.

Ευχαριστώ για την απάντηση. Αλλά ψάχνω κάτι πιο σύνθετο., μάλλον δεν το διατύπωσα σωστά.

Με την strstr νομίζω βρίσκεις το 1ο occurrence. Aν ήταν το string $msg = " insomnia kai insomnia "; πώς γίνεται να πάει στο 2ο insomnia και όχι στο 1ο ?

Πιστεύω ότι θα χρειαστώ και την strpos και substr ή/και την explode απλά δεν ξέρω πως να κάνω την σύνταξη.

 

Το πώς θα κάνεις τη δουλειά εξαρτάται από το τι ακριβώς θέλεις να καταφέρεις. Τo string από μόνο του δεν "πάει" πουθενά, και όσον αφορά τον compiler το πρώτο "insomnia" είναι ακριβώς ίδιο με το δεύτερο. Περιέγραψέ μας λίγο περισσότερο το τι σκοπεύεις να κάνεις αφότου βρεις το index που θέλεις.

  • 2 εβδομάδες αργότερα...
Δημοσ.

>
<?php
$instr = 'insomnia is not the insomnia of the insomnia which is part of insomnia';
$findme = 'insomnia';
$find_times = 3;
$count=0;
$pos = 0;
$found = '';

do {
 $pos = strpos($instr, $findme, $pos);
 if ($pos > -1) {
   $count ++ ;
   $pos ++ ;
   if ($count == $find_times) {
     echo 'Break@' . $count . ' , left part is: "' . substr($instr,0, $pos-1) . '"<br />';
     echo 'Break@' . $count . ' , right part: "' . substr($instr,$pos -1) . '"<br />';
     $found = 'yupi';
     break ;  		  	
   }
 }
}
while ($pos <> '');

if (!$found) echo 'not found';

?>

 

Υ.Γ.

Εχμ, μπορώ να γράψω και χειρότερο κώδικα...

 

 

Προσθήκη

Με βάσει τις διορθώσεις του defacer οι οποίες είναι βασικές για να "βλέπεται" λίγο ο κώδικας...

>
Αλλάξτε τα 
($pos > -1) και ($pos <> '')
σε ($pos !== false)

Δημοσ.

@At0m0:

 

Ο κώδικάς σου έχει αρκετά σημεία που χρειάζονται διόρθωση (ας μη τα πω όλα bugs μιας και δεν επηρρεάζουν τη σωστή λειτουργία του όλα), αλλά θα περιοριστώ στο bug: η strpos επιστρέφει false όταν δε βρεθεί το string, όχι -1 ούτε οποιαδήποτε άλλη integer τιμή. Επομένως το check της επιστρεφόμενης τιμής μπορεί να γίνει μόνο έτσι:

 

>if ($pos !== false) ...

 

(ή αντίθετα, $pos === false)

Δημοσ.

Εχμ, μάλλον σε παρα-μπέρδεψα :)

Στο link που μου έστειλες γράφει, σωστά, ότι η strpos επιστρέφει INT !!

Και εγώ για INT την ελέγχω, (γκουχ, γκουχ, όπου μου αρέσει...) όχι για true/false.

Όσο αφορά τα true/false, άν χρειαζόταν κάπου...

Κανονικά (δλδ, άν ακολουθούσα πιστά τους κανόνες), ο ελεχγος για το true/false θα έπρεπε να γραφτεί έτσι όπως το γράφεις.

Ακανόνιστα (εχμ, like a hippie) τις τιμές true/false μπορείς να τις ελέγξεις και με άλλους τρόπους (πηγή).

 

Προσθήκη

Εχμ, διαβάζοντας λίγο πιο προσεκτικά, έχεις δίκιο, όταν ΔΕΝ έχει αποτέλεσμα η αναζήτηση επιστρέφει false

ΑΛΛΑ, λέει επίσης

"This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function."

 

Οπότε μια χαρά το έγραψα :)

 

Υ.Γ.

Εννοείται ότι ο κώδικας που έγραψα δεν είναι παράδειγμα προς μίμηση και προφανώς δεν είχα καμία πρόθεση να γράψω "τεχνικά σωστό" κώδικα.

Εξάλλου το έγραψα και στο πρώτο Υ.Γ. (και νόμιζα ότι θα ήταν σαφές)

Δημοσ.

Προσθήκη

Εχμ, διαβάζοντας λίγο πιο προσεκτικά, έχεις δίκιο, όταν ΔΕΝ έχει αποτέλεσμα η αναζήτηση επιστρέφει false

ΑΛΛΑ, λέει επίσης

"This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function."

 

Οπότε μια χαρά το έγραψα :)

 

Λοιπόν κοίτα να δεις τι έγινε... :)

 

Κατ' αρχήν όσον αφορά τα docs:

 

Αν το string που ψάχνεις υπάρχει, η strpos επιστρέφει έναν int ο οποίος μπορεί να είναι και 0 (αν το string που ζητάς είναι prefix του string που ερευνάται).

Αν το string που ψάχνεις δεν υπάρχει, η strpos επιστρέφει boolean false.

 

Οι εκφράσεις !strpos(), strpos() != 0, strpos() == false και άλλες παρόμοιες έχουν το ίδιο αποτέλεσμα όταν επιστραφεί 0 από την strpos όπως και όταν επιστραφεί false, όμως αυτές οι δύο περιπτώσεις έχουν τεράστια διαφορά γιατί στη μία το string δε βρέθηκε ενώ στην άλλη βρέθηκε. Αυτό σημαίνει ότι όπου τις δεις, αυτομάτως καταλαβαίνεις πως ο κώδικας έχει bug. Για το λόγο αυτό υπάρχει η προειδοποίηση ότι μπορεί να επιστραφεί false αλλά και 0, τα οποία μπερδεύονται αν δεν κάνεις τον έλεγχο με identical operator

>===

ή με το not identical

>!==

 

 

Η έκφραση strpos() > -1 που έγραψες εσύ φαίνεται απίστευτα ένοχη από μακριά, γιατί μπορεί να επιστραφεί false το οποίο αν γίνει cast σε int για τον operator > τότε θα κάνει eval to true, όπως επίσης θα γίνει αν επιστραφεί 0, οπότε θα έλεγε κανείς ότι έχουμε το παραπάνω ακριβώς bug. Παρόλα αυτά, το δοκίμασα σε κώδικα και διαπίστωσα ότι

 

>0 > -1   === true  // λογικό
'0' > -1 === true  // λογικό
'' > -1  === true  // λογικό

 

 

ΑΛΛΑ

 

>false > -1  === false  // Παρόλο που false == 0 !!!!!

 

 

Αυτό το τελευταίο είναι που κάνει τον κώδικά σου να δουλεύει σωστά, και πρέπει να ομολογήσω ότι αν και έχω φάει την PHP με το κουτάλι δέν το είχα υπόψη (ποιός θα γράψει false > -1;). Αν εσύ το ήξερες άξιος! :)

 

Τώρα, λάβε υπόψη ότι παρακάτω επίσης έχεις

>strpos() <> ''

το οποίο επίσης παραπέμπει σε απροσεξία γιατί σίγουρα η επιστρεφόμενη του strpos() δε θα είναι string, και εν πάσει περιπτώσει μπορείς απλά να γράψεις strpos() και να έχεις το ίδιο αποτέλεσμα...

 

Παρένθεση:

 

>0 <> -1   === true  // λογικό
'0' <> -1 === true  // λογικό
'' <> -1  === true  // λογικό

 

 

ΕΔΩ ΟΜΩΣ

 

>false <> -1  === true // Εδώ γίνεται αυτό που περιμένει κανείς, σε αντίθεση με πριν!

 

 

Οοοοοοοολα αυτά με είχαν κάνει να πιστέψω ότι έχεις bug, που τελικά δεν έχεις -- η σειρήνα συναγερμού όμως χτύπησε.

 

Το ηθικό δίδαγμα της ημέρας:

>false > -1  === false

αν έχεις το θεό σου!

Δημοσ.

Την PHP δεν την κατέχω. Βασικά δεν "κατέχω" καμία γλώσσα προγραμματισμού.

Επίσης - νομίζω είναι προφανές ότι - βαριέμαι αφάνταστα να διαβάζω - προσεκτικά τα - εγχειρίδια.

 

Αυτό το τελευταίο είναι που κάνει τον κώδικά σου να δουλεύει σωστά, και πρέπει να ομολογήσω ότι αν και έχω φάει την PHP με το κουτάλι δέν το είχα υπόψη (ποιός θα γράψει false > -1;). Αν εσύ το ήξερες άξιος! :)

(αστείο) Δοκίμασε και καμιά φορά να την φάς με το πιρούνι, θα βγάλεις λαγούς :)

(εδώ έσβησα κάτι τις που δεν ήταν σωστό)

 

Στο ($pos <> '') πάλι έκανα αυτό στο οποίο με οδήγησε η php.

Είχα κάτι "echo $pos" για ελέγχους τα οποία επέστρεφαν αβίαστα από ένα "" όταν δεν έβρισκε το search_string.

Οπότε έκανα τον έλεγχο με βάση ... τα δεδομένα (όχι με βάση το εγχειρίδιο).

Σημασία έχει το αποτέλεσμα, άμα δουλεύει μην το πειράζεις. lol

 

Υ.Γ.

Στον αρχικό κώδικα έβαλα μια υποσημείωση για το τι πρέπει να αλλάξει έτσι ώστε παρόλο που είναι "σωστό" να "δείχνει" και σωστό (χμ, κάτι μου θυμίζει αυτό...) :)

 

Προσθήκη.

Ξανακοιτώντας την κατάσταση με τα Boolean....

Αυτό το "false > -1 === false" μοιάζει τελικά σωστό καθώς.

>var_dump(0 > -1)) == true   //integers
ενώ
var_dump((bool) 0 > -1)) == false  // booleans
var_dump((bool) 0 > (bool) -1)) == false // booleans

και αυτό γιατί για την php ο τύπος boolean είναι unsigned οπότε αυτό το δυστυχισμένο το "-1" μετατρέπετε σε ... κάποιον θετικό "αριθμό" οπότε

γίνεται κάτι σαν var_dump((bool) 0 > (bool) 1)) == false

οπότε σωστό.

 

Σωστά;

Δημοσ.

Βασικά αυτό που ήθελα να πω πριν, αλλά χωρίς να παρεξηγηθώ, είναι ότι το πρόγραμμα ήταν σωστό "κατά λάθος". Εφόσον είσαι χομπίστας όλα καλά, απλώς επειδή στην PHP πολύ συχνά βλέπεις παρόμοια πράγματα ή ακούς παρόμοιες ατάκες από "επαγγελματίες" I can't help it και τρελλαίνομαι λίγο. :)

 

Όταν δε βρίσκει το search string η strpos είπαμε πως επιστρέφει false -- αν θέλεις να το διαπιστώσεις, κάνε var_dump($pos) αντί για echo. To echo δε σε βοηθάει να ξεχωρίσεις ανάμεσα στις τιμές false, '' και null όπως θα δεις.

 

Για τη σύγκριση ανάμεσα σε int και boolean, η εξήγησή σου δεν είναι σωστή (τέτοια πράγματα δεν τα υποθέτεις -- μόνο από το manual). Εξηγούμαι:

 

Ο τύπος boolean στην PHP δεν είναι ούτε unsigned ούτε signed, είναι απλά 1 bit (η PHP είναι γραμμένη σε C και δεν έχω δει πώς είναι implemented ο boolean της PHP στη C, αλλά δεν έχει σημασία γιατί στην PHP όπως είπα είναι απλά 1 bit).

 

Στις "περίεργες" συγκρίσεις, αυτό που συμβαίνει είναι ότι ο integer μετατρέπεται σε boolean και όχι το αντίθετο (όπως πχ συμβαίνει στη C και όπως είχα και γω στο μυαλό μου όταν διάβαζα τον κώδικά σου). Αυτό μπορείς να το δείς στη δεύτερη γραμμή αυτού του πίνακα, που λέει στην ουσία πως όταν σε έναν comparison operator ο ένας τελεστέος είναι boolean, τότε και ο άλλος μετατρέπεται σε boolean και γίνεται ordered comparison ανάμεσα σε booleans (!!!!) στην οποία ισχύει false < true.

 

Επομένως αυτό που γίνεται είναι

 

>
/* αρχικά έχουμε           */ false > -1
/* που ισοδυναμεί με       */ false > true // cast int to bool: 0 -> false, οτιδήποτε άλλο -> true
/* και επειδή false < true */ false  // τελικό αποτέλεσμα

Δημοσ.

Προτιμώ να είμαι χομπίστας παρά ένας από τους "επαγγελματίες" που περιγράφεις.

Την var_dump() την έβαλα στα USEFUL. Με αυτά που βλέπω δεν γίνεται δουλειά αλλιώς.

 

Την προσθήκη την έκανα επειδή όντως από τις δοκιμές που έκανα προέκυψε ότι η php μετέτρεπε τον int σε boolean και όχι το αντίθετο, όπως θα περίμενε ο πολύς ο κόσμος. (Είπαμε, εγώ δεν διαβάζω εγχειρίδια, τα βρίσκω όλα στην πράξη :) )

 

Γιατί είναι λάθος η εξήγησή μου;

Το ότι ο τύπος boolean είναι unsigned το έγραψα διότι με 1 bit, εχμ, δεν μπορούμε να έχουμε signed αριθμούς.

Aντί για "// cast int to bool: 0 -> false, οτιδήποτε άλλο -> true" έγραψα ότι το -1 μετατρέπεται σε "θετικό" αριθμό, με την έννοια ότι, με όποιον τρόπο και να γίνει η μετατροπή, το -1 θα πρέπει να γίνει είτε 0 ή 1 (εχμ, θετικοί unsigned αριθμοί) αφού εν τέλει αποθηκεύεται σε αυτό το 1 bit.

 

Βασικά την μετατροπή την έχω στο μυαλό μου όπως την περιγράφει με το παρακάτω σχόλιο του ένας χρήστης στο εγχειρίδιο της php.

Just a side note, doesn't really matters, the reason -1 is true and not false is because boolean type is treated as unsigned, so -1 would be for example, if it's unsigned int32 translate to hex: 0xFFFFFFFF and back to decimal: 4294967295 which is non-zero. there isn't really a "negative boolean". it's a binary thing. :o (since it used to be a bit and then there was only 0 and 1 as an option)

 

Όπως και να έχει..., σε κάθε τι μου μου φαίνεται γενικά λογικό θα πρέπει να ψάχνω το manual της php για να δώ μήπως έχουν σκεφτεί κάποια "λεβεντιά"; Δεν το νομίζω !!

Εγώ θα συνεχίσω γράφω κώδικα όπως μου αρέσει αρκεί να δουλεύει, ανεξάρτητα από το πώς και γιατί δουλεύει :)

 

Πάντως σε ευχαριστώ που μπήκες στο κόπο να κάνεις αυτές τις διορθώσεις/παρατηρήσεις γιατί αναγκάστηκα και να θυμηθώ διάφορα και να χρησιμοποιήσω νέα πράγματα.

 

Προσθήκη

Εχμ, νομίζω ότι η ιστορία με το "unsigned" είναι προπατοτική αμαρτία

"NOTE: There is NO Boolean type in C -- you should use char, int or (better) unsigned char. "

ή αυτός που το έγραψε δεν πήρε ποτέ πτυχίο (lol)

πηγή:Cardif School of Computer Science & Informatics

 

Προσθήκη 2

Εχμ, το παραπάνω με έβαλε σε σκέψεις.

Άν στην C η boolean στην καλύτερη περίπτωση είναι char (1 byte) στην php πως κατάφεραν και το έκαναν 1 bit. Μάλλον και στην php ο μικρότερος τύπος είναι 1 byte και όχι 1 bit.

Δημοσ.

Μια χαρά επιλογή είναι να είσαι χομπίστας. Απλά ήθελα να ξεκαθαρίσω ότι αυτά που λέω τα λέω γιατί συνήθως κρίνω άθελά μου από τη σκοπιά του επαγγελματία, οπότε καταλαβαίνεις ότι αν άκουγα κάποιον που ονομάζει τον εαυτό του έτσι να λέει π.χ. "εγώ δεν διαβάζω εγχειρίδια, τα βρίσκω όλα στην πράξη" θα τον πυροβολούσα για να μη χαλάει την πιάτσα. :)

 

Για τη λάθος εξήγηση: ο τύπος boolean είναι boolean. Δεν είναι ούτε signed ούτε unsigned, γιατί δεν είναι αριθμητικός τύπος. 1 bit είναι το μέγεθος της πληροφορίας που χωράει σε 1 boolean value. Το γεγονός ότι η υλοποίησή του μπορεί να γίνεται μέσω signed ή unsigned αριθμητικού τύπου ο οποίος πιθανότατα έχει 32 bits από τα οποία τα 31 πάνε χαμένα δεν έχει κανένα νόημα όταν μιλάμε σε επίπεδο κώδικα PHP. Για παράδειγμα, μπορεί οι σχεδιαστές της PHP να αποφάσιζαν ότι η bitwise αναπαράσταση του false θα είναι π.χ. 42 και αυτή του true -2406, signed integers και οι 2 -- δεν έχει καμία σημασία. Μη μπερδεύεις την υλοποίηση της PHP (που είναι γραμμένη σε C) με τον κώδικα που είναι γραμμένος σε PHP.

 

Τα σχόλια των χρηστών στο εγχειρίδιο της PHP (δε δίνεις link δυστυχώς) όποιος θέλει τα πιστεύει όσο θέλει. Εγώ προσωπικά όταν έχω απορία που δεν την καλύπτει το manual πάω και διαβάζω το source. Σε καμία περίπτωση δε θα εμπιστευόμουν έναν "random guy on the internet" ούτε να χρησιμοποιήσει τη σωστή τεχνικά ορολογία γι' αυτά που λέει σε ένα τέτοιο technical θέμα, πόσο μάλλον να περιμένω ότι αυτά που λέει έχουν και νόημα.

 

Φυσικά δεν έχω ούτε σκοπό ούτε μου πέφτει λόγος να σου πω πώς θα γράφεις κώδικα. Είπα κάποια πράγματα, αν σου αρέσουν και τα υιοθετήσεις έχει καλώς, αν όχι τότε πάλι έχει καλώς -- δε μου κάνει διαφορά.

 

Δεν κατάλαβα το τελευταίο που λες με το bool στην C -- η ποτέ δεν είχε boolean type. Απέκτησε έναν "bool" ως C99, αλλά όπως και στη C++ πρόκειται στην ουσία για integral type μικρού (θεωρητικά) μεγέθους. Το οποίο φυσικά είναι σχεδόν τελείως άχρηστο δεδομένου ότι με όλα τα implicit conversions που γίνονται σε C/C++ το μόνο που κερδίζεις είναι ότι γράφοντας "bool flag;" αντί για "int flag;" δίνεις λίγα παραπάνω δεδομένα σ' αυτόν που διαβάζει τον κώδικα.

Δημοσ.

Δεν διάβασα με μεγάλη προσοχή το νήμα, και παρόλο που δεν... φημίζομαι για τις γνώσεις μου στη php, ξέρω πως ελέω ύπαρξης mixed data types είναι πάντα καλό οι συγκρίσεις να γίνονται με τα type comparison operators ===, !==, κλπ (όπως υπέδειξε και ο φίλος defacer). Για τον ίδιο λόγο είναι πάντα καλό να διαβάζει κανείς το εγχειρίδιο όταν χρησιμοποιεί για 1η φορά συναρτήσεις που δεν έχει ξαναχρησιμοποιήσει, ώστε να βλέπει τις τιμές επιστροφής τους.

 

Όσο για τη C, για να μη μπλέκω με το κάθε compiler dependent implementation και να έχω το κεφάλι μου ήσυχο ορίζω πάντα δικό μου πρόσθετο τύπο για Boolean, ως enumerated type:

>
typedef enum { FALSE=0, TRUE} Bool;

 

Btw, ποτέ κώδικας δεν πρέπει να στηρίζεται σε σύγκριση μεγαλύτερου ή μικρότερου ανάμεσα σε δυο Boolean τιμές! Μονάχα ισότητα ή ανισότητα, τίποτε άλλο!

Δημοσ.

@migf1

Κοίτα, για να μην είμαστε "ελέω ύπαρξης mixed data types" θα μπορούσε η php να φρόντισει η strpos() να επιστρέφει (int) -1 όταν δεν βρίσκει το αναζητούμενο string και τιμές (int) >= 0 όταν βρίσκει αποτέλεσμα.

Παντού int, εύκολο, απλό.

Δυστυχώς έχει επικρατήσει οι συναρτήσεις που δεν έχουν επιτελέσει τον σκοπό τους να επιστρέφουν τιμές boolean (!!!). Δεν ξέρω γιατί αλλά εγώ το βρίσκω παράλογο.

 

@defacer

Να υπενθυμίσω ότι ήδη έγραψα στο αρχικό post ότι καλό είναι να χρησιμοποιηθεί το if ($pos !== false), για να είναι όλοι ευτυχισμένοι.

Το σχόλιο είναι από εδώ από κάποιον Symbol και πιστεύω ότι άν ήταν εντελώς λάθος αυτό που έγραψε θα τον είχαν κράξει εκεί που το έγραψε.

Το άρθρο για την C λέει απλά ότι "αν φτιάχνεις με το χέρι boolean τύπο, όπως ο migf1, καλό είναι τον φτιάχνεις με unsigned char".

"ο τύπος 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 */

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

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

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