You are on page 1of 24

Συμβολοσειρές

ΣΥΜΒΟΛΟΣΕΙΡΕΣ

Γεώργιος Παπαϊωάννου (2013-14)


gepap@aueb.gr
Συμβολοσειρές

• Περιγραφή:
– Ο τύπος string
– Μετατροπή από και προς τον τύπο string
– Βασικές μέθοδοι
– Χρήση Ελληνικών
– Συναρτήσεις C εκτύπωσης και ανάγνωσης

• Τελευταία ενημέρωση: Ιούνιος 2013

Εισαγωγή - 2
Συμβολοσειρές

• Είδαμε ότι τα null-terminated strings (πίνακες χαρακτήρων)


μπορούν να χρησιμοποιηθούν ως strings
• Στη C++ υπάρχει ειδική κλάση, η string που ενσωματώνει
μια αντικειμενοστρεφή υλοποίηση των συμβολοσειρών και
παρέχει υποστήριξη για σύνθετες αναπαραστάσεις
χαρακτήρων, όπως Unicode, wide characters κλπ.
• Σημείωση: Εξακολουθούμε να δουλεύουμε με πίνακες
χαρακτήρων όταν:
– Θέλουμε συμβατότητα με C (γίνεται και μετατροπή μεταξύ των 2
τύπων
– Επιθυμούμε μεγαλύτερη ταχύτητα (απλούστερη αναπαράσταση)

3
Συμβολοσειρές

#include <string> // Εδώ δηλώνεται το string


#include <iostream>
using namespace std; // Εδώ ανήκει το string (std::string)

int main() {
string s1, s2; // Δε χρειάζεται να καθορίσουμε τα μεγέθη.
cin >> s1; // Ο χώρος του s1 προσαρμόζεται αυτόματα.
s2 = "copy of " + s1; // Πρόσθεση συμβολοσειρών. Μετατροπή
// του πίνακα χαρακτήρων σε string.
s1 = "new string"; // Νέα τιμή του s1.
cout << s1 << endl << s2 << endl;
}

Πληκτρολογώ "test". Τυπώνει:


new string
copy of test

4
Συμβολοσειρές

• Η κλάση string είναι μέρος της βασικής βιβλιοθήκης


«standard template library» (STL) η οποία είναι σπασμένη σε
διάφορα αρχεία (π.χ. iostream, string κλπ)
• Η βιβλιοθήκη αυτή εντάσσει όλες τις κλάσεις της, τους
τύπους της και τις συναρτήσεις της σε έναν κοινό χώρο
ονομάτων (namespace), τον std
• Για να δηλώσω ένα string κανονικά ενσωματώνω και το
namespace στο όνομα της κλάσης: std::string
• Αν δηλώσω ότι «χρησιμοποιώ» αυτό το namespace, μπορώ
να το παραλείψω από τη δήλωση:
using namespace std;
string var = “my string”;
5
Συμβολοσειρές

• Από πίνακα χαρακτήρων σε string:


char buffer[20] = “try me”;

std::string str = buffer;

• Από string σε πίνακα χαρακτήρων:


str.c_str();

• Πρόσβαση στον εσωτερικό buffer (χαρακτήρων):


str.data(); // Δεν είναι αντίγραφο και

// δε μπορούμε να το αλλάξουμε (const)

6
Συμβολοσειρές

• Μέγεθος:
string.size() και string.length() (ισοδύναμα)
• Άδεια συμβολοσειρά:
string.empty()

• Ανατρέξτε στον οδηγό αναφοράς για τον πλήρη


κατάλογο των μεθόδων του string:
http://www.cplusplus.com/reference/string/string/

7
Συμβολοσειρές

• Σύνθεση συμβολοσειρών:
string str1 = “try me ”;
string str2 = “now”;
string str3 = str1 + str2; // str3: “try me now”
str1.append(str2); // str1: “try me now”
srt1 += “ again”; // (append) “try me now again”

• Πρόσβαση σε χαρακτήρες:
cout << str3[2] << endl; // διάβασμα του 3ου χαρ.: ‘y’
str3[4] = 'i'; // αντικατάσταση του 5ου χαρ.
str3[5] = 't'; // αντικατάσταση του 6ου χαρ.
cout << str3 << endl; // “try it now”

8
Συμβολοσειρές

• Σύγκριση συμβολοσειρών:
string str1 = “Android”;

string str2 = “Androids”;

bool _2gt1 = str1 < str2; // _2gt1 == true

str1 = “Android4.2”;

str2 = “Android3.2”;

_2gt1 = str1 < str2; // _2gt1 == false

str1 = “Andro”; Ο έλεγχος γίνεται λεξικογραφικά. Το


αποτέλεσμα ισοδυναμεί με τη σύγκριση των
str2 = “Andras”; πρώτων από αριστερά ανόμοιων χαρακτήρων

_2gt1 = str1 < str2; // _2gt1 == false

9
Συμβολοσειρές

• Εύρεση sub-string:
2 16
string str1 = "I am a healthy camel";

string str2 = "am";

size_t pos = str1.find(str2); // pos == 2

pos = str1.find(str2, pos+1); // pos == 16

10
Συμβολοσειρές

string to_string (int val);

string to_string (long val);

string to_string (long long val);

string to_string (unsigned val);

string to_string (unsigned long val);

string to_string (unsigned long long val);

string to_string (float val);

string to_string (double val);

string to_string (long double val);

11
Συμβολοσειρές

int stoi (const string& str, size_t* idx = 0, int base = 10);

long stol (const string& str, size_t* idx = 0, int base = 10);

unsigned long stoul (const string& str, size_t* idx = 0, int


base = 10);

long long stoll (const string& str, size_t* idx = 0, int base =
10);

unsigned long long stoull (const string& str, size_t* idx = 0,


int base = 10);

float stof (const string& str, size_t* idx = 0);

double stod (const string& str, size_t* idx = 0);

long double stold (const string& str, size_t* idx = 0);

12
Συμβολοσειρές

• Για να υποστηρίξουμε Ελληνικά σε οποιαδήποτε


γλώσσα προγραμματισμού, έχουμε τις ακόλουθες
επιλογές, ανάλογα και με το λειτουργικό σύστημα:
– «Ελληνική» κωδικοποίηση του (7-bit) ASCII, όπως για
παράδειγμα η ISO8859-7
– Χρήση Unicode κωδικοποίησης (8- και 16-bit): UTF-8, UTF-16
• Στο Linux, υποστηρίζεται UTF-8 εγγενώς
– Χρήση “wide characters” (wchar_t). Στα Windows έχουμε 16-
bit wide characters (UTF-16) ενώ στο Linux έχουμε 32-bit
«μεγάλους» χαρακτήρες

13
Συμβολοσειρές

• Αν επιχειρήσουμε να τυπώσουμε Ελληνικό κείμενο


απευθείας, θα τυπωθεί πιθανότατα σε λάθος
κωδικοποίηση (χρησιμοποιείται η default
κωδικοποίηση της C++ “C”)
• Λύση 1: Αλλάζουμε την κωδικοποίηση σε Ελληνικό
locale (με την προϋπόθεση ότι το System Locale είναι
Ελληνικό!):
string str2 = "Ελληνικά";

setlocale(LC_ALL,"Greek");

cout << str2;

14
Συμβολοσειρές

• Λύση 2: Χρησιμοποιούμε μεγάλους χαρακτήρες


(UTF16).
• Για τους μεγάλους χαρακτήρες (wchar_t αντί για char),
υπάρχουν οι αντίστοιχες “w” (wide) δηλώσεις:
– wstring αντί για string
– wcout αντί για cout κλπ
• Τα σταθερά strings δηλώνονται λίγο διαφορετικό
τρόπο:
wstring mystring = L”Καλημέρα”;

15
Συμβολοσειρές

wstring str1 (L"Ελληνικά"); Δεν τυπώνονται σωστά τα Ελληνικά από την


κλάση wstring στο output stream
wcout << str1 << endl;
_cputws(str1.c_str()); Χρήση της C συνάρτησης εξόδου του string:
Σωστή κωδικοποίηση

Κατασκευάζουμε έναν πίνακα από wide


• Διάβασμα από την κονσόλα: characters
Δηλώνουμε στην πρώτη θέση του πίνακα τον
wchar_t buffer [100] = {97}; μέγιστο αριθμό χαρακτήρων που επιτρέπεται να
διαβάσουμε
_cgetws(buffer);
Χρησιμοποιούμε την αντίστοιχη συνάρτηση
_cputws(buffer); εισόδου συμβολοσειρών μεγάλων χαρακτήρων
wstring str2(buffer); της C

16
Συμβολοσειρές

• Σε όλες τις τυπικές εγκαταστάσεις Linux,


χρησιμοποιείται κωδικοποίηση UTF8, οπότε δε
χρειάζεται να χρησιμοποιηθεί wide string
• Εφόσον το αρχείο που έχουμε γράψει τον κώδικα ή το
αρχείο από το οποίο διαβάζουμε συμβολοσειρές είναι
σε κωδικοποίηση UTF8, τυπώνονται κανονικά οι
χαρακτήρες

17
Συμβολοσειρές

• Η κλάση string είναι της C++ (η C δεν είναι


αντικειμενοστρεφής)
• Όμως, η C παρέχει ένα μεγάλο εύρος συναρτήσεων για
πίνακες χαρακτήρων
• Πολύ βασικές συναρτήσεις για μορφοποιημένη είσοδο
και έξοδο συμβολοσειρών:
– printf, sprintf
– scanf, sscanf

18
Συμβολοσειρές

• Τυπώνει παραμετρικό μορφοποιημένο κείμενο


• Παίρνει ως είσοδο μια συμβολοσειρά μορφοποίησης
και ένα πλήθος παραμέτρων που «κουμπώνουν» σε
κατάλληλες θέσεις μέσα σε αυτή
• Παράδειγμα:
int hits = 33;
long total = 1000;
printf( “We scored %d out of %ld points.\nThis is %.2f%%.\n”,
hits, total, 100.f*hits/(float)total );

Τυπώνει:
We scored 33 out of 1000 points.
This is 3.30%.
19
Συμβολοσειρές

Θέση 1 Θέση 2 Θέση 3


printf( “We scored %d out of %ld points.\nThis is %.2f%%.\n”,

hits, total, 100.f*hits/(float)total );


Παράμετρος 1 Παράμετρος 2 Παράμετρος 3

• % : δηλώνει ότι ακολουθεί εκτύπωση παραμέτρου


• %d : εκτυπώνει δεκαδικό αριθμό (decimal)
• %ld: εκτυπώνει «μεγάλο» δεκαδικό (long decimal)
• %f: εκτυπώνει float (και double)
• … Πλήρης λίστα: http://www.cplusplus.com/reference/cstdio/printf/
• %%: δηλώνει την εμφάνιση του χαρακτήρα %
• %.2f: Θέλουμε να εμφανίζει 2 δεκαδικά ψηφία
20
Συμβολοσειρές

• Διαβάζει μορφοποιημένα δεδομένα από το ρεύμα εισόδου


και περνάει σε μεταβλητές τα ορίσματα που εμφανίζονται
στις θέσεις που υποδεικνύουμε
• Είναι ουσιαστικά η αντίθετη της printf
char name[80];
int age;
int read = scanf (“name: %s, %d ",name, &age);

• Αν αποτύχει η ανάγνωση γιατί η συμβολοσειρά εισόδου δεν


ταιριάζει στο μορφότυπο που δώσαμε, επιστρέφει αμέσως
• Η τιμή επιστροφής είναι ο αριθμός των παραμέτρων που
διαβάστηκαν ορθά
21
Συμβολοσειρές

#define STATUS_CODE_PARSING -1
#define STATUS_CODE_OK 0
int parseVec2(float *v, char * text) {
if (!text)
return STATUS_CODE_PARSING;
if ( scanf(text, "\(%f%*[ ,\t]%f\)", &(v[0]), &(v[1])) < 2 )
return STATUS_CODE_PARSING;
else
return STATUS_CODE_OK;
}

22
Συμβολοσειρές

scanf(text, "\(%f%*[ ,\t]%f\)", &(v[0]), &(v[1]))

\( , \) : Ειδικοί χαρακτήρες ‘(’ ‘)’


%f : διάβασμα αριθμού κινητής υποδιαστολής
%*… : διάβασε και αγνόησε (μην αποθηκεύσεις κάπου) την επόμενη
τιμή
%[…] : διάβασε έναν ή περισσότερους από τους χαρακτήρες μέσα
στις αγκύλες
Ενδεικτικές έγκυρες είσοδοι:
(0.04 1.3)
(200, 40.45)
( 1.4 50)
(-200, 50)
23
Συμβολοσειρές

• Χρήσιμες συναρτήσεις για μορφοποιημένη έξοδο και


είσοδο σε/από πίνακες χαρακτήρων
• Χρήσιμες για εύκολη επεξεργασία συμβολοσειρών (π.χ.
parsing γραμμών κειμένου από αρχεία)
• Έχουν ένα παραπάνω όρισμα (το πρώτο), τον πίνακα
χαρακτήρων εισόδου ή εξόδου (δείτε τον οδηγό
αναφοράς για περισσότερες πληροφορίες)

24

You might also like