Transcript Programozási Nyelvek (C++) Gyakorlat Gyak 03.
Programozási Nyelvek (C++) Gyakorlat
Gyak 03.
Török Márk [email protected]
D-2.620
1
Kódelemzés
• Feladat: Olvassunk be betüket a sabványos bemenetről (a – z), és írjuk ki a nagybetűs párjukat (A – Z).
Különleges karakterek, nagybetűk helyben maradnak, angol abc-vel dolgozunk.
Tömbök
Konstansokról
• Nézzünk egy példát: – strlen implementálása: int { strlen( char * s ) char while *p = s; ( *p != '0' { ) ++p; } // hello world0, előre zavarom a p-t.
return p - s; // két pointer különbsége az adott szó hossza.
} 4
Konstansokról
• Mi van akkor, ha: int { strlen( char * s ) char while *p = s; ( *p = '0' { ++p; } return p - s; } ) // hiba lehetőség!
5
Konstansokról
} • Javítsuk: int { strlen( const char * s ) const char while *p = s; ( *p = '0' // csak együtt lehetnek!
) // így már szemantikai hiba!
{ ++p; } return p - s; 6
Kódelemzés
• Áttekintés: – Kezdjünk egyből C++-vel!
– Ha egy C++ programot írunk, érdemes a biztonságra törekedni.
• Azaz, kerüljük, hogy egyszerre megírjuk az egészet, és csak utána fordítunk!
• Részenként kell csinálni! (és úgy fordítani!) – Ezek a lépések: 1.
2.
3.
Elso lépésként megnézzük, hogy a stdinputot másolja át a stdoutputra!
Második lépésként nézzük meg, hogy felismerie a kisbetűt.
Majd harmadik lépésként alakítsuk a felismert kisbetűket nagybetűssé!
Kódelemzés
#include
Kódelemzés
•Megoldás: #include using
Kódelemzés
• Fordul! Yeehaaa!
• Kisbetűk felismerése a feladat!
Kódelemzés
#include
Kódelemzés
• #1 Kérdés: Működik-e char-ok között a <= operator? Mivel mindegyik int-re konvertálódik, így az ascii kódok között történik meg a <= vizsgálat!
• #2 Kérdés: Hogyan konvertáljuk a karaktereket nagybetűvé?
Mivel ascii-val dolgozunk, ezért ch + 'A' - 'a'
Kódelemzés
• int-ek kerülnek kiírásra, mivel a + és - szintén nincs értelmezve a char-ok között!
• ascii kód íródik ki, ahelyett, hogy char érték íródott volna ki!
Kódelemzés
#include
Kódelemzés
• Mi történt?
– A kiértékelés miatt precedenciaproblémák vannak!
Kódelemzés
#include
Kódelemzés
• Továbbra is számok íródnak ki! Meglepő módon most már a betűk helyett is számok íródnak ki!
• T1 T2 ==> T • Fordítási időben meg kell mondania, hogy melyik kiíró operátort válassza meg! A fordítónak fordítás alatt tudnia kell, hogy milyen a kifejezés típusa!
• Itt: int op char => int
Kódelemzés
• Promotion rules: – short, char => int – float => double – double => long double • Odafelé jól mentek a dolgok, maguktól mentek a konverziók!
• Visszafelé már nem!
Kódelemzés
• Megoldások: – char(i), ha i : integer, akkor i-t char-ra konvertáljuk.
– static_cast
Kódelemzés
#include
Kódelemzés
• Más lehetőség: – Saját toupper metódus írása!
• Amit egyszer már megírtak, azt ne írjuk meg mégegyszer!
– Beépített toupper metódus használata
Kódelemzés
• Írjunk olyan utility-t, ami úgy működik, mint egy unixparancs.
• Ha nem adunk paramétert, akkor stdinput /outputot használja, ha adunk paramétert, akkor azt, mint fájlt akarja használni!
Kódelemzés
#include
}
Kódelemzés
#include
Kódelemzés
• Akár van fájl, akár nincs, ugyanazt csinálom, ezzel megóvom magamat a dupla munkától!
• az istream, ostream osztályoknak a copyconstruktora private, hogy ne lehessen másolni, így mindig referencia szerint adom át öket paraméternek.
Kódelemzés
#include #include
} return 0 ; }
Kódelemzés
for { ( int i= 1 ; i < argc; ++i ) // Meg kell nyitni a fájlt! ifstream inp(argv[i]); if { ( !inp ) std::cerr << "Can't open" } else { toupper(inp, std::cout); } << argv[i] << std::endl; }
Kódelemzés
• Kérdés: Kell-e close-t mondanom?
– Amikor a zárójelet becsukom, akkor az ifstream destruktora meghívódik!
Kódelemzés
• Feladat: Számoljuk meg, hogy a bemeneten hány sor volt. (Sorvége-jel: ‘\n’)
Kódelemzés
#include #include
} return 0 ; }
Kódelemzés
for { ( int i= 1 ; i < argc; ++i ) ifstream inp(argv[i]); if ( !inp ) { std::cerr << "Can't open" << argv[i] << std::endl; } else { lines(inp, std::cout); } }
Kódelemzés
• Egy adott karakter előfordulása egy egyszerű számlálás!
Kódelemzés
void { lines( std::istream& inp, std::ostream& outp ) int char cnt = 0 ; prev = '\n' ; char while curr; ( std::cin.get(curr) ) { cnt = f(cnt, prev, curr); prev = curr; } }
Kódelemzés
int { f( int cnt, char prev, char if { ( '\n' == prev ) ++cnt; } return cnt; } curr ) // warning!
Kódelemzés
int { f( int cnt, char prev, char if { ( '\n' == prev ) ++cnt; } return cnt; } ) // így már nem!
Kódelemzés
} • Javítás: void { lines( std::istream& inp, std::ostream& outp ) int char cnt = 0 ; prev = '\n' ; char while curr; ( std::cin.get(curr) ) { cnt += '\n' == prev; prev = curr; }
Kódelemzés
•Megoldás: #include
Kódelemzés
•Megoldás: más út #include
Kódelemzés
• Kimenet: alma szilva ctrl-D eredmény: 2 alma szilva ctrl-D eredmény: 1
Kódelemzés
• Feladat: Írjuk át úgy a programot, hogy ne az ‘\n’ karaktereket keressük, mert az utóbbi esetben hibás a végrehajtás.
Kódelemzés
•Megoldás: int f ( char { return } prev, int prev == ls) ‘\n’ ? ls + 1 : ls; char while c, prev; ( std::cin >> std::noskipws >> c) { ls = f(prev, ls); prev = c; }
Kódelemzés
• Feladat: Szavak számának a számolása.
alma (1) „ „ szilva (2) …
Kódelemzés
•Megoldás: int { f ( char prev, char c, int ls) return ( prev == ‘\n’ && c != ‘\n’ || prev == && c != ‘\t’ ‘\t’ || prev == && c != ‘ ’ ‘ ‘ ? ls + ) 1 : ls; }
Kódelemzés
•Megoldás: Más út bool { isWS( char c) … }