1 Wstęp do informatyki- wykład 8 Pętla while, do while,for -pętla w pętli- przykłady Operator rzutowania Manipulatory Treści prezentowane w wykładzie zostały oparte o: S. Prata, Język C++. Szkoła programowania. Wydanie VI, Helion, 2012 www.cplusplus.com Jerzy Grębosz, Opus magnum C++11, Helion, 2017 B. Stroustrup, Język C++. Kompendium wiedzy. Wydanie IV, Helion, 2014 S. B. Lippman, J. Lajoie, Podstawy języka C++, WNT, Warszawa 2003.
Instrukcje iteracyjne - pętla while 2
Pętla do...while... 3
Pętla for 4
Pętle przykład pętla w pętli czynniki pierwsze // Rozkład liczby naturalnej na czynniki pierwsze // np. 12 =2*2*3 40=2*2*2*5 90=2*3*3*5 /* Elementarnym sposobem rozkładu liczb na czynniki pierwsze jest wykonywanie kolejnych dzieleń, np.: 56 2 28 2 14 2 7 7 1 */ int main() { unsigned int n; cout << "podaj liczbe"; cin >> n; cout<<"rozkład liczby "<< n << " na dzielniki pierwsze \n;" 5
6 Pętle przykład pętla w pętli czynniki pierwsze //rozkład liczby naturalnej n na czynniki pierwsze int k = 2; //kolejne cyfry rozkładu while (n>1)//dopóki są jeszcze jakieś dzielniki { //dzielimy dopóki się da przez k while (n%k == 0)//dopóki n się dzieli przez k { cout << k << " ";//wypisujemy dzielnik n /= k; //skracamy liczbę } //n już nie dzieli się przez k, k++;//następny potencjalny dzielnik } }
7 Pętle przykład pętla w pętli - liczby pierwsze //Program wyświetla wszystkie liczby pierwsze //z danego zakresu int main() { unsigned int n = 500; if (n >= 2) cout<< 2 <<",";// 2 wyswietlamy osobno // sprawdzamy wszystkie wartości nieparzyste od 3 do n for (i = 3; i <= n; i += 2) { bool isprime = true; // zolozmy, ze jest pierwsza //aby pokazać, że liczba jest pierwsza wystarczy //sprawdzić czy ma dzielniki od 3 do sqrt(n) //obliczamy pierwiastek przed petla int p = (int) (sqrt(i)); //rzutowanie na int // dla sqrt trzeba: #include<cmath>
8 Pętle przykład pętla w pętli - liczby pierwsze //dzielimy przez liczby nieparzyste od 3 do sqrt(i) for (int j = 3; j <= p; j += 2) { if (i % j == 0) //jeśli i ma dzielnik { isprime = false;//to nie jest pierwsza break; //wychodzimy z pętli } } // albo doszliśmy do sqrt(i) i nie było dzielnika // albo opuściliśmy pętle przez break(był dzielnik) if (isprime) cout<< i << ","; }//end for po nieparzystych z zakresu return 0; }//main
9 Operator postaci (nazwa typu) wyrażenie Operator rzutowania to operator rzutowania (jawnego przekształcania typu). Jest on operatorem jednoargumentowym: wynikiem działania tego operatora na wyrażenie pewnego typu jest odpowiadająca tej wartości wartość innego typu - tego wymienionego w nawiasie. Z operatora tego należy korzystać tylko w przypadku, gdy naprawdę wiemy, co chcemy zrobić. Nie należy go nadużywać. Czasem jest jednak przydatny. Na przykład w drugiej instrukcji fragmentu double x = 7; int k = (int)x; Rzutowanie wartości zmiennej x jest wskazane, gdyż wartość ta, jako wartość szerszego typu, może być wpisana do zmiennej typu węższego, jakim jest typ int, tylko ze stratą informacji (precyzji). Choć nie jest to błąd, to kompilator zwykle wypisuje ostrzeżenia; jeśli zastosujemy jawne rzutowanie, ostrzeżeń nie będzie.
Formatowanie manipulatory i flagi 10 Sposób formatowania danych w operacjach wyjścia można zmienić. Służą do tego flagi (znaczniki) formatowania (format flags) i manipulatory. Manipulatory są to funkcje zdefiniowane w klasie ios i wywoływane poprzez podanie ich nazw jako elementów wstawianych do lub wyjmowanych ze strumienia.
11 Formatowanie manipulatory bezargumentowe Manipulatory bezargumentowe Manipulatory bezargumentowe wstawia się do strumienia nie podając nawiasów. Mają one nazwy takie jak flagi. fixed, scientific ustawiają formatowanie wyprowadzanych liczb zmiennopozycyjnych. W notacji naukowej (scientific) wypisywana jest jedna cyfra przed kropką, maksymalnie tyle cyfr po kropce, ile wynosi aktualna precyzja, następnie litera 'e' i wykładnik potęgi dziesięciu, przez którą należy pomnożyć liczbę znajdującą się przed literą 'e'. Jeśli liczba jest ujemna, to przed nią wypisywany jest znak minus. Na przykład 1.123456e2 oznacza 112.3456, natomiast -1.123456e-3 oznacza -0.001123456.
Formatowanie manipulatory bezargumentowe Format normalny (fixed) oznacza wypisywanie maksymalnie tylu cyfr po kropce dziesiętnej, ile wynosi aktualna precyzja. Jeśli żaden format nie jest ustawiony, to użyty będzie format ogólny, który pozostawia implementacji sposób zapisu (naukowy lub normalny) w zależności od wartości liczby tak, żeby zapis z ustaloną precyzją zajmował jak najmniej miejsca double x = 123.4567891; double y = 12345678.91; //format ogólny cout<< x << endl; // 123.457 cout<< y << endl; // 1.23457e+07 cout<< fixed << y << endl; //12345678.910000 cout<< scientific << x << endl; // 1.234568e+02 12
Formatowanie - manipulatory showpos, noshowpos- znak plus przed liczbami dodatnimi (domyślnie dla wartości dodatnich znak plus jest pomijany) lub liczby dodatnie nie są poprzedzane znakiem plus int a = 123; cout<< showpos <<"a = "<< a <<endl; //a = +123 showpoint, noshowpoint zawsze wypisz kropkę dziesiętną i końcowe zera w części ułamkowej (domyślnie: NIE) albo wynik bez kropki jeśli część ułamkowa jest zerowa double b = 1234; cout<< b << endl; //1234 cout<< showpoint << b << endl; //1234.00 13
14 Formatowanie - manipulatory left, right ustawiają sposób wyrównywania (justowania) wyprowadzanych danych: do lewej, prawej. endl powoduje wysłanie do strumienia wyjściowego znaku końca linii i opróżnienie bufora związanego z tym strumieniem, czyli natychmiastowe wyprowadzenie znaków z bufora do miejsca przeznaczenia (na ekran, do pliku itd). boolalpha, noboolalpha wstawianie do strumienia wynikowego wartości logicznych w postaci słów false i true albo liczb 0 lub 1
Manipulatory z argumentami 15 Istnieją też manipulatory argumentowe. Stosuje się je analogicznie jak manipulatory bezargumentowe, ale wymagają one argumentów, które, jak dla zwykłych funkcji, podaje się w nawiasach. Aby używać predefiniowanych manipulatorów argumentowych, należy dołączyć plik nagłówkowy #include<iomanip>. Predefiniowane manipulatory argumentowe zwracają, jak wszystkie manipulatory, referencję do strumienia do którego zostały wstawione
Manipulatory z argumentami 16 setw(int szer) ustawia szerokość pola dla najbliższej operacji na strumieniu, przy czym określana jest minimalna szerokość pola: jeśli dana zajmuje więcej znaków, to odpowiednie pole zostanie zwiększone. Domyślną wartością szerokości pola jest zero, czyli każda wypisywana dana zajmie tyle znaków, ile jest potrzebne, ale nie więcej int e = 1, f = 10; cout<< "--------" << endl << setw(4) << e << setw(4) << f <<endl; cout<< left << setw(4) << e << setw(4) << f << endl <<"--------"; -------- 1 10 1 10 --------
Manipulatory z argumentami 17 setfill(char_type znak) ustawia znak, którym będą wypełniane puste miejsca jeśli szerokość pola wydruku jest większa niż liczba wyprowadzanych znaków (domyślnie jest to znak spacji). int j = 1, k = 10; cout << right << setw(6) << setfill('0') << j << endl; //000001 cout << left << setw(6) << j <<endl; //100000 cout << right;//powrót do wyrównania do prawej cout << setw(5) << setfill('*'); cout <<'a'<< endl; //****a
18 Manipulatory z argumentami //dopoki nie zmienimy wypełnienia, mamy //wypelnienie '*'. Mamy zmienne j = 1, k = 10; cout << setw(4) << j << setw(4) << k << endl; //***1**10 cout << left << setw(4) << j << setw(4) << k << endl; //1***10** //powrot do standardowych ustawien cout << right << setfill(' '); cout << setw(4) << j << setw(4) << k << endl; // 1 10
Manipulatory z argumentami 19 setprecision(int prec) ustawia precyzję wyprowadzanych liczb zmiennopozycyjnych. W przypadku formatu fixed jest to ilość cyfr po kropce dziesiętnej W przypadku formatu naukowego scientific jest to ilość cyfr mantysy po kropce Dla formatu ogólnego jest to całkowita liczba cyfr liczby, chyba, że liczba ma mniej cyfr. Domyślnie precyzja ustawiona jest na 6.
20 Manipulatory z argumentami #include <iostream> // std::cout, std::fixed #include <iomanip> // std::setprecision using namespace std; int main () { double d = 3.14159, g = 1234567.89; cout << g << endl; //1.23457e+06 //format ogólny cout << setprecision(5) << g << '\n'; //1.2346e+006 cout << setprecision(5) << d << '\n'; //3.1416 cout << setprecision(9) << d << '\n'; //3.14159 cout << fixed; //format z. cout << setprecision(5) << d << '\n'; //3.14159 cout << setprecision(8) << d<<'\n'; //3.14159000 cout << setprecision(5) << g <<'\n'; //1234567.89000 }
Pętle for- przykład- tabliczka mnożenia /*Wyświetlić na ekranie tabliczkę mnożenia wymiaru n x n. Pobrać od użytkownika n, 0< n <15. */ #include <iostream> #include <iomanip> using namespace std; int main () { int n; //pobieramy n w pętli zaporowej do{ cout<<"podaj liczbe "; cin>>n; }while(n<=0 n>=15); 21
Pętle for- przykład- tabliczka mnożenia /*tabliczka mnożenia, dla n=3 1 2 3 2 4 6 3 6 9 */ //mamy wiersze od 1 do n for(int i =1; i<=n; i++) { //w każdym wierszu mamy n elementów for(int j=1; j<=n; j++) cout << setw(4) << i*j; //po wydrukowaniu wiersza znak nowej linii cout<<endl; } //wstawiamy puste linie przed kolejną częścią cout<<endl<<endl; 22
Pętle for- przykład- trójkąt pętle zagniezdżone /*wyświetlić trójkąt prostokątny o wysokości n postaci: dla n=4 * dla i=1 1 * ** dla i=2 2 * *** dla i=3 3 * **** dla i=4 4 * */ for(int i = 1; i <= n; i++) // mamy n wierszy { //jesteśmy w i tym wierszu, drukujemy i gwiazdek for(int j = 1; j <= i; j++) cout << '*'; //po wyświetleniu wiersza znak nowej linii cout << endl; } cout << endl << endl;//dodatkowe puste linie 23
Pętle for- przykład- trójkąt manipulator setfill /* 2 wersja: z wykorzystaniem manipulatora setfill * ** *** **** */ for(int i=1; i<=n; i++) // mamy n wierszy { // w i tym wierszu, drukujemy i gwiazdek: cout << setfill('*')//ustawiamy wypełnienie na * << setw(i+1) //szerokosc na i+1 << ' '//na i+1 miejscu wyświetlamy spację //poprzedzoną i gwiazdkami << endl;//znak nowej linii } return 0; } 24
Pętle for- przykład- trójkąt- choinka /* choinka o wysokości 5 ^ i=1 4 spacje 1 ^ ^^^ i=2 3 spacje 3 ^ ^^^^^ i=3 2 spacje 5 ^ ^^^^^^^ i=4 1 spacja 7 ^ ^^^^^^^^^ i=5 0 spacji 9 ^ */ for (int i = 1; i <= 5; i++) { //dla i-tego wiersza: 5-i spacji for (int j = 1; j <= 5 - i; j++) //spacje cout<<' '; //dla i-tego wiersza: 2*i-1 ^ for (int j = 1; j <= i * 2-1; j++) //^ cout<<'^'; cout << endl; //nowa linia } 25