Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Programozási Nyelvek (C++) Gyakorlat Gyak 03.

Hasonló előadás


Az előadások a következő témára: "Programozási Nyelvek (C++) Gyakorlat Gyak 03."— Előadás másolata:

1 Programozási Nyelvek (C++) Gyakorlat Gyak 03.
Török Márk D-2.620 1

2 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.

3 Tömbök

4 Konstansokról Nézzünk egy példát: strlen implementálása:
int strlen( char* s ) { char *p = s; while ( *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. }

5 Konstansokról Mi van akkor, ha: int strlen( char* s ) { char *p = s;
while ( *p = '0' ) // hiba lehetőség! ++p; } return p - s;

6 Konstansokról Javítsuk: int strlen( const char* s ) {
const char *p = s; // csak együtt lehetnek! while ( *p = '0' ) // így már szemantikai hiba! ++p; } return p - s;

7 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: 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é!

8 Kódelemzés #include <iostream> int main() { char ch; std::cin >> std::ios_base::noskipws; while ( std::cin >> ch ) std::cout << ch; } return 0;

9 Kódelemzés Megoldás: #include <iostream> using namespace std; int main() { char ch; while (cin >> noskipws >> ch) { cout << …(???) } } noskipws: io-manipulátor, nem ugorja át a whitespaceket (space, tab,…), ennek testvére a skipws, mely átugorja azokat.

10 Kódelemzés Fordul! Yeehaaa! Kisbetűk felismerése a feladat!

11 Kódelemzés #include <iostream> int main() { char ch; std::cin >> std::ios_base::noskipws; while ( std::cin >> ch ) if ( 'a' <= ch && ch <= 'z') // #1 std::cout << ch + 'A' - 'a'; // #2 } else std::cout << ch; return 0;

12 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'

13 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!

14 Kódelemzés #include <iostream> int main() { char ch; std::cin >> std::ios_base::noskipws; while ( std::cin >> ch ) std::count << 'a' <= ch && ch <= 'z' ? ch - 'a' + 'A' : ch; } return 0;

15 Kódelemzés Mi történt? A kiértékelés miatt precedenciaproblémák vannak!

16 Kódelemzés #include <iostream> int main() { char ch; std::cin >> std::ios_base::noskipws; while ( std::cin >> ch ) std::count << ('a' <= ch && ch <= 'z' ? ch - 'a' + 'A' : ch); } return 0;

17 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

18 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!

19 Kódelemzés Megoldások:
char(i), ha i : integer, akkor i-t char-ra konvertáljuk. static_cast<char>(i) (Később) char ch = i;

20 Kódelemzés #include <iostream> int main() { char ch; std::cin >> std::ios_base::noskipws; while ( std::cin >> ch ) std::count << char('a' <= ch && ch <= 'z' ? ch - 'a' + 'A' : ch); } return 0;

21 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

22 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!

23 Kódelemzés #include <iostream> int main(int argc; char *argv[]) { ... }

24 Kódelemzés #include <iostream> void toupper(std::istream&, std::ostream&); int main( int argc; char *argv[] ) { if ( argc < 2 ) toupper(std::cin, std::cout); }

25 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.

26 Kódelemzés #include <fstream> #include <iostream> void toupper(std::istream&, std::ostream&); int main( int argc; char *argv[]) { if ( argc < 2 ) toupper(std::cin, std::cout); } else // folyt. return 0;

27 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" << argv[i] << std::endl; } else toupper(inp, std::cout);

28 Kódelemzés Kérdés: Kell-e close-t mondanom?
Amikor a zárójelet becsukom, akkor az ifstream destruktora meghívódik!

29 Kódelemzés Feladat: Számoljuk meg, hogy a bemeneten hány sor volt. (Sorvége-jel: ‘\n’)

30 Kódelemzés #include <fstream> #include <iostream> void lines(std::istream&, std::ostream&); int main( int argc; char *argv[]) { if ( argc < 2 ) lines(std::cin, std::cout); } else // folyt. return 0;

31 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);

32 Kódelemzés Egy adott karakter előfordulása egy egyszerű számlálás!

33 Kódelemzés void lines( std::istream& inp, std::ostream& outp ) { int cnt = 0; char prev = '\n'; char curr; while ( std::cin.get(curr) ) cnt = f(cnt, prev, curr); prev = curr; }

34 Kódelemzés int f( int cnt, char prev, char curr ) // warning! { if ( '\n' == prev ) ++cnt; } return cnt;

35 Kódelemzés int f( int cnt, char prev, char ) // így már nem! { if ( '\n' == prev ) ++cnt; } return cnt;

36 Kódelemzés Javítás: void lines( std::istream& inp, std::ostream& outp ) { int cnt = 0; char prev = '\n'; char curr; while ( std::cin.get(curr) ) cnt += '\n' == prev; prev = curr; }

37 Kódelemzés Megoldás: #include <iostream> int main()
{ int ls = 0; char c; while ( std::cin >> std::noskipws >> c) { if (c == ‘\n’) { ls += 1; } } std::cout << ls << std::endl; return 0; }

38 Kódelemzés Megoldás: más út #include <iostream> int main()
{ int ls = 0; char c; while (std::cin >> std::noskipws >> c) { ls = (c == ‘\n’ ? ls + 1 : ls); } std::cout << ls << std::endl; return 0; }

39 Kódelemzés Kimenet: alma szilva ctrl-D eredmény: 2 alma szilva ctrl-D eredmény: 1

40 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.

41 Kódelemzés Megoldás: int f ( char prev, int ls)
{ return prev == ‘\n’ ? ls + 1 : ls; } char c, prev; while ( std::cin >> std::noskipws >> c) { ls = f(prev, ls); prev = c; }

42 Kódelemzés Feladat: Szavak számának a számolása. alma (1) „ „ szilva (2) …

43 Kódelemzés Megoldás: int f (char prev, char c, int ls)
{ return ( prev == ‘\n’ || prev == ‘\t’ || prev == ‘ ‘) && c != ‘\n’ && c != ‘\t’ && c != ‘ ’ ? ls + 1 : ls; }

44 Kódelemzés Megoldás: Más út bool isWS(char c) { … }


Letölteni ppt "Programozási Nyelvek (C++) Gyakorlat Gyak 03."

Hasonló előadás


Google Hirdetések