2. C++ Avancé
2.1. Les flux
Les flux permettent la lecture ou l'écriture d'information. A la différence
du C on utilise pas un format d'affichage mais les informations sont envoyées
de manière sérielle.
2.1.1. Les flux standard et les opérateurs d'indirection
- cin : entrée standard, console
- cout : sortie standard, console
- cerr : sortie erreur, non bufférisée
- clog : sortie erreur, bufférisée
on utilise les opérateurs de redirection :
- << : envoi d'information sur un flux de sortie (écriture)
- >> : envoi d'information sur un flux d'entrée (lecture)
2.1.2. Ecriture
On dispose d'un ensemble de manipulateurs qui autorisent la modification dont l'information
est affichée :
- hex oct dec : affichage d'un nombre en hexadécimal, octal ou décimal
- setw : fixe la longueur de l'affichage
- setfill : caractère de remplissage
- setprecision : nombre de chiffres après la virgule
- scientific affichage des flottants avec exposant
- fixed affichage des flottants en point fixe
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
vector<vector<double>> matrix;
const int MAX_ROWS = 4;
const int MAX_COLS = 3;
int main() {
for (int i=0; i<MAX_ROWS; ++i) {
matrix.push_back(vector<double>(MAX_COLS));
}
for (int i=0; i<MAX_ROWS; ++i) {
for (int j=0; j<MAX_COLS; ++j) {
if ((j % 2)==0) {
matrix[i][j] = static_cast<double>(1.0)/(2.0+i+j);
} else {
matrix[i][j] = static_cast<double>(rand())/(2.0+i+j);
}
}
}
// print line of 40 '='
cout << setw(40) << setfill('=') << '\0' << endl;
vector<vector<double>>::iterator row_it;
vector<double>::iterator col_it;
// =============================================
// print matrix contents in three different ways
// =============================================
// 1. default
cout << "default ===========" << endl;
cout.precision(8);
for (row_it = matrix.begin(); row_it != matrix.end(); ++row_it) {
for (col_it = (*row_it).begin(); col_it != (*row_it).end(); ++col_it) {
cout << setw(20);
cout << *(col_it);
}
cout << endl;
}
cout << endl;
// 2. scientific
cout << "scientific ===========" << endl;
cout << std::scientific;
cout.precision(8);
for (row_it = matrix.begin(); row_it != matrix.end(); ++row_it) {
for (col_it = (*row_it).begin(); col_it != (*row_it).end(); ++col_it) {
cout << setw(20);
cout << *(col_it);
}
cout << endl;
}
cout << endl;
// 3. fixed
cout << "fixed ===========" << endl;
cout << std::fixed;
cout.precision(8);
cout << setfill('_');
for (row_it = matrix.begin(); row_it != matrix.end(); ++row_it) {
for (col_it = (*row_it).begin(); col_it != (*row_it).end(); ++col_it) {
cout << setw(20);
cout << *(col_it);
}
cout << endl;
}
return 0;
}
123456789012345678901234567890123456789012345678901234567890
default ===========
0.5 6.0142979e+08 0.25
0.33333333 2.1173272e+08 0.2
0.25 3.3633856e+08 0.16666667
0.2 2.8577282e+08 0.14285714
scientific ===========
5.00000000e-01 6.01429794e+08 2.50000000e-01
3.33333333e-01 2.11732722e+08 2.00000000e-01
2.50000000e-01 3.36338555e+08 1.66666667e-01
2.00000000e-01 2.85772819e+08 1.42857143e-01
fixed ===========
__________0.50000000__601429794.33333337__________0.25000000
__________0.33333333__211732721.50000000__________0.20000000
__________0.25000000__336338555.39999998__________0.16666667
__________0.20000000__285772819.16666669__________0.14285714
2.1.3. Lecture
Lecture depuis le clavier : utiliser Ctrl-D pour fermer le flux ou utiliser un pipe
#include <iostream>
#include <istream>
#include <vector>
#include <iterator>
#include <string>
#include <algorithm>
#include <functional>
#include <cstdlib>
using namespace std;
int main() {
istream_iterator<string> cin_iter(std::cin);
istream_iterator<string> cin_end;
vector<string> v;
for ( ; cin_iter != cin_end; ++cin_iter) {
v.push_back(*cin_iter);
}
copy(v.begin(), v.end(), ostream_iterator<string>(cout, " * "));
cout << endl;
return EXIT_SUCCESS;
}
\$ ./c2_stream_cin_read.exe
abc def, ghi jkl^D
abc * def, * ghi * jkl *
\$ echo "ab cd ef,gh ij" | ./c2_stream_cin_read.exe
ab * cd * ef,gh * ij *
2.1.4. Les fichiers : fstream
La classe fstream permet de gérer les fichiers en lecture ou en écriture.
On utilise les méthodes open pour ouvrir le fichier et close pour le fermer.
#include <iostream>
#include <fstream>
#include <stdexcept>
using namespace std;
int main() {
fstream file;
const char *file_name = "data.txt";
// ===================================
// create file
// ===================================
file.open(file_name, ios::out);
if (!file.is_open()) {
throw runtime_error("could not open file");
}
const int ROWS = 5;
const int COLS = 4;
file << ROWS << " " << COLS << endl;
for (int i=0; i<ROWS; ++i) {
file << "line" << i << " ";
for (int j=0; j<COLS; ++j) {
file << 20*i+j << " ";
}
file << endl;
}
file.close();
// ===================================
// read file by tokens
// ===================================
file.open(file_name, ios::in);
if (!file.is_open()) {
throw runtime_error("could not open file");
}
int rows, cols, value;
string str;
file >> rows >> cols;
for (int i=0; i<rows; ++i) {
file >> str;
for (int j=0; j<cols; ++j) {
file >> value;
cout << "read: " << str << " " << value << endl;
}
}
file.close();
// ===================================
// read file by lines
// ===================================
file.open(file_name, ios::in);
if (!file.is_open()) {
throw runtime_error("could not open file");
}
string line;
file >> rows >> cols;
for (int i=0; i<rows; ++i) {
getline(file, line);
cout << "[" << line << "]" << endl;
}
file.close();
return 0;
}
read: line0 0
read: line0 1
read: line0 2
read: line0 3
read: line1 20
...
read: line4 83
lecture ligne à ligne : attention ligne vide après 5 4 \n
[]
[line0 0 1 2 3 ]
[line1 20 21 22 23 ]
[line2 40 41 42 43 ]
[line3 60 61 62 63 ]
Le fichier écrit puis relu est le suivant :
5 4 <--- 5 lignes, 4 colonnes
line0 0 1 2 3
line1 20 21 22 23
line2 40 41 42 43
line3 60 61 62 63
line4 80 81 82 83
2.1.5. Les chaines comme flux : sstream
- la classe ostringstream permet d'utiliser une chaine comme flux de sortie
- la classe istringstream permet d'extraire des mots depuis une chaine
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
/**
* main function
*/
int main() {
string word;
vector<string> words;
// ==========================================
// read string from keyboard
// terminate input with ^D
// ==========================================
// read words and put them into a vector
while (cin >> word) {
words.push_back(word);
}
// display what was read from keyboard
ostringstream oss;
for (int i=0; i<words.size(); ++i) {
oss << i << ": " << words[i] << endl;
}
cout << oss.str() << endl;
// ==========================================
// use of istringstream
// distinguish between strings and numbers
// ==========================================
string str = " exemple 2 phrase à étudier 123 ";
istringstream iss(str);
int n = 1;
while (iss >> word) {
if (isdigit(word[0])) {
cout << "number : " << atoi(word.c_str()) << endl;
} else {
cout << n << ": " << word << endl;
}
++n;
}
return 0;
}
12.5 abc def 0 @CTRL-D
0: 12.5
1: abc
2: def
3: 0
4: @
1: exemple
number: 2
3: phrase
4: à
5: étudier
number: 123