Copy of https://perso.isima.fr/loic/cpp/tp01.en.php
tete du loic

 Loïc YON [KIUX]

  • Enseignant-chercheur
  • Référent Formation Continue
  • Responsable des contrats pros ingénieur
  • Référent entrepreneuriat
  • Responsable de la filière F2 ingénieur
  • Secouriste Sauveteur du Travail
mail
loic.yon@isima.fr
phone
(+33 / 0) 4 73 40 50 42
location_on
Institut d'informatique ISIMA
  • twitter
  • linkedin
  • viadeo

[++C] PW 1

 This page might be outdated. Please email me if you found something incorrect.
Lire en Français

First publication date : 2020/03/26

You will discover the differences between C and C++ languages with these first exercises. No OOP for this !

From C to C++

"Hello world"

#include <iostream>

int main(int argc, char ** argv) {
  for(int i=0; i< 120; ++i)
    std::cout << "Hi guys ! " << std::endl;

  return 0;
}

<< is called the insertion operator. You can read it as "put to".

Standard (keyboard) input

#include <iostream>
#include <string>

int main(int, char **) {
  std::string first; // special type for characters strings
  int age;

  std::cout << "What is your first name ?" << std::endl;
  std::cin >> first;
  std::cout << "How old are you ?" << std::endl;
  std::cin >> age ;
  std::cout << "Hi "<< first << std::endl;

  return 0;
}

>> is called the extraction operator. You can read it as "get from".

std::string is a type that represents the characters string in C++. You will NEVER AGAIN need to handle char * (except in particular situations like a lecture for example).

Handling standard "objects" with the prefix std:: can be tedious. One instruction can help using namespace std; ou using std::cout;. Usually developers love the last one !

Arrays and constants

You can compile the following code in C or C++ (if you put aside the calls to std::cout).

If you want to keep the display feature, you can use the printf C function because any C++ program can call the C libraries. Only header files change : for example, stdlib.h becomes cstdlib.

#include <iostream>

using std::cout;
using std::endl;

/* The const keyword can be used to define the size of n static array */
/* no #define anymore                                                 */
const int SIZE = 10;

int main(int, char **) {
  int tab[SIZE];
  
  for (int i=0; i < SIZE; ++i) {
    tab[i] = i %2;
    cout << tab[i] << " ";
  }

  cout << endl;

  return SIZE;
}

Function overloading

Put this code in a .c file and compile with gcc. Note the errors.

#include <stdio.h>

void display(int a) {
  printf("%d", a);
}

void display(double a) {
  printf("%lf", a);
}

int main(int, char **) {
  display(1);
  display(2.0);

  return 0;
}

If the file is a .cpp one and is compiled with gcc OR if the .c file is compiled with g++, you won't have the error messages!

String

A specific note on strings is available.

Run the following code and look what is going on with the different versions of s :

#include <iostream>
int main() {

  char s[10];
  // std::string s;
  // char *      s;

  std::cin >> s;

  std::cout << "#" << s << "#" << std::endl;
  for (int i = 0; i< 10; ++i)
    std::cout << "@" << s[i] << "@" << (int)s[i] << "@" << std::endl;

  return 0;
}

References

First use


#include <iostream>

void function1(int a) {
  a = 3;
}

void function2(int* p) {
  *p = 5;
}

void function3(int& b) {
  b = 7;
}

int main(int, char **) {
  int a = 1;

  std::cout << a << std::endl;
  function1(a);
  std::cout << a << std::endl;
  function2(&a);
  std::cout << a << std::endl;
  function3(a);
  std::cout << a << std::endl;

  return 0;
}

But what happened ?

More...


#include <iostream>

void function1(int a) {
  std::cout << &a << std::endl;
}

void function2(int& a) {
  std::cout << &a << std::endl;
}

int main(int, char **) {
  int age = 2021-1983;

  std::cout << age << std::endl;
  std::cout << &age << std::endl;
  function1(age);
  std::cout << &age << std::endl;
  function2(age);
  std::cout << &age << std::endl;

  return 0;
}

Variables swap

Try the following code:

int  a = 3;
int  b = a;
int& c = a;

std::cout << a << " " << b << " " << c << std::endl;
b = 4;
std::cout << a << " " << b << " " << c << std::endl;
c = 5;
std::cout << a << " " << b << " " << c << std::endl;
a = 6;
std::cout << a << " " << b << " " << c << std::endl;

Write a function that allows swapping parameters of int type

Compare the ease to write and understand the different versions.

Introduction to valgrind

valgrind is a very handful tool to detect faulty programs during execution : you will notice context errors and memory allocation errors

Let's see this piece of code :

#include <iostream>

int main(int , char ** ) {
  int i;

  while (i<10) {}
    std::cout << i << std::endl;
    ++i;
  }

  std::cout << "end of program" << std::endl;

  return 0;
}

You can find the error by yourself but we will try it the valgrind way. Let's compile (do not forget the -g option):


$ g++ -Wall -Wextra -g valtest.cpp
$ ./a.out

The fun is that on some machines, it can work, on others it can crash. Let's try a first analysis:


$ valgrind ./a.out

and a more complete one:


$ valgrind --track-origins ./a.out

It is now pretty clear, isn't it ?

Simple dynamic memory allocation

Execute valgrind on these two examples and correct them ! Here is the first:

int main(int, char**) {
   int * p = new int;

   *p = 3;
   cout << *p << endl;

   return 0;
}

Now, the second one:

int main(int, char**) {
   const int SIZE = 500;

   int * p = new int[SIZE];

   for(auto i = 0; i< SIZE; ++i ) p[i] = i;
   for(auto i = 0; i< SIZE; ++i ) cout << p[i] << endl;

   return 0;
}