Chapitre 1 : de C à C++ #
Slides #
Version imprimable (faire CTRL+P)
Exemples #
1242.2_01.01_HelloWorld
main.cpp
#include <iostream>
#include <print>
int main()
{
std::cout << "Hello world++!" << std::endl;
// Since C++23
std::println("Hello world from C++23!");
return 0;
}1242.2_01.02_VariablesDeclarations
main.cpp
#include <print>
int main()
{
for (int i = 0; i < 3; ++i)
{
int x = i * 2;
std::println("{}", x);
}
return 0;
}1242.2_01.03_Namespaces
main.cpp
#include <print>
#include <string>
namespace language::english
{
std::string colors[] = {"White", "Red", "Black"};
void colorName(int index)
{
std::println("The color is: {}", colors[index]);
}
}
namespace language
{
namespace french
{
std::string colors[] = {"Blanc", "Rouge", "Noir"};
void colorName(int index)
{
std::println("La couleur est : {}", colors[index]);
}
}
}
// Promote language namespace in the global namespace
using namespace language;
int main()
{
// GCC: error: 'colorName' was not declared in this scope
// colorName(1);
// OK: we specify the namespace for the colorName function
english::colorName(1);
// following brackets { } are to show scope limitation
{
using namespace french;
colorName(1); // -> "Rouge"
} // end of scope for the using namespace french directive
// Promote english namespace in the global namespace
using namespace english;
colorName(1); // -> "Red"
french::colorName(1); // -> "Rouge"
// Promote french namespace in the global namespace
using namespace french;
// GCC: error: call of overloaded 'colorName(int)' is ambiguous
// colorName(1);
return 0;
}1242.2_01.04_CinCout
main.cpp
#include <iostream>
#include <iomanip>
#include <limits>
int main()
{
// Store the current formatting flags, precision and fill character of std::cout
auto flags = std::cout.flags();
auto precision = std::cout.precision();
auto fill = std::cout.fill();
std::cout << std::setfill('.')
<< std::setw(25) << std::right << "Column 1"
<< "Column 3"
<< "\n"
<< std::setw(10) << std::left << "Column 2\n";
std::cout << std::setprecision(5) << std::fixed << std::setw(25)
<< std::left << 158.82589 << std::endl
<< std::setw(10) << std::left << 456.10288432 // --> 456.10288
<< std::endl;
std::cout << std::hex << std::uppercase
<< std::setw(25) << std::left << 255
<< std::setw(10) << std::left << 128 // Note: the format is still hex
<< std::endl;
std::cout << std::setw(25) << std::left << std::boolalpha << true //--> "true"
<< std::setw(10) << std::left << false //--> "false"
<< std::endl;
std::cout << true << std::endl; //--> "true"
std::cout << std::noboolalpha << true << std::endl; //--> "1"
// Reset std::cout to default formatting
std::cout.flags(flags);
std::cout.precision(precision);
std::cout.fill(fill);
int n;
std::cin >> n;
std::cout << "val " << n;
int j = 10;
std::cout << std::hex << std::nouppercase << j << std::endl;
std::cout << std::hex << std::uppercase << j << std::endl;
std::cout << std::dec << std::showpos << j << std::endl;
int N = 0;
std::cout << "Enter a number between 1 and 6: ";
while (!(std::cin >> N) || N < 1 || N > 6)
{
if (std::cin.fail())
{
std::cout << "Wrong input, try again: ";
std::cin.clear();
std::cin.ignore(256, '\n');
}
else
{
std::cout << "The number is out of range: ";
}
}
return 0;
}1242.2_01.05_Print
C++23
La fonction std::print() affiche du texte formaté de manière plus simple que les fonctions d’affichage précédentes.
En particulier, les modificateurs de formatage sont locaux à l’appel de la fonction std::print() et ne sont pas persistants.
main.cpp
#include <print>
#include <string>
int main()
{
// C++20/23: std::format syntax with {:.Nf} instead of std::setprecision
double pi = 3.1415926535897932384626433832795;
std::println("{:.2f}", pi);
std::println("{:.8f}", pi);
std::println("{:.4e}", pi);
std::println("{:.2f}", pi);
// C++23: print and println instead of std::cout and std::endl
std::string firstname = "Donald";
std::string lastname = "Knuth";
int answerToEverything = 42;
std::println("Hello, {} {}!", firstname, lastname);
std::print("The answer is = {}\n", answerToEverything);
return 0;
}1242.2_01.06_References
main.cpp
#include <print>
#include <string>
#include <stdexcept>
int &getRefOnCount()
{
static int count = 0;
return count;
}
const int N = 2;
std::string names[N] = {"Bob", "John"};
int ages[N] = {20, 30};
int &age(const std::string &name)
{
for (int i = 0; i < N; i++)
{
if (name == names[i])
return ages[i];
}
// If we are here, the name was not found
// See chapter on exceptions for more details
throw std::out_of_range("name not found");
}
int main()
{
double d1 = 1.0;
double &rd1 = d1;
std::println("double");
// sizeof(ref) is the size of the variable it references
std::println(" - Address for d1 = {} {}", static_cast<const void*>(&d1), sizeof(d1));
std::println(" - Address for rd1 = {} {}", static_cast<const void*>(&rd1), sizeof(rd1));
std::println("");
int i1 = 10;
int &ri1 = i1;
std::println("int");
// sizeof(ref) is the size of the variable it references
std::println(" - Address for i1 = {} {}", static_cast<const void*>(&i1), sizeof(i1));
std::println(" - Address for ri1 = {} {}", static_cast<const void*>(&ri1), sizeof(ri1));
std::println("");
struct STRUCT
{
double x, y, z;
};
// Note: no need for struct keyword in C++
STRUCT varStruct{1.0, 2.0, 3.0};
STRUCT &refStruct = varStruct;
std::println("STRUCT");
// sizeof(ref) is the size of the variable it references
std::println(" - Address for varStruct = {} {}", static_cast<const void*>(&varStruct), sizeof(varStruct));
std::println(" - Address for refStruct = {} {}", static_cast<const void*>(&refStruct), sizeof(refStruct));
// getRefOnCount() returns a reference on the static variable count
// So we modify count directly
std::println("Count: {}", getRefOnCount()++);
std::println("Count: {}", ++getRefOnCount());
for (int i = 0; i < N; i++)
{
std::println("{} {}", names[i], ages[i]);
}
age("Bob") = 50;
for (int i = 0; i < N; i++)
{
std::println("{} {}", names[i], ages[i]);
}
age("John")++;
for (int i = 0; i < N; i++)
{
std::println("{} {}", names[i], ages[i]);
}
return 0;
}1242.2_01.07_MemoryAllocation
main.cpp
#include <print>
int main()
{
// [[maybe_unused]] to avoid the compiler warning about an unused variable
// GCC: warning: variable 'x' set but not used [-Wunused-but-set-variable]
[[maybe_unused]] int *x = nullptr;
// See chapter on exceptions for more details
try
{
for (int n = 1;; n++)
{
std::println("{}", n);
// throws std::bad_alloc if no more memory is available
x = new int[1024 * 1024];
// Comment to provoke a memory leak
delete[] x;
}
}
// See chapter on exceptions for more details
catch (const std::bad_alloc &e)
{
std::println("Memory allocation failed: {}", e.what());
}
return 0;
}1242.2_01.08_Strings
main.cpp
#include <print>
#include <string>
int main()
{
std::string x = "Hello";
// Or
// auto x = std::string("Hello");
std::string y = x;
std::string z = x + "_" + y;
std::println("{} {} {}", x, y, z);
std::println("cap: {}", z.capacity());
std::println("size: {}", z.size());
// C++14: string literals
// Need to add "using namespace std::string_literals;"
using namespace std::string_literals;
auto s = "Hello"s;
return 0;
}1242.2_01.09_Vectors
main.cpp
#include <string>
#include <vector>
using Line = std::vector<double>;
using Matrix = std::vector<Line>;
int main()
{
// {10, 11}
std::vector<int> myVector1{10,11};
// {10.0, 11.0}
std::vector<double> myVector2;
myVector2.push_back(10.0);
myVector2.push_back(11.0);
// {5, 5}
std::vector<int> myVector3(2,5);
// {10, 11}
myVector3[0]=10;
myVector3[1]=11;
Matrix m(5);
for (int i = 0; i < 5; ++i)
{
m[i].resize(5); // rows size is 5
for (int j = 0; j < 5; ++j)
{
if (i == j)
{
m[i][j] = 1;
}
else
{
m[i][j] = 0;
}
}
}
return 0;
}1242.2_01.10_Double2String
main.cpp
#include <string>
#include <sstream>
#include <iomanip>
#include <print>
int main()
{
auto pi = 3.1415926535897932384626433832795;
// C++11: std::to_string, with no control over the format
auto s1 = std::to_string(pi);
std::print("C++11: std::to_string: {}\n", s1);
// C++11: std::ostringstream, with control over the format
std::ostringstream oss;
oss << std::fixed << std::setprecision(2) << pi;
auto s2 = oss.str();
std::print("C++11: std::ostringstream: {}\n", s2);
// C++20: std::format
auto s3 = std::format("{:.2f}", pi);
std::print("C++20: std::format: {}\n", s3);
}1242.2_01.11_DefaultParameters
main.cpp
#include <vector>
#include <print>
#include <algorithm>
void sort(const std::vector<int> &v, bool ascending = true)
{
auto sorted = v;
if (ascending)
{
std::sort(sorted.begin(), sorted.end());
}
else
{
std::sort(sorted.rbegin(), sorted.rend());
}
std::print("Sorted vector: ");
for (const auto &elem : sorted)
{
std::print("{} ", elem);
}
std::print("\n");
}
int main()
{
auto v = std::vector<int>{5, 2, 9, 1, 5, 6};
sort(v);
sort(v, false);
}1242.2_01.12_FunctionsOverloading
main.cpp
#include <print>
int add(int a, int b)
{
return a + b;
}
int add(int a, int b, int c)
{
return a + b + c;
}
double add(double a, double b)
{
return a + b;
}
double add(double a, double b, double c)
{
return a + b + c;
}
int main()
{
// Same name, different parameters
std::println("add(2, 3) = {}", add(2, 3));
std::println("add(2.5, 3.5) = {}", add(2.5, 3.5));
std::println("add(2, 3, 4) = {}", add(2, 3, 4));
std::println("add(2.5, 3.5, 4.5) = {}", add(2.5, 3.5, 4.5));
}Les types de containers dans la bibliothèque standard #
Série 1.1 #
Exercice 1 : affichage #
Compléter le code suivant :
bool isNumber = true;
std::cout << isNumber << " " << !isNumber << std::endl;
std::cout << isNumber << " " << !isNumber << std::endl;
int x = 15;
std::cout << x << " " << x << " " << x << std::endl;
std::cout << x << " " << x << " " << x << std::endl;
double dbl = -5345.123456789;
std::cout << dbl << std::endl;
std::cout << dbl << std::endl;
std::cout << dbl << std::endl;
std::cout << dbl << std::endl;de manière à obtenir le résultat suivant:
true false
1 0
hexadecimal: f decimal: 15 octal: 17
15 15 15
-5345.12
-5345.12345679
-5.3451e+03
-5345.12Exercice 2 : surcharge de fonctions #
Écrire deux fonctions
minimum()qui retournent le plus petit des 2 nombres passés en arguments. La première utilise des nombres entiers (int) et la seconde des nombres décimaux (double).Laquelle de ces fonctions sera appelée si on lui passe les paramètres suivants :
minimum(7, 3),minimum(7.0, 3),minimum(7, 3.0)etminimum(7.0, 3.0)?Que se passe-t-il si on supprime la méthode qui reçoit deux entiers en arguments ?
Pour aller plus loin : Résolution de surcharge et conversions implicites
Exercice 3 : passage de paramètres #
Écrire des fonctions <return> divide(dividend, divisor, <other_params>) qui, à partir de deux entiers passés en paramètre, retournent le quotient et le reste de la division entière.
Exemple
13 divisé par 2 donne un quotient de 6 et un reste de 1.
Tester les différentes possibilités de passage de paramètres en C++. Lesquelles vous semblent les plus appropriées à ce problème, et pourquoi ?
Exercice 4 : string #
Écrire un programme qui :
- utilise une fonction
askForAString()demandant à l’utilisateur de saisir une phrase et renvoyant cette phrase au programme principal sous la forme d’un pointeurchar*. Le programme déclarera ensuite une variable de typestringpour y copier cette phrase et en calculer sa longueur avec la fonctionsize(). Une fois la copie faite, libérer la mémoire allouée dynamiquement et afficher le message contenu dans lestring.
Bonus : concaténer au string des points (’.’) jusqu’à concurrence de sa capacité.
Consigne : gérer l’allocation dynamique et la récupération de la mémoire avec les opérateurs C++ new et delete.
Exercice 5 : range-based for loop #
Compléter le programme suivant :
- remplacer la boucle
forsuivante par une bouclerange-based - copier les valeurs du tableau
primeNumbersdans le tableaucopie
Pourquoi ne peut-on pas faire cette copie SIMPLEMENT avec le nouveau for ?
#include <iostream>
int main()
{
int primeNumbers[] = {2, 3, 5, 7, 11, 13, 17};
int copy[7] = {0, 0, 0, 0, 0, 0, 0};
int sizeArray = sizeof(primeNumbers) / sizeof(primeNumbers[0]);
//TODO
for (int i=0; i < sizeArray; i++)
{
std::cout << primeNumbers [i] << std::endl;
}
// TODO
return 0;
}Exercice 6 : structure #
Définir une structure
Roomcapable de contenir les dimensions d’une chambre (largeur, longueur, hauteur), de lui donner un nom à l’aide d’un champ de typestring, et possédant les fonctions suivantes :surfaceFloor(): calcule et renvoie la surface au sol de la piècesurfaceWalls(): calcule et renvoie la surface des murs de la piècevolume(): calcule et renvoie le volume de la pièce
Écrire un programme utilisant ce nouveau type, qui lui affecte des valeurs et utilise ses fonctions (méthodes)