migf1 Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 Θα μπορούσε κάποιος να επιβεβαιώσει/διαψεύσει αν η μέθοδος του τίτλου είναι σύγκριση bytes ή όχι; Επίσης είναι locale-aware ή όχι; Φτιάχνω στην LIBS ένα απλοποιημένο Java-like API, προσαρμοσμένο σε απλά c-strings (δηλαδή NUL terminated arrays of char, όπου char το στάνταρ ASCII value, κι όχι το 16bit Unicode char της Java) και τα 'χω πάρει ολίγον με τα locale και μη locale-aware methods της Java. Άλλα είναι documented, άλλα ( όπως η equals() ) δεν είναι... ή τουλάχιστον δεν βρίσκω εγώ την σχετική τεκμηρίωση. Δεν με βοηθάει ούτε ο πηγαίος της κώδικας (μάλλον επειδή δεν είμαι τόσο εξοικειωμένος με την Java)... 998 /** 999 * Compares this string to the specified object. The result is {@code 1000 * true} if and only if the argument is not {@code null} and is a {@code 1001 * String} object that represents the same sequence of characters as this 1002 * object. 1003 * 1004 * @param anObject 1005 * The object to compare this {@code String} against 1006 * 1007 * @return {@code true} if the given object represents a {@code String} 1008 * equivalent to this string, {@code false} otherwise 1009 * 1010 * @see #compareTo(String) 1011 * @see #equalsIgnoreCase(String) 1012 */ 1013 public boolean equals(Object anObject) { 1014 if (this == anObject) { 1015 return true; 1016 } 1017 if (anObject instanceof String) { 1018 String anotherString = (String)anObject; 1019 int n = count; 1020 if (n == anotherString.count) { 1021 char v1[] = value; 1022 char v2[] = anotherString.value; 1023 int i = offset; 1024 int j = anotherString.offset; 1025 while (n-- != 0) { 1026 if (v1[i++] != v2[j++]) 1027 return false; 1028 } 1029 return true; 1030 } 1031 } 1032 return false; 1033 } 1034 Και για να μην αλλάζω νήμα, αν θέλατε να φτιάξετε σε ANSI C μια συνάρτηση σύγκρισης 2 c-strings που δεν θα είναι locale-aware, και δεδομένου πως όλα τα C προγράμματα ξεκινάνε πάντα με ένα default locale (συνήθως "C") πως θα το κάνατε; Υπάρχει κάποιος άλλος τρόπος πλην του να φτιάξουμε δικιά μας απεικόνιση των char;
nilosgr Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 Απ τον κωδικα εγω βλεπω char-by-char συγρισεις, στη γραμμη 1026 δηλαδη. Με τον operator != στα primitive data types, συγκρινουμε bytes (νομιζω). Oποτε η απαντηση ειναι ναι (χωρις να ειμαι 100% σιγουρος)
migf1 Δημοσ. 30 Δεκεμβρίου 2012 Μέλος Δημοσ. 30 Δεκεμβρίου 2012 Το primitive char type στην Java δεν ορίζεται ως 16μπιτο Unicode16 entity? Διότι έτσι γνώριζα. EDIT: Αν είναι (που νομίζω είναι) τότε μας εγγυάται η equals() πως όντως είναι byte σύγκριση (απαλλαγμένη από endianess, surrogates, κλπ); Επίσης, με το locale γνωριζει κανείς τι παίζει για την συγκεκριμένη μέθοδο;
albNik Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 Ε ναι, αφού κάθε char έχει μια αριθμητική 16-bit τιμή 0 μέχρι ~65000 , αυτή συγκρίνει ανεξάρτητα από endianess και locale. http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Character.html#compareTo Compares two Character objects numerically
nilosgr Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 Για το locale δεν γινεται να το τσεκαρεις; πχ να συγκρινεις δυο strings (με equals) τα οποια εχουν ιδια αναπαρασταση αλλα διαφοριτικο locale (αν λεω λαλακια feel free να κραξετε)
defacer Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 String equality και locales απλά δε συνδέονται. Εφόσον μιλάμε για μια method equals (επιστρέφει true/false) και εφόσον το internal encoding στα strings της Java είναι συγκεκριμένο (δεν έχει σημασία ποιό είναι καν) δεν υπάρχει κανένας τρόπος με τον οποίο μια locale -- και συγκεκριμένα το collation -- θα μπορούσε να επηρρεάζει¹ το αποτέλεσμα της σύγκρισης. Αυτός είναι αρκετός λόγος για να μην υπάρχει πουθενά αναφορά στο τι γίνεται: does not apply. Αν μιλούσαμε για μια method compare (επιστρέφει int) τότε ναι, το collation μπαίνει στη συζήτηση. Update: ...και γι' αυτό το λόγο η String.compareTo αναφέρει σαφώς το τι είδους comparison κάνει. Update #2: ...και ακριβώς από κάτω βλέπω την compareToIgnoreCase και σκέφτομαι αν είναι δυνατόν να είναι τόσο ανίκανοι και να έβαλαν μια method η οποία δε μπορεί παρά να λειτουργεί σωστά "συνήθως αλλά μη το δένεις και κόμπο". To their credit υπάρχει σχόλιο που λέει μη τη χρησιμοποιείς, έχουμε καλύτερα. Ενδιαφέρουσα ερώτηση για όποιον θέλει να εμβαθύνει λίγο σε Unicode: για ποιό λόγο η compareToIgnoreCase με το υπάρχον signature δεν μπορεί να εγγυηθεί ότι θα δουλέψει σωστά; Hint#1 Το κακό ξεκινάει από το ότι δεν της λέμε ποιό locale να χρησιμοποιήσει για τη σύγκριση. Hint#2 Και στην compareTo δεν το λέμε, όμως αυτή δεν έχει ανάλογο πρόβλημα (άσχετα που είναι "άχρηστη" για γενική χρήση, αυτό που κάνει το κάνει με συνέπεια). Άρα η διαφορά πρέπει να βρίσκεται σε κάτι που κάνει η μία διαφορετικά από την άλλη. Τί είναι αυτό; ¹ Θα μπορούσε βέβαια θεωρητικά να υπάρχει τρόπος να ελέγχεις το αν η σύγκριση θα γίνεται πάνω στα περιεχόμενα των strings ως έχουν ή πάνω σε normalized μορφές τους. Αυτό όμως πέραν του ότι είναι αμφιβόλου χρησιμότητας για να μπει στη "standard library" γενικά και εγκληματικό να ισχύει by default, επίσης δεν έχει να κάνει με locale.
migf1 Δημοσ. 30 Δεκεμβρίου 2012 Μέλος Δημοσ. 30 Δεκεμβρίου 2012 Ε ναι, αφού κάθε char έχει μια αριθμητική 16-bit τιμή 0 μέχρι ~65000 , αυτή συγκρίνει ανεξάρτητα από endianess και locale. http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Character.html#compareTo Compares two Character objects numerically Ok, thanks! Οπότε σε C καλώς κάνω τη σύγκριση ως unsigned chars: http://x-karagiannis.gr/prg/custom/doc/libs/html/s2java_8c_source.html#l00272 απλώς πρέπει να συμπληρώσω στις διαφορές πως η LIBS εκδοχή είναι locale specific. Σωστά; EDIT1: Ώπα, έπεσαν πολλές απαντήσεις όσο έγραφα. Πάω ν αφάω όμως τώρα, και θα τις διαβάσω μετά (thanks). EDIT2: Έφαγα @nilosgr & defacer: Το πρόβλημα είναι πως στην C όλες οι αντίστοιχες ρουτίνες της libc είναι πάντα locale-aware. Για να μπορέσω να κάνω locale-independent συγκρίσεις, μετατροπές κλπ, πρέπει να φτιάξω custom απεικόνιση του τύπου char, και κατόπιν να αλλάξω σχεδόν τα πάντα στην βιβλιοθήκη (ζήσε Μάη μου δηλαδή, και δεν έχει και νόημα να μπω σε τέτοια διαδικασία για μια βιβλιοθήκη που υποστηρίζει μονάχα single-byte characters). Οπότε, νομίζω θα αρκεστώ στο unsigned char comparison, κι απλώς θα γράψω στην τεκμηρίωση πως το simplified Java-like API της LIBS είναι πάντα locale-aware. Ήθελα όμως να διασταυρώσω πως η equals() είναι όντως byte σύγκριση (πάντως και τις compareTo(), contentsEqual() κλπ κλπ έτσι τις έχω κάνει, με unsigned char συγκρίσεις). Ευχαριστώ όλους για τη συμμετοχή. Αν χρειαστώ κάτι άλλο θα επανέλθω, 1
defacer Δημοσ. 30 Δεκεμβρίου 2012 Δημοσ. 30 Δεκεμβρίου 2012 Το πρόβλημα είναι πως στην C όλες οι αντίστοιχες ρουτίνες της libc είναι πάντα locale-aware. Για να μπορέσω να κάνω locale-independent συγκρίσεις, μετατροπές κλπ, πρέπει να φτιάξω custom απεικόνιση του τύπου char, και κατόπιν να αλλάξω σχεδόν τα πάντα στην βιβλιοθήκη (ζήσε Μάη μου δηλαδή, και δεν έχει και νόημα να μπω σε τέτοια διαδικασία για μια βιβλιοθήκη που υποστηρίζει μονάχα single-byte characters). Πράγμα που συμβαίνει γιατί η C δεν έχει strings, έχει "μάτσα από characters" (δηλαδή το internal encoding δεν είναι συγκεκριμένο). Έχουμε ξανααναφερθεί σ' αυτό το θέμα (ICU vs standard library functions). Οπότε, νομίζω θα αρκεστώ στο unsigned char comparison, κι απλώς θα γράψω στην τεκμηρίωση πως το simplified Java-like API της LIBS είναι πάντα locale-aware. Ήθελα όμως να διασταυρώσω πως η equals() είναι όντως byte σύγκριση (πάντως και τις compareTo(), contentsEqual() κλπ κλπ έτσι τις έχω κάνει, με unsigned char συγκρίσεις). Το οποίο API σε τι μπορεί να διαφέρει από την ξερή strcmp?
migf1 Δημοσ. 30 Δεκεμβρίου 2012 Μέλος Δημοσ. 30 Δεκεμβρίου 2012 Το οποίο API σε τι μπορεί να διαφέρει από την ξερή strcmp? Πέρα από ότι το simplified Java API παρέχει utility functions που δεν υπάρχουν στη στάνταρ <string.h> και ακόμα και για τις κοινές συχνά κάνει raise διαφορετικά errors (exceptions) και επίσης επιστρέφει και διαφορετικά πράγματα, όλη η LIBS αντί να κρασάρει στο bad-input κάνει raise errors, τα οποία μπορείς είτε να τα κάνεις catch είτε να τα αγνοήσεις. Επίσης, σου δίνει την δυνατότητα να επιλέξεις αν θα έχεις loud ή silent failures (by default είναι loud), καθώς επίσης αν θέλεις να γίνεται pause ή όχι το πρόγραμμά σου όταν προκαλεί σφάλματα (link1, link2) Πέρα από το Java-like API, περιέχει ήδη μαζεμένες τις πιο συχνά χρησιμοποιούμενες c-string συναρτήσεις σε Unix & Unix-like πλατφόρμες (POSIX και μη), προσαρμοσμένες κι αυτές σε πιο αυστηρούς ελέγχους από ότι οι original + το error handling που περιγράφω στην προηγούμενη παράγραφο. Παρέχει και μερικές που στην original μορφή τους δεν είναι διαθέσιμες παντού, δλδ κάποια extensions κυρίως GNU και BSD (π.χ. την s_stresep() εγώ την έχω συνατήσει μονάχα σε NetBSD και Minix, η s_strnstr() είναι FreeBSD specific, η s_strnlen() είναι GNU specific, και πάει λέγοντας). Ομοίως και για τις στάνταρ c-string συναρτήσεις (http://x-karagiannis.gr/prg/custom/doc/libs/html/group__libs_modified.html) και για κάποιες LIBS specific (http://x-karagiannis.gr/prg/custom/doc/libs/html/group__libs_util_funcs.html). Στις στάνταρ και στις Unix-like μια σημαντική προσθήκη της LIBS είναι επίσης πως επιτρέπει overlapping strings (π.χ. η s_strcat()), τα οποία τα κάνει detect μόνη της κι αν επικαλύπτονται κάνει malloc temporary buffer internally, καθώς επίσης πως σε κάποιες συναρτήσεις π.χ. για tokenization παρέχει ειδικό όρισμα για το αν θέλουμε ή όχι να διατηρηθεί το αρχικό c-string ή όχι. Είναι περισσότερο οργανωμένη συλλογή συναρτήσεων με κοινό πλαίσιο παρά βιβλιοθήκη. Αρχικά ήθελα αντί για Java-like API να της βάλω PHP-like API (μιλώντας πάντα για απλά c-strings) αλλά τελικά αποφάσισα να κάνω το 1ο, γιατί πιο clean. Όταν τελειώσω με τις Java-like, μπορεί να βάλω και κάποιες PHP-like (π.χ. έχω φτιάξει ήδη explode(), με κάτι μικροδιαφορές προς το παρόν, όπως για παράδειγμα αν θα γίνεται ή όχι preserve το orgiginal string) και ίσως προσθέσω και από C++ ή και από C#, ανάλογα τα κέφια.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα