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

Ερωτήσεις για C#


migf1

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

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

 

Οπότε, δεν είμαι σε θέση ακόμα να αξιολογήσω σωστά όλα όσα μου απαντάτε. Θα είμαι όμως ελπίζω σύντομα.

 

@defacer

 

Θέλω να διαβάσω προσεκτικά και με καθαρό μυαλό όσα γράφεις, γιατί τώρα είμαι μεταξύ νύστας και πτωματίλας. Ότι απορία έχω θα επανέλθω.

 

Για το culture όμως, έχω μια μέθοδο που κάνει Capitalization στα συνθετικά του ονόματος, καλώντας την ToTitleCse, η οποία ότι είδα χρησιμοποιεί CultrureInfo.TextInfo για να το κάνει.

 

Η μέθοδος είναι αυτή...

 

>
/** @brief Method returning the name's text Capitalized (everything in lower case, except
 *  the 1st letter of every word).
 */
public string Capitalize()
{
	if ( string.IsNullOrEmpty(this.Text) )
		return string.Empty;

	string s = CultureInfo.TextInfo.ToTitleCase(this.Text.ToLower(this.CultureInfo));
	string[] tokens = s.Split(null);

	for (int i=0; i < tokens.Length; i++)
	{
		if ( tokens[i].Length > 0 ) {
			if ( 'σ' == tokens[i][ tokens[i].Length-1 ] ) {
				char[] temp = tokens[i].ToCharArray();
				temp[ temp.Length-1] = 'ς';
				tokens[i] = new string(temp);
			}
		}
	}

	return tokens.Length < 1 ? tokens[0] : string.Join(" ", tokens);
}

 

Θεώρησα λοιπόν πως επειδή θέλω οπωσδήποτε αυτές οι μετατροπές των case να γίνονται πάντα σε Ελληνικό context (συν όποιους Αγγλικούς χαρακτήρες υποστηρίζει το Ελληνικό culture των Windows) έπρεπε να τους περνάω explicitly Ελληνικό culture, να μην τα αφήνω δηλαδή να διαβάζουν τα regiοnal settings του εκάστοτε συστήματος (ομοίως και για την ToLower/ToUpper που έχω σε κάποιες άλλες μεθόδους).

 

Το έχω καταλάβει λάθος;

 

Επίσης, πόσο safe είναι το hard-coding των 'σ' και 'ς' στις συγκρίσεις της παραπάνω μεθόδου (τα αρχεία είναι σωσμένα σε UTF8, παίζει ρόλο αυτό στην C# όπως π.χ. παίζει στην C;)

 

Αύριο θα ήθελα να συζητήσουμε λίγο και αυτό που είπες για το parameter massaging των παραμέτρων, όπου πρότεινες απλότητα. Θα σου εξηγήσω το σκεπτικό μου (το οποίο συνοπτικά είναι για να μη τον βάζω να κάνει συνέχεια conversions σε κάθε get... δηλαδή να γίνονται μια μόνο φορά στο set).

 

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

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

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

Ναι σε αυτό το ζήτημα νομίζω χριάζεται το CultureInfo.

 

Όμως τον κώδικα τον βρίσκω πολύ κόπο για το τίποτα.

 

Μια πρόταση

>
public string Capitalize()
{
if ( string.IsNullOrEmpty(this.Text) )
 return "";

return this.CultureInfo.TextInfo.ToTitleCase(this.Text.ToLower(this.CultureInfo)).Replace("σ ", "ς ");
}

 

Ούτε να το χωρίζεις σε λέξεις ούτε σε χαρακτήρες έπειτα.

 

Απλά αν βρεί την ακολουθεία σ + space (που σημαίνει τελικό σίγμα αλλά λάθος γράμμα) το αντικαθιστά με το σωστό τελικό σίγμα και space.

 

 

EDIT

 

 

Δε το σκέφτηκα σωστά. :D

 

Γιατί αν είναι στο τέλος του string σ (και δεν έχει space μετά) δε θα το αντικαταστήσει.

 

Οπότε πας σε κάτι τέτοιο.

 

>
public string Capitalize()
{
if ( string.IsNullOrEmpty(this.Text) )
 return "";

String ret = this.CultureInfo.TextInfo.ToTitleCase(this.Text.ToLower(this.CultureInfo)).Replace("σ ", "ς ");

if( ret[ret.Length - 1] == 'σ' )
 ret = ret.Substring( 0, ret.Length - 1 ) + "ς";

return ret;
}

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

Αυτά είναι, dεν την ήξερα την replace :) ... btw, στην τεκμηρίωση την βλέπω ως Replace.

 

Πάντως, δεν φαίνεται να μου κάνει, γιατί αφενός τα tokens του Text μπορεί να έχουν οποιοδήποτε IsWiteSpace ανάμεσά τους (όχι δηλαδή μόνο ' ') και αφετέρου επειδή, αν το καταλαβαίνω σωστά αυτός ο τρόπος που δίνεις δεν πρόκειται να αλλάξει ενδεχόμενο 'σ' στο τέλος του τελευταίου token του Text, επειδή το Text είναι Trim'ed (άρα δεν υπάρχουν whitespaces μετά το τελευταίο γράμμα του τελευταίου token).

 

Έτσι δεν είναι;

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

Ναι το άλλαξα και καλύπτεται και το τελευταίο σ στο string.

 

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

Μπορεί να φτιαχτεί κάτι πιο αφηρημένο.

Να έχει κάπου σε μια σταθερά ένα char ή ένα string για το πώς διαχωρίζονται οι λέξεις και στο replace να μπαίνει

 

"σ" + αυτή η σταθερά.

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

Ούτε την Substring την ήξερα!

 

Νομίζω όμως πως υπάρχει πρόβλημα και στον διορθωμένο κώδικα. Εκείνη η Replace στην αρχή, πάλι το ίδιο πρόβλημα δεν θα έχει με το τελευταίο s?

 

Πάντως, νομίζω πως τελικά παρά την ένσταση του defacer, μάλλον με συμφέρει να κάνω την μετατροπή (ας το πούμε normalization) απευθείας στον getter της Text, οπότε από εκεί και πέρα όλα τα υπόλοιπα θα έχουν ένα fixed format στο οποίο θα μπορούν να δουλέψουν.

 

Ή για να μην χαλάσουμε και το χατήρι του defacer, που λέει πως οτι κάνεις set το θες ακριβώς ίδιο στο get, θα μπορούσα το normalized Text να το κρατάω σε ξεχωριστό, private field, π.χ. textNormalized.

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

Ούτε την Substring την ήξερα!

 

Για αυτό θα βοηθήσει πάρα μα πάρα πολύ το visual studio.

Π.χ. το suggestion

intellisense.png

 

 

 

Εκείνη η Replace στην αρχή, πάλι το ίδιο πρόβλημα δεν θα έχει με το τελευταίο s?

 

H replace θα κάνει replace μόνο τα "σ " δηλαδή σ + space.

Αν υπάρχει "σ" στο τέλος του string δε θα αντικατασταθεί.

 

π.χ.

Το "καθωσ περνασ"

θα γίνει "καθως περνασ"

 

Όμως ο αμέσως μετά έλεγχος θα το αντικαταστήσει αν υπάρχει.

 

>

if( ret[ret.Length - 1] == 'σ' ) //Αν το τελευταίο γράμμα του string είναι σ
ret = ret.Substring( 0, ret.Length - 1 ) + "ς"; // το κόβει και προσθέτει 'ς'.

 

 

Τώρα το παραπάνω είναι για Capitalize ενός string ολόκληρου με όσες λέξεις και αν περιέχει. Ώστε να μην χωρίζεις σε λέξεις.

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

 

Για αυτό θα βοηθήσει πάρα μα πάρα πολύ το visual studio.

...

 

Εγώ έχω βάλει custom run command στο Notepad++ και με πάει στην online τεκμηρίωση της Microsoft (απλώς πρέπει να έχω τον κέρσορα μέσα στο όνομα της κλάσης).

 

H replace θα κάνει replace μόνο τα "σ " δηλαδή σ + space.

Αν υπάρχει "σ" στο τέλος του string δε θα αντικατασταθεί.

 

π.χ.

Το "καθωσ περνασ"

θα γίνει "καθως περνασ"

 

Όμως ο αμέσως μετά έλεγχος θα το αντικαταστήσει αν υπάρχει.

 

>

if( ret[ret.Length - 1] == 'σ' ) //Αν το τελευταίο γράμμα του string είναι σ
ret = ret.Substring( 0, ret.Length - 1 ) + "ς"; // το κόβει και προσθέτει 'ς'.

 

 

Τώρα το παραπάνω είναι για Capitalize ενός string ολόκληρου με όσες λέξεις και αν περιέχει. Ώστε να μην χωρίζεις σε λέξεις.

 

Ω yes, έχεις δίκιο. Και θα φανεί ιδιαίτερα χρήσιμο αν το εφαρμόσω σε συνδυασμό με το normalization που έλεγα παραπάνω. Thanks.

 

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

@migf1

 

Δεν ηθελα να πω κατι για εσένα.Ελπίζω να μην παρεξηγήθηκες.Είχα την εντύπωση ότι ο defacer είναι πολύ καλός σε C# και C++ και οι γνώσεις του θα βοηθούσαν πολύ.Και φυσικά φαίνεται από τις αναλυτικές του απαντήσεις ( σεντόνια ) στην προηγούμενη σελίδα . Το σχόλιο ήταν για τις γνώσεις του :P

 

 

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

@defacer Είσαι ωραίος, ευχαριστώ για το χρόνο σου! Τα optional/named arguments τα χρησιμοποιώ κατά κόρον στην Python η οποία by design δεν έχει αυτό το πρόβλημα. Έχω να πιάσω C# 3 χρόνια τώρα :D Δια ροπάλου επομένως έχεις δίκιο! :D

 

Ναι, σε δυναμικές γλώσσες όπως Python το binding για το method call γίνεται και αυτό στο runtime, οπότε δεν υπάρχει δυνατότητα να σου μείνει κάποιο "κατάλοιπο" σε παλιό binary. Και πάλι όμως το να αλλάξεις την τιμή του default argument σε derived class είναι κατακριτέο.

 

Για το culture όμως, έχω μια μέθοδο που κάνει Capitalization στα συνθετικά του ονόματος, καλώντας την ToTitleCse, η οποία ότι είδα χρησιμοποιεί CultrureInfo.TextInfo για να το κάνει.

 

Θεώρησα λοιπόν πως επειδή θέλω οπωσδήποτε αυτές οι μετατροπές των case να γίνονται πάντα σε Ελληνικό context (συν όποιους Αγγλικούς χαρακτήρες υποστηρίζει το Ελληνικό culture των Windows) έπρεπε να τους περνάω explicitly Ελληνικό culture, να μην τα αφήνω δηλαδή να διαβάζουν τα regiοnal settings του εκάστοτε συστήματος (ομοίως και για την ToLower/ToUpper που έχω σε κάποιες άλλες μεθόδους).

 

Το έχω καταλάβει λάθος;

 

Όχι, έτσι γίνονται τα πράγματα. Πάντως πρώτον έχε υπόψη ότι η ToTitleCase δεν μετατρέπει λέξεις που είναι σε ALL CAPS. Επίσης, εγώ θα έκανα τη μετατροπή κάπως έτσι:

 

>
var culture = new CultureInfo("el-GR");
var titleCase = culture.TextInfo.ToTitleCase("ΠαΠΆΣ ΠΑπαδόπουΛΟς");
return Regex.Replace(titleCase, "σ(?=\\", "ς");

// ΠΡΟΣΟΧΗ! Μέσα στο regular expression το B πρέπει να είναι lowercase,
// αλλά ο φανταστικός editor του insomnia...

 

Γενικά σαν rule of thumb θα πω ότι όταν στη C# δεις τον εαυτό σου να γράφει τέτοια for κλπ κλπ you are doing something wrong. Προφανώς τώρα δεν ξέρεις how to do it right αλλά έχε το υπόψη.

 

Ακόμα κι αν δε θέλεις να χρησιμοποιήσεις regex εδώ (γιατί?) τότε το "σωστό" ισοδύναμο του κώδικα που έδωσες θα ήταν

 

>return string.Join(" ", str.Split(null).Select(s => s.EndsWith("σ") ? s.Substring(0, s.Length - 1) + "ς" : s));

 

LINQ και μετά there is no going back (αυτό το έχω πει πολλές φορές για τη C# -- they must have done something right).

 

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

 

- Δημήτριος Ιωάννη Χατζηκώστα (τι παίζει με first name και last name? γενικά τα ονόματα των ανθρώπων δεν μπορείς να τα κάνεις split στο space και να πεις τελειώσαμε)

- ΑΝΑΝίΑΣ-Παφνούτιος Φορουμίτης (τι παίζει με τη μετατροπή του ς στον Ανανία? η μετατροπή με regular exp<b></b>ression δεν έχει αυτό το πρόβλημα)

 

Επίσης, πόσο safe είναι το hard-coding των 'σ' και 'ς' στις συγκρίσεις της παραπάνω μεθόδου (τα αρχεία είναι σωσμένα σε UTF8, παίζει ρόλο αυτό στην C# όπως π.χ. παίζει στην C;)

 

Εδώ είσαι. Εσωτερικά το encoding που χρησιμοποιείται σε .NET είναι UTF-16 αλλά αυτό δε σε επηρρεάζει. Εσύ απλά κάνε save as utf-8.

 

Ή για να μην χαλάσουμε και το χατήρι του defacer, που λέει πως οτι κάνεις set το θες ακριβώς ίδιο στο get, θα μπορούσα το normalized Text να το κρατάω σε ξεχωριστό, private field, π.χ. textNormalized.

 

Αυτό θα ήταν η καλύτερη λύση αν παίζει τόσο σημαντικό ρόλο το να μην κάνεις μετατροπές στους getters (στην ουσία και γω αυτό σου πρότεινα, normalize και αποθήκευσε στο firstName field).

 

Πάντως ρεαλιστικά δεν παίζει κανένα ρόλο αν θα κάνεις μετατροπή στους getters ή κάπου αλλού οπότε αντί για premature optimizations διάλεξε από τις λύσεις που είναι λογικές αυτήν που παράγει τον πιο κομψό κώδικα.

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

 

Αυτό θα ήταν η καλύτερη λύση αν παίζει τόσο σημαντικό ρόλο το να μην κάνεις μετατροπές στους getters (στην ουσία και γω αυτό σου πρότεινα, normalize και αποθήκευσε στο firstName field).

 

Ενα interface τυπου

FirstName :string

LastName :string

Parse(string fullName) :NameClass

Normalize() :void

 

Θα ηταν gg (αποψη μου)

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

@Chris: Καμία παρεξήγηση ;)

 

@Papi: Σαφώς, αλλά γράφω toy-κώδικα για να εξοικειωθώ με τη γλώσσα. Δλδ, ξεκίνησα με όλα στη main, μετά έκανα toy-ομαδοποιήσεις σε κλάσεις, μετά σε namespaces, μετά σε assemblies κλπ. Μετά θα τα ξανα-αλλάξω για να κάνω π.χ. base & derived classes (όταν φτάσω σε αυτές τις ενότητες), μετά interface, κλπ κλπ με ότι δω ότι μου παρέχει η γλώσσα. Δηλαδή τα αναδιοργανώνω σχεδόν όλα με κάθε νέο concept που διαβάζω (επειδή θέλω να μου εντυπώνονται όσο το δυνατόν περισσότερο από την 1η φορά, μη ξεχνάς πως έχω να ασχοληθώ σοβαρά με OOP γλώσσα πολλά χρόνια).

 

...

Στα members της τρέχουσας class βάζε πάντα this, αν και δεν έχει καμία τεχνική διαφορά. Ο λόγος είναι ότι έτσι λέει η Microsoft οπότε ελλείψει πολύ καλού λόγου για το αντίθετο, go with the flow. Αυτό θα βοηθήσει.

 

Στην ονοματολογία το "σωστό" είναι:

 

>private CultureInfo cultureInfo;
private string text;
private string firstName;
private string lastName;

 

(by the way το CultureInfo πού χρειάζεται?)

 

Τα comments σε xmldoc.

...

Και τέλος κάτι γενικό: αν χρησιμοποιείς Visual Studio θα δεις ότι το μέγεθος της βοήθειας που σου παρέχει το IDE (και το tooling γενικότερα) στη C# σε σχέση με τα αντίστοιχα που υπάρχουν για C διαφέρει περίπου όσο διαφέρει ο ήλιος με ένα φακό τσέπης. Για να καταλάβεις για τι πράγμα μιλάω, βάλε ReSharper και γράψε λίγο κώδικα. Αν τυχόν είσαι δύσκολος πελάτης ψάξε να δεις τι επιλογές σου δίνει από τα μενού ή από το help.

 

There is no going back.

 

 

Thanks για τα χρησιμότατα links!

 

Είμαι λίγο αναποφάσιστος για το αν θα πρέπει να ακολουθήσω τα στάνταρ της Microsoft ή του Mono. Βασικά είναι πολύ μεγάλη η ασυμβατότητα μεταξύ των runtimes τους (αν υπάρχει μεγάλος βαθμός συμβατότητας/portability μάλλον θα προτιμήσω να διαβάσω του Mono).

 

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

 

>var s = "Trailing spaces ";
foo.Text = s;
if (foo.Text != s) Console.WriteLine("Wait, what?!?!?");

 

To expectation σε μια property είναι πως ο,τι βάλεις, αυτό θα βγάλεις. Αν θέλεις να κάνεις τέτοια και θεωρείς ότι πρέπει να γίνουν στην μέσα στην class (που συνήθως δεν πρέπει) τότε κάνε μια σχετική method. Εκεί δεν υπάρχει expectation.

...

Τέλος, για το FirstName -- simple is good:

>
public string FirstName
{
get { return this.firstName; }

}
public string Text
{
get { ... }
set
{
    // ....
        this.firstName = ...;
}
}

...

 

PS: Τώρα που το βλέπω καλύτερα, δε μου αρέσει αυτό που γίνεται στον constructor που κάνει "μασάζ" στις τιμές των παραμέτρων του. Γενικά το "προσπαθώ να κάνω ο,τι μπορώ" δεν είναι στη φιλοσοφία της c#. Αν δε σου αρέσει αυτό που βλέπεις, throw new ArgumentException ή ArgumentNullException και περάστε έξω παρακαλώ.

 

Δεν ξέρω αν το πήρε το μάτι σου στις προηγούμενες σελίδες, που κάπου το ανέφερα, το σκεπτικό μου για αυτού του είδους την υλοποίηση των setters ήταν για να αποφορτίσω τους getters από τα συνεχόμενα calculations, μιας και οι getters χρησιμοποιούνται πολύ συχνότερα.

 

Αντιτίθεται αυτό το σκεπτικό με την κοινή πρακτική στη γλώσσα; Θεωρείται κακή πρακτική;

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

Μια ερώτηση: Κερδίζει κάτι κάποιος αν κάνει trivially implemented properties με private μεταβλητές αντί να κάνεις τις μεταβλητές public? Δηλαδή γιατί να κάνει αυτό:

>
private string _Name;
public string Name
{
  get
  {
     return this._Name;
  }
  set
  {
     this._Name = value;
  }
}

και όχι αυτό:

>
public string Name;

 

Μιλάω βέβαια μόνο για τέτοιο trivial implementation. Με την εξης λογική: Γιατί να μην κάνει απλά τη μεταβλητή public, και μετά αν αποφασίσει ότι θέλει να έχει πιο πολύ πολύπλοκη λογική να την κάνει property με το ίδιο όνομα. Έτσι ο κώδικας στις client classes δεν κάνει break.

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

...

Πάντως πρώτον έχε υπόψη ότι η ToTitleCase δεν μετατρέπει λέξεις που είναι σε ALL CAPS. Επίσης, εγώ θα έκανα τη μετατροπή κάπως έτσι:

 

>
var culture = new CultureInfo("el-GR");
var titleCase = culture.TextInfo.ToTitleCase("ΠαΠΆΣ ΠΑπαδόπουΛΟς");
return Regex.Replace(titleCase, "σ(?=\\", "ς");

// ΠΡΟΣΟΧΗ! Μέσα στο regular exp<b></b>ression το B πρέπει να είναι lowercase,
// αλλά ο φανταστικός editor του insomnia...

 

Γενικά σαν rule of thumb θα πω ότι όταν στη C# δεις τον εαυτό σου να γράφει τέτοια for κλπ κλπ you are doing something wrong. Προφανώς τώρα δεν ξέρεις how to do it right αλλά έχε το υπόψη.

 

Ακόμα κι αν δε θέλεις να χρησιμοποιήσεις regex εδώ (γιατί?) τότε το "σωστό" ισοδύναμο του κώδικα που έδωσες θα ήταν

 

>return string.Join(" ", str.Split(null).Select(s => s.EndsWith("σ") ? s.Substring(0, s.Length - 1) + "ς" : s));

 

LINQ και μετά there is no going back (αυτό το έχω πει πολλές φορές για τη C# -- they must have done something right).

 

Ευτυχώς το είχα βρει εξαρχής πως η ToTitleCase έχει διάφορα exceptions, οπότε από την αρχή τα έκανα πρώτα ToLower και μετά ToTitleCase.

 

Thanks και για τον κώδικα! Κάτι παρόμοιο με τη χρήση του LINQ έχω βάλει ήδη στη input validation method, που απαιτεί μονάχα γράμματα ή blanks...

 

 

 

>
   public GreekName InputTextLettersOnly( string prompt, bool verbose )
   {
       string   tempText = string.Empty;
       string[] errMessages =    {
               "*** επιτρέπονται μόνο γράμματα\n",
               "*** τα ονόματα πρέπει να περιέχουν τουλάχιστον 2 γράμματα\n"
           };

       for(; {

           if ( !string.IsNullOrEmpty(prompt) )
               Console.Write( prompt );

           tempText = Console.ReadLine().Trim();

           if ( 0 == tempText.Length ) {
               continue;
           }
           if ( !tempText.All(c=>Char.IsLetter(c) || Char.IsWhiteSpace(c)) )
           {
               if ( verbose && errMessages.Length > 0 )
                   Console.WriteLine( errMessages[0] );
               continue;
           }
           if ( tempText.Length < 2 ) {
               if ( verbose && errMessages.Length > 1 )
                   Console.WriteLine( errMessages[1] );
               continue;
           }
           break;

       }
       this.Text = tempText;
       return this;
   }

 

 

αλλά βασικά κάπου την βρήκα σχεδόν έτοιμη, ψάχνοντας για κάτι άλλο. Οπότε την έβαλα παπαγαλίστικα, μέχρι να φτάσω να διαβάσω για το LINQ (ομοίως και για τα Rexeges... δεν έχω φτάσει ακόμα, τα σημείωσα όμως για να τα ξαναδώ όταν θα είμαι σε θέση να καταλαβαίνω και τα mechanics τους).

 

Πάντως και οι 2 κώδικες που μου έδωσες, έχουν το πρόβλημα πως αν υπάρχουν κολλητά blanks ανάμεσα στα tokens, τότε προστίθενται ως κενά. Πριν λίγο ανακάλυψα μια overloaded έκδοση της split η οποία δέχεται ως 2ο όρισμα ένα "StringSplitOptions", για το αν θα κρατάει ή όχι blank tokens.

 

Προς το παρόν λοιπόν την NormalizeText() μέθοδο την υλοποίησα έτσι...

 

>
   string NormalizeText()
   {
       if ( string.IsNullOrEmpty(this._text) || string.IsNullOrEmpty(this._text))
           return string.Empty;

       // NOTE: ctors guarantee that this.CultureInfo is never null
       this._textNormalized = this._text.ToLower(this.CultureInfo).Trim();
       string[] tokens = this._textNormalized.Split(
                       new char[]{' ','\t','\n','\r','\v','\f'},
                       StringSplitOptions.RemoveEmptyEntries
                       );
       return this._textNormalized = string.Join( " ", tokens );

μέχρι να φτάσω σε LINQ και RegExes

 

Btw, αν αλλάξω την εν λόγω κλήση σε...

 

>
       string[] tokens = this._textNormalized.Split(
                       null,
                       StringSplitOptions.RemoveEmptyEntries
                       );

 

τρώω...

 

>
test.cs(130,21): error CS0121: The call is ambiguous between the following methods or properties: 'string.Split(char[], System.StringSplitOptions)' and 'string.Split(string[], System.StringSplitOptions)'

 

Διορθώνεται με casting: .Split( (char[])null, StringSplitOptions.RemoveEmptyEntries );

 

είναι όμως safe?

 

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

 

- Δημήτριος Ιωάννη Χατζηκώστα (τι παίζει με first name και last name? γενικά τα ονόματα των ανθρώπων δεν μπορείς να τα κάνεις split στο space και να πεις τελειώσαμε)

 

fname = Δημήτριος

lname = Χατζηώστα

 

Θεωρώ δεδομένο πως η είσοδος γίνεται στην ονομαστική πτώση (για αυτό έχω βάλει και prompt "Το πλήρες ονομά σας" αντί π.χ. "Πώς σας λένε;" :) )

 

Προς το παρόν, για να τα μετατρέψω σε κλητική πτώση, απλώς ελέγχω αν οποιοδήποτε token λήγει σε (normalized) 'ς', κι αν ναι το κόβω.

 

Το επόμενο βήμα θα ήταν αν λήγει σε "ος" να μετατρέπεται σε "ε", αλλά ανακάλυψα εκ των υστέρων όχι μόνο πως δεν ισχύει (π.χ. Αλέκος/Αλέκο αλλά Παπαδόπουλος/Παπαδόπουλε) αλλά και δεν είναι καν στανταρισμένο με γραμματικούς κανόνες πότε αλλάζει σε -ε και πότε σε -ο η κατάληξη όταν στην ονομαστική είναι -ος.

 

Οπότε, θα βάλω 2 bool και θα τον ρωτάω αν είτε το fname είτε το lname του αλλάζει την κατάληξή του σε -ε (μόνο αν δω πως τελειώνει κάποιο από τα 2 σε -ος, στα υπόλοιπα αρκεί η αφαίρεση του ς if any (νομίζω δηλαδή). Λόγω αυτού θέλησα να προσθέσω fname & lname fields.

 

- ΑΝΑΝίΑΣ-Παφνούτιος Φορουμίτης (τι παίζει με τη μετατροπή του ς στον Ανανία? η μετατροπή με regular exp<b></b>ression δεν έχει αυτό το πρόβλημα)

Εννοείς πως με τα regex δεν χρειάζεται να δηλώσεις explicitly ποιοι χαρακτήρες θα λογιστούν ως token separators?

 

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

[..]Πριν λίγο ανακάλυψα μια overloaded έκδοση της split η οποία δέχεται ως 2ο όρισμα ένα "StringSplitOptions", για το αν θα κρατάει ή όχι blank tokens.

Βάλε επάνω το VS, το IntelliSense με το που θα έγραφες .Split( θα στο πρότεινε αμέσως (μαζί με όλα τα διαθέσιμα overloads) δίχως καμία ταλαιπωρία και ανάγκη για περαιτέρω ψάξιμο.

 

 

post-41640-0-86702000-1352994527_thumb.png

 

 

Και εγώ δεν συμπαθούσα στην αρχή το VS Editor αλλά τώρα τον θεωρώ υποδειγματικό (σχεδόν).

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

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

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

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

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

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

Σύνδεση

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

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

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