Narzędzia użytkownika

Narzędzia witryny


format

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Next revision
Previous revision
format [2008/04/16 00:38]
piechot
format [2008/04/16 23:50] (aktualna)
piechot
Linia 1: Linia 1:
 ====== Biblioteka Boost Format ====== ====== Biblioteka Boost Format ======
 + --- //​[[tpiechot@stud.elka.pw.edu.pl|Tomasz Piechota G1ISI]] 2008/04/16 23:44//
 +
 Biblioteka Boost Format dostarcza klasę do formatowania argumentów zgodnie z dostarczonym łańcuchem formatującym. Podstawowe różnice w stosunku do funkcji printf, to m.in.: Biblioteka Boost Format dostarcza klasę do formatowania argumentów zgodnie z dostarczonym łańcuchem formatującym. Podstawowe różnice w stosunku do funkcji printf, to m.in.:
   * deterministyczne zachowanie, nawet w przypadku podania błędnych argumentów (generuje wyjątek lub ignoruje błąd, w zależności od ustawień).   * deterministyczne zachowanie, nawet w przypadku podania błędnych argumentów (generuje wyjątek lub ignoruje błąd, w zależności od ustawień).
Linia 58: Linia 60:
 std::cout << frm << std::​endl; ​                // --> "% _Foo_ _2_ _Bar_ %" std::cout << frm << std::​endl; ​                // --> "% _Foo_ _2_ _Bar_ %"
 </​code>​ </​code>​
 +
 +
  
  
Linia 78: Linia 82:
 Argumenty ujęte w nawiasy kwadratowe są opcjonalne, a dla typu drugiego (%|spec|) również ''​type-char''​. Argumenty ujęte w nawiasy kwadratowe są opcjonalne, a dla typu drugiego (%|spec|) również ''​type-char''​.
  
-Znaczenie poszczególnych parametrów:+==== Znaczenie poszczególnych parametrów ​==== 
   * N - numer argumentu   * N - numer argumentu
   * flags - jedna lub więcej spośród flag:   * flags - jedna lub więcej spośród flag:
Linia 100: Linia 105:
     * s or S - łańcuch znaków     * s or S - łańcuch znaków
     * c or C - jeden znak     * c or C - jeden znak
 +
 +
 +
 +==== Przykłady formatowania przy użyciu łańcucha znaków ====
  
 Przykłady użycia poszczególnych formatowań pokazane są w poniższym kodzie: Przykłady użycia poszczególnych formatowań pokazane są w poniższym kodzie:
 <code cpp> <code cpp>
-//TODO+// Sposób pierwszy według formatu %spec 
 +std::cout << boost::​format("​_%1$d_ _%1$o_ _%1$#​o_"​) % 10 << std::​endl; ​               // --> "_10_ _12_ _012_"​ 
 +std::cout << boost::​format("​_%1$d_ _%1$x_ _%1$#​X_"​) % 47 << std::​endl; ​               // --> "_47_ _2f_ _0X2F_"​ 
 +std::cout << boost::​format("​_%1$5.2f_ _%1$=5.0f_ _%1$05.0f_"​) % 48.237 << std::​endl; ​ // --> "​_48.24_ _  48 _ _00048_"​ 
 + 
 +// Sposób drugi według formatu %|spec| 
 +std::cout << boost::​format("​_%|1$-6|_ _%|2$+-7.2f|_"​) % "​foo"​ % 23.199 << std::​endl; ​ // --> "​_foo ​  _ _+23.20 _" 
 +std::cout << boost::​format("​_%|6.2e|_ _%|11.3e|_"​) % 30.2312 % 312.3 << std::​endl; ​   // --> "​_3.02e+001_ _ 3.123e+002_"​ 
 + 
 +// Trzeci sposób według formatu %N% 
 +std::cout << boost::​format("​%1% %2% %1% %2%") % "​o_O"​ % "​O_o"​ << std::​endl; ​          // --> "o_O O_o o_O O_o" 
 </​code>​ </​code>​
  
 W jednym łańcuchu możemy korzystać z różnych sposóbów, natomiast błędem jest użycie zarówno argumentów numerowanych,​ jak i nienumerowanych. W jednym łańcuchu możemy korzystać z różnych sposóbów, natomiast błędem jest użycie zarówno argumentów numerowanych,​ jak i nienumerowanych.
 <code cpp> <code cpp>
-std::cout << boost::​format("​%d %s") % 10 % "​foo"​ << std::​endl; ​        ​// OK +std::cout << boost::​format("​%d %|s|") % 10 % "​foo"​ << std::​endl; ​       // OK 
-std::cout << boost::​format("​%1$s %2$s") % "​foo"​ % "​bar"​ << std::​endl; ​ // OK +std::cout << boost::​format("​%1$s %2%") % "​foo"​ % "​bar"​ << std::​endl; ​   // OK 
-std::cout << boost::​format("​%1$d %s") % 10 % "​bar"​ << std::​endl; ​      ​// BŁĄD!+std::cout << boost::​format("​%1$d %s") % 10 % "​bar"​ << std::​endl; ​       // BŁĄD!
 </​code>​ </​code>​
  
-Inne sposoby modyfikacji formatowania parametrów:+Ciekawym przykładem może być również technika wymuszająca wcięcie (z wypełnieniem lub bez) niezależnie od długości poprzednich argumentów:
 <code cpp> <code cpp>
-//TODO+// w obu przypadkach liczba 199 zaczyna się po 15 znakach 
 +std::cout << boost::​format("​%s %|15t|%d%"​) % "​Abcdefgh"​ % 199 << std::​endl; ​ // --> "​Abcdefgh ​      ​199"​ 
 + 
 +// z wypełnieniem (duże T + wypełniacz) 
 +std::cout << boost::​format("​%s %|15T-|%d%"​) % "​Abcde"​ % 199 << std::​endl; ​   // --> "Abcde ---------199"​
 </​code>​ </​code>​
 +
 +
 +==== Formatowanie poprzez manipulatory - metoda group() ====
 +
 +Na wygląd formatowania poszczególnych parametrów możemy wpływać także mając już zdefiniowany łańcuch formatujący (utworzony obiekt klasy boost::​format). Tak zdefiniowane formatowanie ma wyższy priorytet od tego wpisanego w konstruktorze. Manipulatory dostępne są po dołączeniu biblioteki ''​iomanip''​.
 +
 +<code cpp>
 +#include <​iomanip>​
 +
 +// (...)
 +
 +// Pierwsze wystapienie argumentu pierwszego również ma szerokość 5 (priorytet manipulatora większy)
 +std::cout << boost::​format("​_%1$3d_ _%1%_"​) % boost::​io::​group(showpos,​ std::​setw(5),​ 101);  // --> "_ +101_ _ +101_"
 +
 +// Manipulatory nie resetują wszystkich, tylko nadpisują istniejące flagi
 +std::cout << boost::​format("​_%1$-3d_ _%1%_"​) % boost::​io::​group(showpos,​ std::​setw(5),​ 101); // --> "_+101 _ _ +101_"
 +, setfill('​x'​)
 +
 +
 +// Inny przykład
 +std::cout << boost::​format("​_%1%_"​) % boost::​io::​group(hex,​ std::​setw(5),​ 99);  // --> "​_ ​  ​63_"​
 +std::cout << boost::​format("​_%|=10|_"​) % boost::​io::​group(setfill('​-'​),​ 101);   // --> "​_----101---_"​
 +</​code>​
 +
 +Funkcja ''​boost::​io::​group''​ może przyjąc wiele manipulatorów,​ jednak ostatnim argumentem musi być wartość przekazywanego parametru.
 +
  
 ===== Wyjątki i ich konfiguracja ===== ===== Wyjątki i ich konfiguracja =====
  
 +Boost Format wprowadza pewną liczbę zasad korzystania z objektów ''​boost::​format'':​
 +  * Łańcuch znaków musi przestrzegać składni opisanej powyżej
 +  * Użytkownik musi dostarczyć dokładnie taką liczbę argumentów,​ jakie zadeklarował w łańcuchu, przed pobraniem sformatowanego wyjścia
 +  * Używając metod ''​modify_item''​ oraz ''​bind_arg'',​ indeksy elementów i argumentów muszą być właściwe
  
-===== Ciekawe przykłady użycia =====+Jeśli klasa format wykryje, że jedna z powyższych zasad nie jest spełniona, odpowiedni wyjątek zostanie rzucony. 
 +Użytkownik jednak ma możliwość wpłynięcia na zachowanie obiektu, deklarując które błędy mają skutkować wyjątkiem, a które mają zostać przemilczane (wyjście zostanie wygenerowane z pustą wartością danego argumentu).
  
 +W celu ustawienia ''​bitów błędów''​ wykorzystuje się metody:
 +<code cpp>
 +unsigned char exceptions(unsigned char newexcept); ​ // ustaw i zwróć
 +unsigned char exceptions() const; ​                  // tylko zwróć
 +</​code>​
  
- --- //[[tpiechot@stud.elka.pw.edu.pl|Tomasz Piechota]] 2008/04/16 00:38//+Dostępne są następujące bity błędów:​ 
 +  * boost::​io::​bad_format_string_bit ​reakcja na błędny format łańcucha formatującego 
 +  * boost::​io::​too_few_args_bit ​za mało argumentów 
 +  * boost::​io::​too_many_args_bit ​za dużo argumentów 
 +  * boost::​io::​out_of_range_bit - nieprawidłowy index dostarczony podczas wywołania np metody ''​modify_item''​ 
 +  * boost::​io::​all_error_bits - reakcja na wszystkie błędy 
 +  * boost::​io::​no_error_bits - brak reakcji na jakikolwiek błąd 
 + 
 +Przykładowy kod prezentujący działane metod exceptions i bitów błędów:​ 
 +<code cpp> 
 +boost::​format f("​_%1%_ _%2%_"​);​ 
 +f % 10; 
 +try 
 +
 +    std::cout << f << std::​endl;​ 
 +
 +catch (boost::​io::​too_few_args &e) 
 +
 +    std::cout << "Za malo argumentow"​ << std::​endl;​ 
 +
 +f.exceptions(~boost::​io::​too_few_args_bit);​ 
 +try 
 +
 +    std::cout << f << std::​endl;​ 
 +
 +catch (boost::​io::​too_few_args &e) 
 +
 +    std::cout << e.what() << std::​endl;​ 
 +
 + 
 +// --> "Za malo argumentow"​ 
 +// --> "_10_ __" 
 +</​code>​ 
 + 
 + 
 + 
 + 
 + 
 + 
 +===== Przykład użycia ===== 
 +Poniższy program wyświetla listę produktów w postaci sformatowanej tabeli 
 + 
 +<code cpp> 
 +#include <​iostream>​ 
 +#include <​boost/​format.hpp>​ 
 +#include <​string>​ 
 +#include <​list>​ 
 + 
 +using namespace std; 
 +using namespace boost; 
 + 
 +class Produkt 
 +
 +public: 
 +    Produkt(string n, int i, float c, float z) : nazwa(n), ilosc(i), cena(c), zmiana(z) { } 
 +    string nazwa; 
 +    int ilosc; 
 +    float cena; 
 +    float zmiana; 
 +}; 
 + 
 +int main(int argc, char *argv[]) 
 +
 +    // Lista obiektów 
 +    list<​Produkt>​ p; 
 +    p.push_back(Produkt("​Widelec",​ 4, 4.99f, 1.021f)); 
 +    p.push_back(Produkt("​Łopatka",​ 32, 2.99f, -10.2292f));​ 
 +    p.push_back(Produkt("​Packa",​ 19, 19.39f, 19.1133f));​ 
 + 
 + 
 +    // pozioma linia 
 +    format line("​%|55T-|"​);​ 
 + 
 +    ​// nazwa ​%|1$-.20s| - wyrownanie do lewej, maksimum 20 znakow 
 +    ​// ilość: ​ %2% - bez dodatkowego formatowania 
 +    // cena:   ​%|3$.2f| - liczba zmiennoprzecinkowa,​ do dwóch miejsc po przecinku 
 +    // zmiana: %|4$+10.4f| - wymuszenie wyświetlania znaku +, szerokosc 10, do 4 miejsc po przecinku, wyrównanie do prawej 
 +    format row("​|%|1$-20.20s|%|21t||%2%%|32t||%|3$.2f|%|43t||%|4$+10.4f|%|54t||"​);​ 
 + 
 +    cout << line << endl; 
 +    cout << row % "Nazwa produktu"​ % "​Ilosc"​ % "​Cena"​ % "​Zmiana (%)" << endl; 
 +    cout << line << endl; 
 +     
 +    for (list<​Produkt>::​const_iterator it = p.begin(); it != p.end(); it++) 
 +        cout << row % it->​nazwa % it->​ilosc % it->cena % it->​zmiana << endl; 
 +     
 +    cout << line << endl; 
 +     
 +    return 0; 
 +
 + 
 +</​code>​
format.1208299103.txt.gz · ostatnio zmienione: 2008/04/16 00:38 przez piechot