8. Načítání a zápis PDB souboru



Podobné dokumenty
Pokročilé programování v jazyce C pro chemiky (C3220) Vstup a výstup v C++

PB161 Programování v C++ Proudy pro standardní zařízení Souborové proudy Paměťové proudy Manipulátory

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Programování v jazyce C pro chemiky (C2160) 5. Čtení dat ze souboru

Prostory jmen. při vkládání několika hlavičkových souborů může vzniknout kolize. logika.h const int x=5; typedef struct {...

Programování v jazyce C pro chemiky (C2160) 12. Specifické problémy při vývoji vědeckého softwaru

Programování v jazyce C pro chemiky (C2160) 8. Načítání a zápis PDB souboru

Konstruktory a destruktory

<surface name="pozadi" file="obrazky/pozadi/pozadi.png"/> ****************************************************************************

Pokročilé programování v jazyce C pro chemiky (C3220) Dědičnost tříd v C++

Úvod do programování. Lekce 1

Programování v jazyce C pro chemiky (C2160) 6. Funkce, struktury

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

Základy C++ I. Jan Hnilica Počítačové modelování 18

Datové proudy objektový vstup a výstup v C++

18. února 2015, Brno Připravil: David Procházka. Programovací jazyk C++

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

PB161 Programování v jazyce C++ Přednáška 5

Funkční objekty v C++.

PROGRAMOVÁNÍ V C++ CVIČENÍ

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

Vstupní a vstupní proudy v C++

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Množina v C++ (set, multiset).

Datové typy pro reálná čísla

Šablony, kontejnery a iterátory

Množina čísel int stl-set-int.cpp

Vector datový kontejner v C++.

Šablony, kontejnery a iterátory

map, multimap - Asociativní pole v C++.

Standardní algoritmy vyhledávací.

Více o konstruktorech a destruktorech

Programování v C++ 1, 5. cvičení

Pokročilé programování v jazyce C pro chemiky (C3220) Pokročilá témata jazyka C++

Jazyk C++, některá rozšíření oproti C

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Mělká a hluboká kopie

Iterátory v C++. int pole[20]; for (int *temp = pole, temp!= &pole[20]; temp++) { *temp = 0;

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. December 7, 2016

VISUAL BASIC. Práce se soubory

Programování v C++ 3, 3. cvičení

C++ objektově orientovaná nadstavba programovacího jazyka C

Základy programování (IZP)

Datové typy pro reálná čísla

Pokročilé programování v jazyce C pro chemiky (C3220) Úvod do jazyka C++

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

Proměnná. Datový typ. IAJCE Cvičení č. 3. Pojmenované místo v paměti sloužící pro uložení hodnoty.

Programování v C++ 1, 6. cvičení

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Formátová specifikace má tvar (některé sekce nemají smysl pro načítání) %

Úvod do programování. Lekce 3

Základy programování. Úloha: Eratosthenovo síto. Autor: Josef Hrabal Číslo: HRA0031 Datum: Předmět: ZAP

PB161 Programování v jazyce C++ Přednáška 8

Abstraktní datové typy

Zápis programu v jazyce C#

Algoritmizace a programování

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Datové struktury. alg12 1

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

7. Datové typy v Javě

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

2 Datové typy v jazyce C

1.1 Struktura programu v Pascalu Vstup a výstup Operátory a některé matematické funkce 5

Implementace LL(1) překladů

Algoritmizace a programování

Algoritmizace a programování. Terminálový vstup a výstup

C++ přetěžování funkcí a operátorů. Jan Hnilica Počítačové modelování 19

Jazyk C# a platforma.net

15. Projekt Kalkulačka

Algoritmizace a programování

Programování v jazyce C pro chemiky (C2160) 7. Ukazatele, Funkce pro práci s řetězci

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

Druhy souborů. textové. binární. nestrukturované txt strukturované - ini, xml, csv. veřejné bmp, jpg, wav proprietární docx, cdr, psd

Základy programování (IZP)

Programování v C++ První kroky

PREPROCESOR POKRAČOVÁNÍ

Struktury a dynamická paměť

Basic256 - úvod do programování Příklady. ing. petr polách

Abstraktní třídy, polymorfní struktury

Operační systémy. Cvičení 4: Programování v C pod Unixem

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Základy programování (IZP)

Vysoké učení technické v Brně, Fakulta elektrotechniky a komunikačních technologií Ústav automatizace a měřící techniky. Semestrální projekt

PB161 Programování v jazyce C++ Přednáška 6

Dědičnost. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 23.března

Ukazatele, dynamická alokace

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Programovací jazyk Pascal

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

Programování v C++ 1, 1. cvičení

PB přednáška (19. října 2015)

PB161 Programování v jazyce C++ Přednáška 6

Základy programování (IZP)

Jazyk C# (seminář 5)

Koncepce (větších) programů. Základy programování 2 Tomáš Kühr

Transkript:

Pokročilé programování v jazyce C pro chemiky (C3220) 8. Načítání a zápis PDB souboru Třída string Typ string není základním vestavěným typem ale je implementován jako třída ve standardní knihovně C++. Třída string obsahuje některé užitečné metody: length() - vrátí počet znaků v řetězci size() - totéž jako length() operator[](int pos) vrátí znak na pozici pos substr(int pos, int n) vrátí podřetězec dlouhý n znaků začínající na pozici pos c_str() - vrátí řetězec jak je používan v C, tj. typ char* (např. pro předání řetězce funkcím které akceptují pouze klasické řetězce char* a nepodporují string) Podrobnější informace lze nalézt na: http://www.cplusplus.com/reference/string/string/ Uvedené metody nekontrolují platnost řetězce, tj. pokud do proměnné typu string nepřiřadíme žádný řetězec, je řetězec nedefinován a pokus o práci s ním vede k chybě programu. Uvedené metody nekontrolují velikost řetězce, tj. před zavoláním metody musíme zkontrolovat velikost řetězce. desetinnou tečkou (pro výpis fixed a scientific se vypíše přesně n cifer za desetinnou tečkou a případně doplní zprava nulami, při výchozím/implicitním nastavení se jedná pouze o maximální celkový počet cifer před a za desetinnou tečkou). Následující manipulátory lze použít při načítání ze vstupu: skipws nastaví přeskakování bílých znaků (mezera, tabelátor, konec řádku) při načítání (toto je výchozí nastavení) noskipws nastaví že bílé znaky nebudou přeskakovány ws načítá bílé znaky tak dlouho dokud nenarazí na nebílý znak Podrobný výčet manipulátorů se nachází na: http://www.cplusplus.com/reference/iostream/manipulators/ Formátování výstupu Pro formátování výstupů používáme tzv. manipulátory. Pro použití manipulátorů je třeba v záhlaví zdrojového souboru deklarovat #include <iomanip> a using namespace std; Manipulátory se používají ve spojení s operátorem << Manipulátory nastavují formátování a různé parametry pro načítání vstupu a výstupu. #include <iostream> #include <iomanip> using namespace std; int main() // Vypise cele cislo zarovnane // doprava, minimalne 5 znaku, // (zleva se doplni mezery) cout << right << setw(5) << 234 << endl; // Nasledujici prikaz vypise realne // cislo s platnosti na 2 //desetinna mista, tj. 456.15 cout << fixed << setprecision(2) << 456.15738 << endl; return 0; Manipolátory k I/O formátování Následující manipulátory lze použít pro formátování výstupu: fixed výstup reálného čísla ve formátu 123.45 scientific výstup reálného čísla ve formátu1.235e2 Výchozí chování je takové, že se vybere fixed nebo scientific tak aby vypsaná přesnost byla co nejvyšší. left zarovnává výpis do leva right zarovnává výpis do prava setw(n) - nastaví minimální počet vypisovaných znaků n pro nejbližší operaci výpisu (pro celá čísla nebo řetězce). setfill(c) nastaví použití znaku c pro vyplnění výpisu pokud je šířka (nastavená pomocí setw()) větší než je vyžadováno. setprecision(n) - nastavuje počet číslic za Webové stránky předmětu: http://www.ncbr.chemi.muni.cz/~martinp/c3220/ 1/6

ATOM 7 CG2 THR A 1 18.159 11.531 6.124 1.00 10.28 C ATOM 7 CG2 THR A 1 18.159 11.531 6.124 1.00 10.28 C 1 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 Načítání PDB souboru v C++ PDB formát se používá pro ukládání struktur biomolekul v PDB databázi www.rcsb.org. Data PDB souboru jsou organizována jako fixed format, tj. každá položka má přesně udanou pozici na řádku. Dokumentace k PDB formátu je dostupná na: http://www.wwpdb.org/docs.html Každý řádek PDB souboru obsahuje na začátku 6 znaků identifikujících typ dat na daném řádku. Souřadnice atomů se načítají z řádků ATOM (pro standardní residua) a HETATM (pro nestandardní residua). Načítání PDB souboru v C++ je podobné jako v C, ale využívají se proměnné typu string a odpovídající metody (např. substr(), length()), proudy stringstream a jejch metody (operátor >>, str(), clear(), fail(). Zápis PDB souboru v C++ je podobný jako v C, zapisuje se do proudu pomocí operátoru << a pro formátování se používají manipulátory (fixed, left, right, setw(), setprecission()). Struktura záznamu ATOM a HETATM 1 6 Jméno záznamu ATOM nebo HETATM (6 znaků) 7 11 Pořadové číslo atomu (celé číslo) 12 Mezera 13 16 Jméno atomu (řetězec max. 4 znaky) 17 Alternativní pozice atomu (znak) 18 20 Jméno residua (řetězec max. 3 znaky) 21 Mezera 22 Identifikátor protein. řetězce (znak) 23 26 Pořadové číslo residua v sequenci (celé číslo) 27 i_code - Kód indikující vložení residua (znak) 28 30 Tři mezery 31 38 Souřadnice x v Å (reálné číslo) 39 46 Souřadnice y v Å (reálné číslo) 47 54 Souřadnice z v Å (reálné číslo) 55 60 Occupancy (reálné číslo) 61 66 Teplotní faktor (reálné číslo) 77 78 Symbol prvku (řetězec max. 2 zn. zarov. doprava) 79 80 Formální náboj na atomu (2 znaky ve tvaru 2+, 1-) Třídy pro načítání PDB souboru Informace načítané z řádků ATOM a HETATM ukládáme to třídy Atom, která obsahuje datové členy pro uložení informace o jednom atomu a odpovídající metody. // Pro moznost vypisu na standardni // vystup (cout) vlozime: #include <iostream> // Pro praci se souborovymi proudy // (ifstream a ofstream) vlozime: #include <fstream> // Pro praci s retezcovymi proudy // (istringstream) vlozime: #include <sstream> // Pro praci s manipulatory vlozime: #include <iomanip> // Pro praci s kontejnetem vector<> // vlozime: #include <vector> // Pro primy pristup ke jemnum // promennych a funkci standardni // knihovny deklarujeme jmenny // prostor std: using namespace std; class Atom // Cleny tridy Atom ; int main(int argc, char *argv[]) 2/6

Třída Atom class Atom public: // Nasledujici staticke konstatntni // promenne slouzi k nastaveni // hodnoty v recordtype (viz. nize) static const int RECORD_UNKNOWN = 0; static const int RECORD_ATOM = 1; static const int RECORD_HETATM = 2; // Konstruktor Atom(); // Metoda pro nacteni radku void readline(const string &line); // Metoda pro zapis radku do PDB // souboru void writeline(ofstream &ofile); // Metoda pro vypis testovacich // informaci o atomu na stand. vystup void print(); // Zde mohou byt dalsi metody, napr. // pro pristup k datovym clenum // napr. getatomnumber(), // getatomname(), getrresiduename() private: int recordtype; int atomnumber; string atomname; char alternatelocation; string residuename; char chainid; int residuenumber; char icode; double coordx; // souradnice x double coordy; // souradnice y double coordz; // souradnice z double occupancy; double tempfactor; string elementname; string formalcharge; // Nasledujici promenne indikuji, // zda libyla nactena occupancy a // teplotni faktor bool isoccupancy; bool istempfactor; ; Načítání řádků z PDB souboru string line; string recordname; ifstream ifile; Atom *atom = 0; vector<atom*> atomscontainer; string inputpdbfilename = "1jxy_noal.pdb"; ifile.open(inputpdbfilename.c_str()); if (ifile.fail()) cout << "Could not open input file!\n"; return 1; while (!ifile.eof()) getline(ifile, line); if (line.length() >= 6) // Zkopirujeme prvnich 6 znaku do // recordname recordname = line.substr(0, 6); if (recordname == "ATOM " recordname == "HETATM") atom = new Atom; // Metoda readline() nacte z radku // vsechna data pro dany atom atom >readline(line); // Atom vlozime do kontejneru atomscontainer.push_back(atom); ifile.close(); 3/6

Načtení záznamu ATOM a HETATM // Funkce prijima jako argument radek // obsahujici zaznam ATOM nebo HETATM void Atom::readLine(const string &line) string recordname; string s; // pomocna retezcova promenna istringstream sstream; // Radek by mel mit minimalne 53 znaku // aby obsahoval vsechny povinne udaje if (line.length() < 53) cout<<"the line is too short!" <<endl; // Zkopirujeme prvnich 6 znaku do // recordname recordname = line.substr(0, 6); if (recordname == "ATOM ") recordtype = RECORD_ATOM; else if (recordname == "HETATM") recordtype = RECORD_HETATM; else // Neni li to ATOM ani // HETATM nelze pokracovat // Budeme nacitat cislo atomu // 5 znaku od pozice 6 se zkopiruje do s s = line.substr(6, 5); // Do retezcoveho proudu nastavime // retezec s, ze ktereho se bude cist sstream.str(s); // Odstranime pripadny chybovy stav // proudu z pripadneho predchoziho cteni sstream.clear(); // Nacitame cislo atomu sstream >> atomnumber; if (sstream.fail()) cout << "Error reading file!" << endl; // Pokracovani metody readline() // z predchoziho sloupce // Zde je treba doplnit kod pro nacteni // dat do promennych residuename, // chainid, residuenumber, icode // Nacteme souradnice x, y, z s = line.substr(30, 24); sstream.str(s); sstream.clear(); sstream >> coordx >> coordy >> coordz; if (sstream.fail()) cout << "Error reading file!" << endl; // Nacteme occupancy, ale pouze pokud je // radek delsi nez if (line.length() >= 60) s = line.substr(54, 6); sstream.str(s); sstream.clear(); sstream >> occupancy; if (!sstream.fail()) isoccupancy = true; // Zde je treba doplnit kod pro nacteni // tempfactor, elementname, formalcharge // Nesmime zapomenout predtim vzdy // zkontrolovat delku radku // Nyni nacteme jmeno atomu // Z retezce line se zkopiruji 4 znaky // od pozice 12 do atomname atomname = line.substr(12, 4); // Nacteme alternate location indicator // Zkopiruje se znak na pozici 16 alternatelocation = line[16]; // Pokracovani na dalsim sloupci... 4/6

Zápis do PDB souboru // Nekde ve funkci main() nebo ve vhodne // funkci/metode bude umisten kod // ktery otevre vystupni soubor a potom // bude pro jednotlive atomy volat // nasledujici metodu void Atom::writeLine(ofstream &ofile) // Zapiseme jmeno zazn. ATOM nebo HETATM if (recordtype == RECORD_ATOM) ofile << "ATOM "; else if (recordtype == RECORD_HETATM) ofile << "HETATM"; else // Zapiseme cislo atomu, 5 znaku // zarovnanych do prava ofile << right << setw(5) << atomnumber; // Zde je v PDB vzdy mezera ofile << ' '; // Zapiseme jmeno atomu, 4 znaky // zarovnane do leva ofile << left << setw(4) << atomname; // Zapiseme jeden znak alternate // location ofile << alternatelocation; // Zapiseme jmeno residua, 3 znaky // zarovnane do leva ofile << left << setw(3) << residuename; // Zde je v PDB vzdy mezera ofile << ' '; // Zapiseme znak identifikujici retezec ofile << chainid; // Zapiseme cislo residua, 4 znaky // zarovnane do prava ofile << right << setw(4) << residuenumber; // Pokracovani metody writeline() // z predchoziho sloupce // Zapiseme kartezske souradnice atomu // zarovnane doprava s fixnim poctem // cislic za desetinnou teckou // (manipulator fixed), pocet // desetinnych mist bude 3 a celkovy // pocet zapsanych znaku je 8 // (vcetne desetinne tecky) ofile << right << fixed << setprecision(3); ofile << setw(8) << coordx; ofile << setw(8) << coordy; ofile << setw(8) << coordz; // Zapiseme occupancy nebo mezery if (isoccupancy) ofile << right << fixed << setprecision(2) << setw(6) << occupancy; else // Zapiseme teplotni faktor if (istempfactor) ofile << right << fixed << setprecision(2) << setw(6) << tempfactor; else // Zde je v PDB souboru vzdy 10 mezer // Zapiseme jmeno prvku ofile << right << setw(2) <<elementname; // Zapiseme formalni naboj ofile << left << setw(2) <<formalcharge; // Zapiseme znak konce radku ofile << endl; // Zapiseme jeden znak insert code ofile << icode; // Zde jsou v PDB vzdy 3 mezery // Pokracovani na dalsim sloupci... 5/6

Třída Application V jazyce C++ často používáme třídu Application, která je hlavní třídou programu a soustřeďuje nejdůležitější data a metody. Ve funkci main() pak pouze vytvoříme objekt typu Application a zavoláme jeho metodu run(), která obsahuje veškerý hlavní kód. class Application public: Application(); // Destruktor, v nem je treba uvolnit // dynamicky alokovanou pamet ~Application(); // V metode run() bude veskery hlavni // kod, ktery jsme drive umistovali // do funkce main() int run(int argc, char *argv[]); bool readpdbfile(); void writepdbfile(); private: string inputpdbfilename; string outputpdbfilename; vector<atom*> atomscontainer; ; int main(int argc, char *argv[]) Application app; return app.run(argc, argv); Dodržujte následující pravidla V konstruktoru vždy inicializujte datové členy třídy (obvykle se inicializují jen proměnné základních typů, proměnné objekt. typů obvykle není třeba inicializovat, protože jsou inicializovány ve svých konstruktorech). V destruktoru vždy uvolněte dynamicky alokovanou paměť (týká se jen situace, kdy ukazatele ukazující na tuto paměť jsou členy třídy). Program vytvářejte postupně, nejdříve vytvořte definice tříd a metody, jejich těla ponechejte prázdná a program přeložte. Potom přidávejte kód, vždy po dokončení důležité části program přeložte a otestujte. Úloha 1 6 bodů Vytvořte program který načte atomy z PDB souboru (řádky ATOM a HETATM) a zapíše je do jiného souboru. Jméno vstupního a výstupního souboru bude specifikováno na příkazovém řádku Program otestujte se souborem /home/martinp/c3220/data/1jxy_noal.pdb Objekty typu Atom alokujte vždy dynamicky (pomocí operátoru new) a ukládejte do kontejneru vector<> V programu použijte třídu Application V destruktoru třídy Application nezapomeňte uvolnit paměť alokovanou pro atomy a vyprázdnit kontejner Chybové hlášky upravte tak, aby nahlásily na kterém řádku ve vstupním PDB souboru chyba nastala Nápověda: Vložte hlavičkové soubory (viz. příklad v sekci "Načítání PDB"). Definujte třídu Atom jak je uvedeno v příkladu v sekci "Třída Atom". Vytvořte metod třídy Atom, jejich obsah prozatím ponechejte prázdný. Vytvořte funkci main() a program zkompilujte. V konstruktoru Atom() inicalizujte proměnné třídy: recordtype inicializujte hodnotou RECORD_UNKNOWN, číselné proměnné (int, double) inicializujte 0, znakové proměnné (char) je v tomto případě vhodné inicializovat znakem mezery. Řetězcové proměnné je možné inicializovat prázdným řetězcem, v tomto případě je však vhodnější je inicializovat mezerami odpovídající šířce záznamu (tj. atomname inicializujeme řetězcem o 4 znacích, residuename o 3 znacích a elementname a formalcharge o 2 znacích). Proměnné isoccupancy a istempfactor a inicializujte hodnotou false. Ve funkci main() zapište kód vycházející z příkladu v sekci "Načítání řádků z PDB souboru". Na konci vypište počet atomů v kontejneru a v cyklu volejte mrtodu print() pro každý atom. V metodě print() implementujte kód pro jednoduchý výpis hlavních vlastností atomu (číslo atomu, jméno atomu, souřadnice, symbol prvku). Implementujte metodu readline() podle příkladu uvedeného v sekci "Načtení záznamu ATOM a HETATM". Do příkladu je však dále potřeba implementovat načtení hodnot residuename, chainid, residuenumber, icode, tempfactor, elementname, formalcharge. Nezapomeňte, že v PDB speifikaci jsou pozice záznamů číslovány od 1, zatímco znaky řetězce jsou v C/C++ číslovány od 0. Implementujte metodu writeline() podle příkladu uvedeného v sekci "Zápis do PDB souboru". Ve funkci main() otevřete výstupní soubor a volejte metodu writeline() pro každý atom v kontejneru. Funkčnost otestujte se souborem 1jxy_noal.pdb, zapisovaný soubor by měl být zcela totožný s načítaným souborem (toto ověřte unixovým příkazem diff). Program nyní předělajte tak, aby obsahoval třídu Application jak je ukázáno na příkladu v sekci "Třída Application". V konstruktoru inicializujte proměnné třídy (např. přiřaďte jména souborů do proměnných inputpdbfilename a outputpdbfilename). V destruktoru uvolněte dynamicky alokovanou paměť (vymažte každý atom v kontejneru a vynulujte velikost kontejneru viz. minulé cvič., příklad v sekci "Kontejner ukazatelů"). Kód pro načtení PDB souboru přesuňte z původní funkce main() do metody readpdbfile(), nezapomeňte odstranit lokální proměnné atomscontainer a inputpdbfilename, protože místo nich se budou používat obdobné proměnné, které jsou členy třídy Application. Metoda bude vracet hodnotu false, pokud nebylo načtení úspěšné, jinak vrátí true. Kód pro zápis PDB souboru přesuňte do writepdbfile(). V metodě run() otestujte počet argumentů (nezapomeňte, že první argument je název programu, takže argc je vždy rovno minimálně 1). Pokud nebyl žádný argument specifikován, ukončete program. Pokud byl specifikován jeden argument (název vstupního PDB souboru), načtěte PDB soubor a na výstop vypište testovací informace. Pokud byly specifikovány dva argumenty, pak navíc zapište PDB soubor (jeho jméno je dáno druhým argumentem). Nezapomeňte zkopírovat argumenty z argv[] do proměnných inputpdbfilename a outputpdbfilename. Abychom mohli při chybě vypisovat číslo řádku, je potřeba v metodě Application::readPdbFile() přidat celočíselnou proměnnou jejíž hodnota ze vždy zvětší po načtení řádku o 1 a tu předávat do metody Atom::readLine(), která potom její hodnotu využije při výpisu chybové zprávy. 6/6