Strömmar och strängar Strömmar In- och utmatning Strängar Delsträngar Strömmar och strängar Först, grunderna: Utmatning Inmatning Strängar Sedan, mer tillämpningsorienterat: Läsning av rader Stränghantering och delsträngar Att tjuvtitta 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 2 Strömmar Exempel på strömmar: Utmatning #include <iostream> #include <iomanip> // innehåller std::cout // innehåller setw() std::cout << "Demo:" // utmatning av char * << std::setw(10) // sätt storlek på utmatning << 4711 // utmatning av int << std::endl; // radmatning std::cout << "Name\tPts\n" // rubriker << "Joe\t37\n" // '\t' är tabulatortecken << "Anna\t41\n"; // '\n' är radmatning Utmatning med std::cout, std::cerr, std::clog int i, j; std::cin >> i >> j; // hämta int från stdin 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 3 2D1387 Programsystemkonstruktion med C++ 1
Utmatning med cout, cerr Prefixet c står för character För utmatning används std::cout (skriver till stdout) För felutmatning och loggning använder man std::cerr resp. std::clog (skriver till stderr) Samtliga är globala objekt av typen std::ostream med överlagrad operator<< Utmatning med cout, cerr Den överlagrade operatorn << klarar samtliga inbyggda datatyper. std::string str = "C++"; const void *p = &str; char c = 'a'; std::cout << (int)c << " " // '97' (int) << 3.14 << " " // 3.14 (double) << str << " " // C++ (std::string) << str.c_str() << " " // C++ (const char *) << p << std::endl; // 0012FF60 (adress) std::cerr << "could not open file" // stderr << std::endl; 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 5 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 6 Formatväljare för utmatning Man kan variera formatet på sin utmatning: Inmatning double balance = 147.5371; // pengar på kontot std::cout.precision(5); // använd fem värdesiffror std::cout << "Balance: " // rubrik << std::setw(10) // tio siffrors fält << std::setfill('*') // fyll tomrum med * << balance // utskrift ger resultat: << std::endl; // Balance: ****147.54 Inmatning från std::cin 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 7 2D1387 Programsystemkonstruktion med C++ 2
Inmatning med cin För inmatning från stdin använder man cin Typen på argumentet till operator>> bestämmer hur indata tolkas Inmatning med cin För att förhindra att man skriver utanför avsett minne kan man använda formatväljare för cin: // antag inmatning för ett bankkonto: // kalle qwerty 147.30 std::string user, passwd; double balance; std::cin >> user >> passwd >> balance; if(passwd!= "qwerty") std::cout << "wrong password" << std::endl; else std::cout << "balance: " << balance << std::endl; char buf[10]; // läs 9 tecken + '\0' i varje varv while(std::cin >> std::setw(sizeof buf) >> buf) do_something(buf); 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 9 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 10 Öppning Läsning Skrivning Accesstyper För att knyta en ström till en fil använder man en filström std::ifstream ger inmatning och tar ett filnamn som argument std::ofstream ger utmatning std::fstream ger en generell filström som klarar att både läsa och skriva 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 12 2D1387 Programsystemkonstruktion med C++ 3
#include <fstream> // ifstream, ofstream std::ifstream input("my_file.in"); // skapa infil std::ofstream output("my_file.out"); // skapa utfil // kontrollera att filerna gick att öppna if(!input) std::cout << "open failed for input file"; if(!output) std::cout << "open failed for output file"; std::vector<int> v; int i; input >> i; v.push_back(i); output << v.back() << std::endl; // hämta data // lägg i vektorn // skriv element 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 13 Standardbiblioteket bidrar med en kraftfull strängklass std::string std::basic_string är en behållare som håller bokstäver såsom char eller wchar_t std::string är en typdefinition av std::basic_string<char> För minneseffektivitetens skull har de flesta implementationer infört referensräkning Exempel på stränganvändning: #include <string> std::string s("c++"); s += " is great!"; // skapa sträng // lägg till sträng std::cout << "True: " // använd c_str() för << s.c_str() << std::endl; // tillgång till data std::cout << "Predecessor: " // använd oper[] för << s[0] << std::endl; // tillgång till bokstav std::reverse(s.begin(), s.end()); // vänd på strängen std::cout << s << std::endl; 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 15 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 16 2D1387 Programsystemkonstruktion med C++ 4
Exempel på medlemsfunktioner: basic_string& operator+=(const basic_string& s) basic_string& insert(size_type pos, const basic_string& s) iterator erase(iterator first, iterator last) size_type find_first_of(const basic_string& s) bool empty() const size_type size() const Utmatning till / inmatning från minne Om man vill skriva till / från minnet kan man använda stringstream som skriver till / från en STL-sträng #include <stringstream> std::ostringstream message; // mata till minne int i = 17; double d = 33.3; message << "Error: " << i // fyll med data << " is less than " << d; std::cerr << message.str() << std::endl; // skriv ut std::istringstream source("to be or not to be"); std::string str; source >> str; // ett ord i taget 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 17 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 18 Tillämpning Läsning av rader Stränghantering och delsträngar Att tjuvtitta Att läsa en hel rad // indata: // den där\tdt.utr.sin.def // denna\tdt.utr.sin.def // dessa\tdt.utr/neu.plu.def #include <iostream> #include <fstream> #include <string> std::ifstream is("in.txt"); std::string str; std::getline(is, str); // cout // ifstream // inström // resultatsträng // hämta en hel rad std::string::size_type pos = str.find('\t'); // hitta tab if(pos == std::string::npos) // hittade ej tab return 0; std::cout << "before tab: " << str.substr(0, pos) // position 0...0+pos std::cout << "after tab: " << str.substr(pos + 1) // position pos+1...slut 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 20 2D1387 Programsystemkonstruktion med C++ 5
Tokenisering Tokenisering med whitespace som avskiljare sker automatiskt Till whitespace räknas tabulatortecken (tab), mellanslag och nyrad etc. Läs från inströmmen till en std::string och lägg i en vektor mha push_back() Tokenisering med godtycklig avskiljare // indata: // Far,får får får?nej,får får lamm. std::ifstream is("tokenize.txt"); // inström std::string str; // resultatsträng std::getline(is, str); // hämta en hel rad const char *delim = ",.!? "; // avdelare std::string::size_type old_pos = 0; std::string::size_type pos = str.find_first_of(delim); while(pos!= std::string::npos) // kolla förekomst std::cout << "token: " // klipp ut delsträng << str.substr(old_pos, pos - old_pos) << std::endl; old_pos = pos + 1; // hitta nästa pos = str.find_first_of(delim, old_pos); 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 21 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 22 Att tjuvtitta // indata: poster avdelade med, avslut med # // 1 7 5 6 2 // 53 18 7 8 3 10 // 5 3 # #include <ctype.h> // isdigit std::ifstream is("peek.txt"); // inström std::vector<std::vector<int> > v(1); // behållare för data while(is) int c = is.peek(); // tjuvtitta på tecken if(c == '#') break; else if(isdigit(c)) int i; // temporär is >> i; // hämta data v.back().push_back(i); // lägg sist i behållare else if(c == ' ') // ny post, ny behållare v.push_back(std::vector<int>()); char t; // temporär för skräp is.get(t); // kasta bort skräp Formatering av utmatning Ibland kan höger- och vänsterjustering visa sig nyttigt: // utmatning: // hello there 1 // hello there 2 std::cout << std::setw(10) << std::right // högerställ << "hello" << " there " << 1 << std::endl; std::cout << std::setw(10) << std::left // vänsterställ << "hello" << " there " << 2 << std::endl; 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 23 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 24 2D1387 Programsystemkonstruktion med C++ 6
Länkar Användbara webbplatser: Standarden on-line: http://www.dinkumware.com/refxcpp.html Bra dokumentation på STL: http://www.sgi.com/tech/stl/ 2D1458 Problemlösning och programmering under press Johnny Bigert 2002 25 2D1387 Programsystemkonstruktion med C++ 7