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

σύγκριση χαρακτήρων στην C


fastmanakos

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

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

δηλαδή η σύγκριση των χαρακτήρων ώστε να τα βάλει σε αλφαβητική σειρά;

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

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

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

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

Θα συγκρίνεις έναν προς έναν τους χαρακτήρες των 2 συμβολοσειρών.

 

>
char str1[4]={"abcd"};
char str2[4]={"abca"};

int length;
if(strlen(str1) > strlen(str2))
 length = strlen(str2);
else
 length = strlen(str1);

int i;
for(i=0; i<length; i++) {
 if(str1[i] < str2[i]) {
   printf("1st str1\n");
   break;
 }
 if(str1[i] > str2[i]) {
   printf("1st str2\n");
   break;
 }
}

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

Αν και είμαι αντίθετος από την απευθείας υπόδειξη όλου του κώδικα σε ερωτήσεις ασκήσεων, εφόσον δόθηκε ήδη να σχολιάσω πως η λύση του φίλου pantpesl2 χρησιμοποιεί αχρείαστα 3 κλήσεις της ιδιαίτερα δαπανηρής strlen().

 

Επίσης οφείλω να ομολογήσω πως είναι η 1η φορά που βλέπω να ορίζονται και να αρχικοποιούνται c-strings με τον τρόπο που περιέχει ο κώδικας αυτός (δηλαδή και άγκιστρα και 2πλα εισαγωγικά, και ταυτόχρονα με ορισμό πλήθους χαρακτήρων κατά έναν λιγότερο από αυτούς με τους οποίους αρχικοποιεί και τα 2 strings... δεν ξέρω καν αν είναι έγκυρος αυτός ο τρόπος). Επιπρόσθετα, ο κώδικας μένει αδρανής αν τα strings είναι ίδια και έχω την εντύπωση πως έχει και θέματα με strings ανόμοιου μήκους, αλλά δεν είμαι σίγουρος (δεν τον έχω τσεκάρει).

 

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

 

>
char str1[ ] = "abcb";
char str2[ ] = "abc";
bool first1st = false;

int  i=0, j=0;
while ( str1[i] == str2[j++] )
	if ( '\0' == str1[i++] )  // ή if ( !str1[i++] )
		break;
first1st = (str1[i] <= str2[--j]);

printf( "1st: %s\n", first1st ? "str1" : "str2" );

Το απλούστερο όλων φυσικά είναι η χρήση της έτοιμης strcmp() που πρότεινε ο φίλος nilos_gr (μιας και ο παραπάνω κώδικας στην ουσία υλοποιεί ένα custom strcmp() )

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

Έχω πάρα πολύ καιρό να ασχοληθώ με C (πριν 3 χρόνια που έφτιαξα ένα tetris για τη σχολή), αλλά αν θυμάμαι καλά, η strcmp() δεν συγκρίνει απλά τα 2 string?

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

Έχω πάρα πολύ καιρό να ασχοληθώ με C (πριν 3 χρόνια που έφτιαξα ένα tetris για τη σχολή), αλλά αν θυμάμαι καλά, η strcmp() δεν συγκρίνει απλά τα 2 string?

Ναι. Αυτό από ότι βλέπω ζητάει και η άσκηση.

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

Θέλω να πω ότι απλά σου βγάζει αν είναι ίδια ή όχι, και όχι αν το ένα προηγείται του άλλου στο αλφάβητο. Σωστά? :rolleyes:

Α, όχι... αν είναι ίδια επιστρέφει 0, αν s1 < s2 επιστρέφει αρνητική τιμή, αλλιώς θετική.

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

beep το tetris μου μεσα !!!

 

@migf1

Εχω παρατηρησει οτι καθε φορα που βλεπεις την strlen() βγαζεις αφρους απο το στομα :P

Πιστευω οτι οι απαντησεις σου ( χωρις την strlen ) δυσκολευουν περισσοτερο τους αρχαριους. Βεβαια , ο κωδικας σου τους κανει να σκεφτονται διαφορετικα και πιο εξυπνα , αλλα για το επιπεδο που βρισκονται μου φαινεται οτι η strlen ειναι "καλο" να χρησιμοποιειται.

 

Οταν αποκτησουν περισσοτερη εμπειρια και νιωθουν πιο ανετα να "παιζουν" με την μνημη , μια απαντηση σαν τη δικη σου ειναι οτι πρεπει ;)

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

Μόνο αν σκοπεύεις να ασχοληθείς με C, αλλιώς και να κάνεις θα τα ξανα-ξεχάσεις μετά από λίγο :)

Η αλήθεια είναι ότι ποτέ δε με τράβηξε αυτή η γλώσσα..

 

 

beep το tetris μου μεσα !!!

Κακές εμπειρίες έχεις κ εσύ?:P

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

Επίσης οφείλω να ομολογήσω πως είναι η 1η φορά που βλέπω να ορίζονται και να αρχικοποιούνται c-strings με τον τρόπο που περιέχει ο κώδικας αυτός (δηλαδή και άγκιστρα και 2πλα εισαγωγικά, και ταυτόχρονα με ορισμό πλήθους χαρακτήρων κατά έναν λιγότερο από αυτούς με τους οποίους αρχικοποιεί και τα 2 strings... δεν ξέρω καν αν είναι έγκυρος αυτός ο τρόπος).

 

Είναι έγκυρος:

 

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

 

Εχω παρατηρησει οτι καθε φορα που βλεπεις την strlen() βγαζεις αφρους απο το στομα :P

Πιστευω οτι οι απαντησεις σου ( χωρις την strlen ) δυσκολευουν περισσοτερο τους αρχαριους. Βεβαια , ο κωδικας σου τους κανει να σκεφτονται διαφορετικα και πιο εξυπνα , αλλα για το επιπεδο που βρισκονται μου φαινεται οτι η strlen ειναι "καλο" να χρησιμοποιειται.

 

Οταν αποκτησουν περισσοτερη εμπειρια και νιωθουν πιο ανετα να "παιζουν" με την μνημη , μια απαντηση σαν τη δικη σου ειναι οτι πρεπει ;)

 

Η αλήθεια είναι πως τις περισσότερες φορές η strlen είναι απλά έξτρα καθυστέρηση, αλλά έχεις δίκιο για τους αρχάριους. Το πρόβλημα είναι πως αυτά τα πράγματα θα πρέπει να τους τα μαθαίνουν οι καθηγητές τους, διαφορετικά δεν πάμε πουθενά. Για παράδειγμα, αν δίδασκα C προσωπικά θα τους έλεγα πρώτα για τη strlen, μετά ασκήσεις με high-level functions, μετά το πραγματικό πρόσωπο των strings (=pointers) και μετά ασκήσεις όπου strlen και σια απαγορεύονται (αφού βέβαια όταν τους δίνεις τις εναλλακτικές κάνεις και τη σχετική κουβέντα για το τι διαφορές υπάρχουν).

 

Το πρόβλημα είναι ότι α) οι ακαδημαϊκοί δεν σκέφτονται έτσι (και ίσως δε θα έπρεπε να σκέφτονται έτσι) και β) δεν υπάρχει χρόνος για να τα κάνεις αυτά τα πράγματα. Όταν κάποια περίοδο δίδασκα τα πιο ενδιαφέροντα πράγματα τα έλεγα σε εθελοντικά (και για μένα και για τους φοιτητές) μαθήματα.

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

@migf1

Εχω παρατηρησει οτι καθε φορα που βλεπεις την strlen() βγαζεις αφρους απο το στομα :P

Βασικά δεν χαλιέμαι όταν βλέπω την strlen(), αλλά όταν δεν χρησιμοποιείται efficiently.

 

Κι αυτό επειδή έχω συναντήσει σε πραγματικές συνθήκες κώδικες που λόγω της αλόγιστης χρήσης της strlen() καταστρέφουν ολόκληρη την εφαρμογή (τρέχουν και 2 και 3 και 4 φορές και n φορές πιο αργά).

 

Πιστευω οτι οι απαντησεις σου ( χωρις την strlen ) δυσκολευουν περισσοτερο τους αρχαριους. Βεβαια , ο κωδικας σου τους κανει να σκεφτονται διαφορετικα και πιο εξυπνα , αλλα για το επιπεδο που βρισκονται μου φαινεται οτι η strlen ειναι "καλο" να χρησιμοποιειται.

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

 

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

 

Το πιο χαρακτηριστικό (και συνάμα συνηθισμένο) παράδειγμα αλόγιστης χρήσης της strlen() είναι το ακόλουθο for loop...

 

>
if (i=0; i < strlen(str); i++)
...

Φαντάσου τώρα αυτό το loop να εφαρμοζεται ας πούμε στην αναζήτηση μιας συμβολοσειράς στα λεξικά 20 γλωσσών, με το κάθε λεξικό να αποτελείται κατά μέσο όρο ας πούμε από 100.000 λέξεις (προφανώς οι αναζητήσεις δεν γίνονται έτσι, αλλά το φέρνω σαν απλοϊκό παράδειγμα αναζήτησης σε 2 εκατομμύρια λέξεις).

 

Μετατρέποντας το παραπάνω loop σε...

 

>
int len = strlen(str);
for (i=0; i < len; i++)
	...

μπορείς να φανταστείς πόσο δραματικά πέφτει ο χρόνος αναζήτησης.

 

Οταν αποκτησουν περισσοτερη εμπειρια και νιωθουν πιο ανετα να "παιζουν" με την μνημη , μια απαντηση σαν τη δικη σου ειναι οτι πρεπει ;)

Σε άλλες γλώσσες το μήκος του string αποθηκεύεται μέσα στο object του string τη στιγμή της δημιουργίας του, με αποτέλεσμα η: string.len να υπολογίζεται σε Ο(1). Σε αυτές τις γλώσσες το παραπάνω παράδειγμα με το loop είναι απόλυτα θεμιτό και γρήγορο. Στη C όμως υλοποιείται με τη 2η χρήση της strlen() και όχι με την 1η (για να χρησιμοποιηθεί με την 1η πρέπει το str να έχει υλοποιηθεί ως struct που υπολογίζει δυναμικά το μήκος του όταν δημιουργείται ή όταν αλλάζει το μέγεθός του γενικότερα).

 

Θεωρώ πολύ σημαντικό για έναν αρχάριο να ξεκαθαρίσει εξαρχής τα + και τα - της strlen, και είναι απορίας άξιον που δεν του δίνουν την αρμόζουσα έμφαση στις σχολές. Τα strings είναι από τα πλέον χρησιμοποιούμενα στον προγραμματισμό.

 

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

 

>
while ( *cp1 == *cp2++ )
	if ( !*cp1++ )
		break;
firts1st = ((int)(*cp1 - *--cp2) <= 0);

που έχει ανεβασμένο βαθμό δυσκολίας κατανόησης κατά 1-2 επίπεδα.

 

EDIT:

 

Thanks για την διευκρίνιση της αρχικοποίησης φίλε @defacer.

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

@migf1:

 

Βασικά καλά τα λέμε εδώ για το O(N) της strlen κλπ, αλλά εκτός συγκεκριμένων εξαιρέσεων η απλή αλήθεια είναι ότι εν έτει 2012 με char* δε μπορείς να γράψεις απολύτως κανένα σοβαρό πρόγραμμα γιατί single byte encoding = fail οπότε

 

1) είναι εγκληματικό το γεγονός ότι δε διδάσκουν παντού κάτι σαν κι αυτό

 

2) εφόσον δεν υπάρχει χρήσιμο Unicode support στη C δεν έχει και πολύ νόημα να μιλάμε για strlen -- θα αναγκαστείς να χρησιμοποιήσεις κάποια εξωτερική library στην οποία το string type μπορεί να περιέχει και το μήκος του (a la BSTR)

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

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

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

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

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

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

Σύνδεση

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

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

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