
//
// To jest przykładowy kod z podrozdziału 23.9 "Dopasowywanie przy użyciu wyrażeń regularnych" książki
// "Programowanie. Teoria i praktyka z wykorzystaniem C++" Bjarne'a Stroustrupa.
//

#include "std_lib_facilities.h"

//------------------------------------------------------------------------------

struct bad_from_string : std::bad_cast
// Klasa do raportowania błędów związanych z rzutowaniem łańcuchów.
{
    const char* what() const throw() // Przesłonięcie funkcji what() klasy bad_cast.
    {
        return "bad cast from string";
    }
};

//------------------------------------------------------------------------------

template<class T> T from_string(const string& s)
{
    istringstream is(s);
    T t;
    if (!(is >> t)) throw bad_from_string();
    return t;
}

//------------------------------------------------------------------------------

int main()
try
{
    ifstream in("table.txt");    // plik wejściowy
    if (!in) error("Brak pliku wejściowego.");

    string line;            // bufor wejściowy
    int lineno = 0;

    regex header( "^[\\w ]+(	[\\w ]+)*$");
    regex row( "^[\\w ]+(	\\d+)(	\\d+)(	\\d+)$");

    if (getline(in,line)) {        // sprawdza wiersz nagłówkowy
        boost::smatch matches;
        if (!boost::regex_search(line, matches, header)) {
            error("brak nagłówka");
        }
    }

    // sumy kolumn:
    int boys = 0;
    int girls = 0;

    // Wartości bieżących wierszy:
    int curr_boy = 0;
    int curr_girl = 0;

    while (getline(in,line)) {    // Wydobywa i sprawdza dane.
        ++lineno;
        smatch matches;
        if (!regex_search(line, matches, row)) 
            error("Niepoprawny wiersz.", lineno);

        // Sprawdza wiersz:
        curr_boy = from_string<int>(matches[1]);
        curr_girl = from_string<int>(matches[2]);
        int curr_total = from_string<int>(matches[3]);
        if (curr_boy+curr_girl != curr_total) error("Nieprawidłowa suma wiersza");

        boys += curr_boy;
        girls += curr_girl;
    }

    // Sprawdza kolumny:
    if (2*curr_boy  != boys)  error("Nie zgadza się suma chłopców.");
    if (2*curr_girl != girls) error("Nie zgadza się suma dziewcząt.");
}
catch (std::exception& e) {
    cerr << "Błąd: " << e.what() << '\n'; 
    return 1;
}
catch (...) {
    cerr << "Nieznany wyjątek!\n"; 
    return 2;
}

//------------------------------------------------------------------------------
