Rad sa stringovima i klasa string Nekoliko primjera iz C jezika - FESB

Rad sa stringovima i klasa string Nekoliko primjera iz C jezika - FESB Rad sa stringovima i klasa string Nekoliko primjera iz C jezika - FESB

13.07.2015 Views

Rad sa stringovima i klasa stringDva su pristupa:• rad s ASCIIZ stringovima pomoću funkcija C-biblioteke• korištenje klase string iz C++ bibliotekeOvaj drugi način je znatno jednostavniji.Nekoliko primjera iz C jezikaProgram: Miješanje karatastr_lik[]As\02\03\04\0Kralj\0Slika 7.1 Niz pokazivačachar *str_boja[4] = {"Srce", "Tref", "Karo", "Pik "};char *str_lik[13] = {"As", "2", "3", "4", "5", "6", "7", "8", "9", "10","Jack", "Dama", "Kralj" };1

<strong>Rad</strong> <strong>sa</strong> <strong><strong>string</strong>ovima</strong> i kla<strong>sa</strong> <strong>string</strong>Dva su pristupa:• rad s ASCIIZ <strong><strong>string</strong>ovima</strong> pomoću funkcija C-biblioteke• korištenje klase <strong>string</strong> <strong>iz</strong> C++ bibliotekeOvaj drugi način je znatno jednostavniji.<strong>Nekoliko</strong> <strong>primjera</strong> <strong>iz</strong> C <strong>jezika</strong>Program: Miješanje karatastr_lik[]As\02\03\04\0Kralj\0Slika 7.1 N<strong>iz</strong> pokazivačachar *str_boja[4] = {"Srce", "Tref", "Karo", "Pik "};char *str_lik[13] = {"As", "2", "3", "4", "5", "6", "7", "8", "9", "10","Jack", "Dama", "Kralj" };1


Datoteka: karte1.cpp – dijeljenje karatachar *str_boja[4] = {"Srce", "Tref", "Karo", "Pik "};char *str_lik[13] = {"As", "2", "3", "4", "5","6", "7", "8", "9", "10", "Jack", "Dama", "Kralj" };#define BROJ_KARATA 52int main( void){int i, karte[BROJ_KARATA];}// poredaj po redufor (i = 0; i < BROJ_KARATA; i++)karte[i] = i;// <strong>iz</strong>mije<strong>sa</strong>j zamjenom vrijednostifor (i = 0; i < BROJ_KARATA; i++){int k = rand() % BROJ_KARATA;int tmp = karte[i]; // swapkarte[i] = karte[k];karte[k] = tmp;}// ispisifor (i = 0; i < 52; i++){cout


Kontenjer za n<strong>iz</strong> <strong>string</strong>ova promjenljive duljineconst int s<strong>iz</strong>eincr=5;typedef char * c<strong>string</strong>;char **txttxt[i]Helloclass CStrArray{private :c<strong>string</strong> *str_arr ;int num<strong>string</strong>s;int maxs<strong>iz</strong>e;World!je pr vi C programpublic:CStrArray () : num<strong>string</strong>s(0),maxs<strong>iz</strong>e(s<strong>iz</strong>eincr){str_arr = new c<strong>string</strong>[s<strong>iz</strong>eincr]; }~CStrArray ();// dopišite kopirni konstruktor i operator =int Num<strong>string</strong>s () const{return num<strong>string</strong>s;}void AddString(c<strong>string</strong> s) ;//...c<strong>string</strong> operator [] (int index){ return str_arr [index];}const c<strong>string</strong> operator [] (int index) const{ return str_arr [index];}};3


Kla<strong>sa</strong> CStrArray enkapsulira rad s n<strong>iz</strong>om ASCIIZ <strong>string</strong>ova.void CStrArray::AddString(c<strong>string</strong> s){if(num<strong>string</strong>s >= maxs<strong>iz</strong>e){ // ako je num<strong>string</strong>s veći od broja alociranih pok.//allociraj novi n<strong>iz</strong> uvećan za s<strong>iz</strong>eincrc<strong>string</strong> * p= new c<strong>string</strong>[maxs<strong>iz</strong>e+s<strong>iz</strong>eincr];//kopiraj stari u novimemcpy(p,str_arr , maxs<strong>iz</strong>e*s<strong>iz</strong>eof(c<strong>string</strong> ));}delete [] str_arr ; // dealociraj stari n<strong>iz</strong> pok.str_arr = p; // novi pridijeli staromemaxs<strong>iz</strong>e += s<strong>iz</strong>eincr;}str_arr[num<strong>string</strong>s]=s;num<strong>string</strong>s++;CStrArray::~CStrArray (){for(int i = 0; i < num<strong>string</strong>s; i++ )delete [] str_arr[i];delete [] str_arr;}// Zadatak:// dopišite kopirni konstruktor i operator =4


int main( void ){CStrArray txt;char str[256]={"\0"}; // radni <strong>string</strong>// Kraj uno<strong>sa</strong> je ako se unese prazna linija.while(true){cin.getline(str,255); // dobavi <strong>string</strong> u strint len=strlen(str); // odredi duljinu strif(len==0) // ako je prazan <strong>string</strong> prekinibreak; // inače, ako je unos ispravanchar *s = new char[len+1]; // formiraj novi <strong>string</strong>strcpy(s, str); // kopiraj radni <strong>string</strong> u njegatxt.AddString(s); // i pridjeli ga n<strong>iz</strong>u <strong>string</strong>ova}cout


11.2 Argumenti komandle linije operativnog sustavaFunkcija "main" također može koristiti argumente. Ovoj funkciji argumente proslijeđuje operativnisustav s komandne linije. Primjerice, pri pozivu kompajlerac:>cl /GX cards.cpp<strong>iz</strong> komandne linije se kao argumenti u funkciju main() prenose dva <strong>string</strong>a: /GX i cards.cpp.Opći oblik deklaracije funkcije main, koja prima argumente s komandne linije, glasi:int main( int argc, char *argv[])Parametri su:argc <strong>sa</strong>drži broj argumenata. Prvi argument (indek<strong>sa</strong> nula) je prema standardu uvijek ime <strong>sa</strong>mogprograma, dakle broj argumenata je uvijek veći ili jednak 1.argv je n<strong>iz</strong> pokazivača na char, svaki pokazuje na početni znak <strong>string</strong>ova koji su u komandnoj linijiodvojeni razmakom.6


Primjer 1: program koji ispisuje <strong>sa</strong>držaj komandne linije operativnog sustava// Datoteka: cmdline.cpp#include using namespace std;int main( int argc, char *argv[]){int i;cout


11.3 String kla<strong>sa</strong><strong>Rad</strong> s ASCIIZ <strong><strong>string</strong>ovima</strong> ima mnoge nedostatke:• ASCIIZ <strong>string</strong>ovi nemaju karakter tipa podatka,• sve radnje s njima mora obavljati <strong>sa</strong>m programer koristeći funkcije biblioteke,• te radnje se često zasnivaju na korištenju pokazivača i dinamičkog alociranja memorije, što jeuzrok mnogim greškama.U C++ jeziku standard<strong>iz</strong>irana je kla<strong>sa</strong> <strong>string</strong> pomoću koje se može obaviti gotovo sve što je potrebnou radu s n<strong>iz</strong>ovima znakova. Detaljna specifikacija ove klase s primjerima primjene opi<strong>sa</strong>na je uDodatku D.Pokazat ćemo kako je real<strong>iz</strong>irana kla<strong>sa</strong> TString koja <strong>sa</strong>drži podskup operacija standardne klase<strong>string</strong>. Kla<strong>sa</strong> TString je neznatno modificirana ap<strong>string</strong> kla<strong>sa</strong>, koja je preporučena za nastavu odameričkog College Boarda - Advance Placement Course of Computer Science.Primjer upotrebe TString (<strong>string</strong>) klaseIspis:#include #include "TString.h"#include "TString.cpp"using namespace std;int main(){TString s = "Hello";8


dodaj znak ','s += ',';// ispiši <strong>string</strong>cout


zamijeni veliko u malo slovoif(idx != TString::npos)s[idx] = tolower(s[idx]);cout


class TString // u std biblioteci ime: <strong>string</strong>{int m_length; // duljina <strong>string</strong>a (broj znakova)int m_capacity; // kapacitet <strong>string</strong>a - u bajtimachar * m_cstr; // pokativač na ASCIIZ <strong>string</strong>public:static const int npos; // not a position (-1)// konstruktori/destruktorTString( ); // konstruktor praznog <strong>string</strong>a ""TString( const char * s ); // konstruktor <strong>iz</strong> literalnog str.TString( const TString & str ); // kopirni konstruktor~TString( ); // destruktor// pridjela vrijednosticonst TString & operator = ( const TString & str );const TString & operator = ( const char * s ); const TString &operator = ( char ch );// pristupniciint length( )const {return m_length;} // broj znakovaint s<strong>iz</strong>e( )const {return m_length;} // broj znakova11


traženje u <strong>string</strong>u//vraća indeks pojave <strong>string</strong>a str u <strong>string</strong>u thisint find( const TString & str ) const;//indeks pojave znaka chint find( char ch ) const;//sub<strong>string</strong> duljine len od pozicije posTString substr( int pos, int len ) const;// pretvorba u char *const char* c_str( ) const {return m_cstr;}// pretvorba u char *operator char* ( ) const {return m_cstr;}// indeksirani pristupchar operator[ ]( int k ) const;char & operator[ ]( int k );// mutatori - dopuna <strong>string</strong>a <strong>string</strong>om str i znakom chconst TString & operator += ( const TString & str );const TString & operator += ( char ch );};12


Nečlanske funkcije//// ulazni/<strong>iz</strong>lazne operacijeostream & operator > ( istream & is, TString & str );istream & getline( istream & is, TString & str );// relacijski operatori:bool operator == (const TString & lhs, const TString & rhs);bool operator != (const TString & lhs, const TString & rhs);bool operator < (const TString & lhs, const TString & rhs);bool operator (const TString & lhs, const TString & rhs);bool operator >= (const TString & lhs, const TString & rhs);// operator + (dopuna <strong>string</strong>a)TString operator+ (const TString& lhs, const TString& rhs );TString operator+ (char ch, const TString & str);TString operator+ (const TString & str, char ch );IMPLEMENTACIJA je dana u skriptiPrikažimo <strong>sa</strong>mo neke funkcije:13


#include #include #include #include #include "TString.h"const int TString::npos = -1;TString::TString()// POST: <strong>string</strong> je prazan{m_length = 0;m_capacity = 1;m_cstr = new char[m_capacity];m_cstr[0] = '\0'; // c<strong>string</strong> nulte duljine}TString::TString(const char * s)// Opis: konstruktor <strong>iz</strong> literalnog <strong>string</strong>a, pr. "abcd"// PRE: s je '\0'-terminirani ASCIIZ <strong>string</strong>// POST: formira se kopija od s{assert (s != 0); // provjera: c<strong>string</strong> not NULL?m_length = strlen(s);m_capacity = m_length + 1; // dodaj bajt za '\0'm_cstr = new char[m_capacity];strcpy(m_cstr,s);}TString::~TString()// POST: dealocira se <strong>string</strong>{ delete[] m_cstr; // dealociraj memoriju}14


const TString& TString::operator =(const TString & rhs)// POST: pridjela kopiranjem <strong>string</strong> objekta{if (this != &rhs) // provjeri da li je{ // s=s;if (m_capacity < rhs.length()+1) // procijeni da li treba{ // povećati memorijudelete[] m_cstr; // dealociraj stari <strong>string</strong>m_capacity = rhs.length() + 1;// dodaj 1 bajt za '\0'm_cstr = new char[m_capacity];}m_length = rhs.length();strcpy(m_cstr,rhs.m_cstr);}return *this;}char& TString::operator[](int k)// PRE: 0


ostream& operator > ch; // dobavi prvi ne-bijeli znak chif (! is.fail()) {do{str += ch;is.get(ch);} while (! is.fail() && ! isspace(ch));}if (isspace(ch)) // vrati razmak u streamis.putback(ch);}return is;istream & getline(istream & is, TString & str)// Opis: dobavlja liniju teksta <strong>iz</strong> ulaznog toka u <strong>string</strong> str// PRE: ulazni tok je otvoren// POST: više znakova zaključno s '\n' se očitava s ulaza// i sprema u str ('\n' se ne sprema u str){char ch;16


}str = "";while (is.get(ch) && ch != '\n') {str += ch;}return is;const TString& TString::operator +=(const TString & str)// POST: dodaje kopiju str <strong>string</strong>a na kraj this <strong>string</strong>a{TString copy<strong>string</strong>(str); // napravi kopiju <strong>string</strong>aint newLength = length() + str.length(); // procijeni duljinuint lastLocation = length(); // položaj '\0' znaka// provjeri da li treba povećati memorijuif (newLength >= m_capacity){m_capacity = newLength + 1;if (str.length() == 1) {m_capacity *= 2;}char * newBuffer = new char[m_capacity];strcpy(newBuffer,m_cstr); // kopiraj u novi bufferdelete [] m_cstr; // dealociraj stari <strong>string</strong>m_cstr = newBuffer;}// <strong>sa</strong>da dodaj str (copy<strong>string</strong>) na kraj od m_cstrstrcpy(m_cstr+lastLocation, copy<strong>string</strong>.c_str() );m_length = newLength; // upiši novu duljinu <strong>string</strong>a}return *this;17


const TString & TString::operator += ( char ch )// POST: dodaje znak ch na kraj this <strong>string</strong>a{ TString temp; // napravi <strong>string</strong> koj <strong>sa</strong>drži znak chtemp = ch;*this += temp;return *this;}TString operator +(const TString & lhs, const TString & rhs)// POST: vraća <strong>string</strong> koji se <strong>sa</strong>stoji od lhs dopunjenog s rhs{TString result(lhs); // kopira lhs u resultresult += rhs; // dopunjuje rhsreturn result; // vraća result}TString operator + ( char ch, const TString & str )// POST: vraća <strong>string</strong> koji se <strong>sa</strong>stoji znaka ch i <strong>string</strong>a str{ TString result; // napravi <strong>string</strong> koj <strong>sa</strong>drži znak chresult = ch;result += str;return result;}TString operator + ( const TString & str, char ch )// POST: vraća <strong>string</strong> koji se <strong>sa</strong>stoji str dopunjenog znakom ch{TString result(str);result += ch;return result;}18


TString TString::substr(int pos, int len) const// Opis: vraća sub<strong>string</strong> duljine len počevši od indek<strong>sa</strong> pos// PRE: this <strong>string</strong> <strong>sa</strong>drži c0, c1, ..., c(n-1), uz uvjet// 0 = m_length) // budi unutar <strong>string</strong>a?{lastIndex = m_length-1;}}TString result(*this); // alociraj dovoljno memorijeint j,k;for(j=0,k=pos; k


int TString::find(const TString & str) const// Opis: pronalazi pojavu <strong>string</strong>a str u this <strong>string</strong>u// i vraća indeks prvog znaka. Ako this <strong>string</strong> ne// <strong>sa</strong>drži <strong>string</strong> str, tada vraća npos.// PRE: this <strong>string</strong> <strong>sa</strong>drži c0, c1, ..., c(n-1)// str <strong>sa</strong>drži s0, s1, ...,s(m-1)// POST: ako je s0 == ck0, s1 == ck1, ..., s(m-1) == ck(m-1)// i ako ne postoji j < k0 takovi da je// s0 = cj, ...., sm == c(j+m-1),// tada vraća k0;// u suprotnonm slučaju vraća npos{int len = str.length();int lastIndex = length() - len;for(int k=0; k


ool operator == ( const TString & lhs, const TString & rhs ){return strcmp(lhs.c_str(), rhs.c_str()) == 0;}bool operator != ( const TString & lhs, const TString & rhs ){return ! (lhs == rhs);}bool operator < ( const TString & lhs, const TString & rhs ){return strcmp(lhs.c_str(), rhs.c_str()) < 0;}bool operator ( const TString & lhs, const TString & rhs ){return rhs < lhs;}bool operator >= ( const TString & lhs, const TString & rhs ){return ! ( lhs < rhs );}21


Primjer programa karte2.cpp pomoću klase TString#include #include "t<strong>string</strong>.h"#include "TString.cpp"#include // deklaracija rand()TString boja[] = {"Srce", "Tref", "Karo", "Pik "};TString lik[] = {"As", "2", "3", "4", "5","6", "7", "8", "9", "10","Jack", "Dama", "Kralj" };// Sve ostalo prepiši <strong>iz</strong> programa karte.cpp u kojem smo// koristili ASCIIZ <strong>string</strong>oveKlasom <strong>string</strong> možemo u mnogo slučajeva zamijeniti ASCIIZ objekte.Što time dobijamo?• Dobijamo na sigurnosti, jer se smanjuje mogućnost nedozvoljenog pristupa memoriji.• Često dobijemo kraće i elegantnije napi<strong>sa</strong>ne programe, iako s nešto duljim vremenom <strong>iz</strong>vršenja.To ćemo demostrirati tako da pomoću klase <strong>string</strong> ponovo napišemo klasu za rad s n<strong>iz</strong>om <strong>string</strong>ovaCStrArray.// program strarray2.cpp#include #include #include // standardna kla<strong>sa</strong> <strong>string</strong>using namespace std;const int s<strong>iz</strong>eincr=5;22


class CStrArray{private :<strong>string</strong> *str_arr ; // n<strong>iz</strong> <strong>string</strong>ovaint num<strong>string</strong>s;int maxs<strong>iz</strong>e;public:CStrArray () : num<strong>string</strong>s(0), maxs<strong>iz</strong>e(s<strong>iz</strong>eincr){str_arr = new <strong>string</strong>[s<strong>iz</strong>eincr]; }~CStrArray ();int Num<strong>string</strong>s () const {return num<strong>string</strong>s;}void AddString(<strong>string</strong> s) ;//...<strong>string</strong>& operator [] (int index) { return str_arr [index];}const <strong>string</strong>& operator [] (int index) const { return str_arr [index];}};void CStrArray::AddString(<strong>string</strong> s){if(num<strong>string</strong>s >= maxs<strong>iz</strong>e){ // ako je num<strong>string</strong>s veći od broja alociranih pok.//allociraj novi n<strong>iz</strong> pok.<strong>string</strong> * p= new <strong>string</strong>[maxs<strong>iz</strong>e+s<strong>iz</strong>eincr];for(int i=0; i


CStrArray::~CStrArray (){delete [] str_arr;}int main( void ){CStrArray txt;<strong>string</strong> str; // radni <strong>string</strong>// Kraj uno<strong>sa</strong> je ako se unese prazna linija ili EOFwhile(getline(cin, str)){if(str.length()==0) // ako je prazan <strong>string</strong>break; // prekini unos teksta// ako je unos ispravantxt.AddString(str); // i pridjeli ga n<strong>iz</strong>u}cout


11.4 Stringovni tokoviU standardnoj iostream biblioteci implementirane su klasei<strong>string</strong>stream, o<strong>string</strong>stream i <strong>string</strong>stream.One omogućuje da se i objekti standardne klase <strong>string</strong> tretiraju <strong>iz</strong>vor ili odredište ulazno/<strong>iz</strong>laznih tokova. Njih semože koristiti tako da se deklarira zaglavlje .11.4.1. Izlazni <strong>string</strong>ovni toko<strong>string</strong>steream ostr;takovom objektu možemo pristupiti kao i bilo kojem drugom ostream toku:int n = 2345;ostr


11.4.1. Ulazni <strong>string</strong>ovni tokUlazni <strong>string</strong>ovni tok se formira kao objekt klase i<strong>string</strong>stream koja naslijeđuje istream.Članske funkcije su:i<strong>string</strong>stream::i<strong>string</strong>stream();i<strong>string</strong>stream::i<strong>string</strong>stream (<strong>string</strong> const &text);void i<strong>string</strong>stream::str(<strong>string</strong> const &text);Izlazni <strong>string</strong>ovni tok se uvijek prije upotrebe mora ispuniti nekim tekstualnim <strong>sa</strong>držajem.Primjerice,i<strong>string</strong>stream istr("55 678 921");Kada je tok ispunjen, <strong>iz</strong> njega se može vršiti ekstrakcija numeričkih i <strong>string</strong>ovnih tipova pomoću operatora i funkcijaekstrakcije. Primjerice, <strong>iz</strong> ovog toka može se dobaviti vrijednost tri cjelobrojne varijable <strong>sa</strong>int x, y, z;istr >> x >> y >> z;Uočite da će se petljom;ispi<strong>sa</strong>ti:int x;while ( istr >> x)cout

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!