C++ PROGRAMMING LANGUAGE: NAMESPACE AND MANGEMENT OF INPUT/OUTPUT WITH C++. CAAM 519, CHAPTER 15 This chapter introduces the notion of namespace. We also describe how to manage input and output with C++ commands via the terminal or files. 1. Namespace The notion of namespace was introduced in C++ to allow the creation of a space that contains various entities like variables, pointers, functions and classes. The use of namespaces allows a program (or the standard of a programming language) to define multiple variables with the same name. Similarly functions with the same name and arguments can also be defined in different namespaces. This feature allows to prevent name conflict in large C++ projects and to greatly reduce the number of keywords defined by the C++ programming language. The following describes how to define namespace and get access to their entities. 1.1. Definition of namespace. A namespace is defined with the keyword namespace as follows namespace my_ space { // entities definition or declaration double a1, a2; where my space is the name given to the namespace. A namespace can contain various entities such as variables, pointers, objects of class, classes and functions. A member of my space is made accessible by adding the prefix my space:: to its name. For instance, the member a1 is accessed as follows: my_space :: a1 =5.0; where we assume that the namespace was defined (or included) in previous instructions. An entity of a namespace can be initialized to a value, or via a constructor for a class s object, inside the namespace. A functions entity can also be defined outside the namespace. In that case, the namespace only provides a prototype of the function. namespace my_ space { double a1, a2; void print ( void ); void my_space :: print ( void ){ 1
2 1.2. The keyword using. After defining the namespace my space, or including it via a header file that contains its definition, we can add the following instructions into our program using namespace my_ space ; It allows us to have access to the members of my space without adding the prefix my space::. The keyword using can also be associated to one entity of a namespace as follows: using my_space :: a1; The member a1 of my space can then be referred as a1 and not my space::a1. We refer to the example ex41 namespace.cc for more details. 1.3. The namespace std. Many features provided by C++ via the include of a standard library have their members defined as entities of the namespace std. As a consequence, we have to add the instructions std:: before referring to a standard function like cout (write info on terminal) or endl (end of line). 2. Input and output with the terminal This section provides information on how to display or read information to/from terminal command using C++ command. We focus on two command named std::cout and std::cin that are both part of the library iostream. We refer to the chapter 8 for the management of input/output via a terminal with C commands (see printf and scanf). 2.1. Write information on a terminal. As introduced previously in the course, the command cout allows to write information on a terminal. This command is part of the namespace std and its name stands for standard console output. It can be used as follows: int i =60; std :: cout << "My age is " << i << "\n"; where the command end of line \n can be changed to std::endl. Unlike with the C function printf, there is no need to specify the type of a variable that is printed on the terminal with std::cout. 2.2. Read information from a terminal. A user can give data to a program during its execution with the command std::cin. Its structure is similar to std::cout as the left arrows becomes right arrows. Here is a short example: int i; std :: cout << " Type your age : "; std :: cin >> i; Similarly to the function scanf, the function cin can fails when the input data has not the proper format. For instance, in the above example typing 42xft is considered to be 42 by cin. Typing an input that does not even start by a number can lead to undefined behavior like skipping next cin or setting the input to zero. We refer to the example ex42 input output stream.cc for more details.
C++ PROGRAMMING LANGUAGE: INTRODUCTION. 3 3. Read and write information with a file This section introduces the functions of C++ that allows to read and write information from and into a files. These features use the standard library iostream and fstream that we consider to be included in all the following examples. We refer to the chapter 8 of this course for information on how such operations can be done using functions of C. 3.1. Open and close a file. Unlike C that allows the creation of unique type of stream with the keyword FILE, C++ allows to create three different kind of streams with the following keywords. std::ofstream. Stream class to write in files. std::ifstream. Stream class to read from files. std::fstream. Stream class that allows to read and write from/in a file. After declaring a stream of one of the above three classes, the stream can be used to open and close file as follows. std :: fstream file ; file. open ( name_file, opening_mode ); file. close (); where the opening mode is a combination of the following modes. ios::in. Open a file to read. ios::out. Open a file to write. ios::trunc. If a file openend to write already exists, its content is removed. ios::ate. Set position of the stream at the end of the file. ios::app. All output are written at the end of the file. Can only be used to write in a file. ios::binary. Open a file in binary mode. The combination of multiple opening modes is done by adding the character between two different modes. The following example shows how to open a file named test file to write in it (ios::out). In addition, if the file already exists we remove its content with the option ios::trunc. std :: ofstream file_ out ; file. open (" test_file ", ios :: out ios :: trunc ); file. close (); Remark: The stream of C++ have a default mode that is used when the user does not provide a second argument (opening mode) when opening a file. A stream of type ofstream has a default mode of ios::out, ifstream a default mode of ios::in and fstream a default mode of ios::in ios::out. 3.2. Write information in a file. Information can be written on a file using the operator << as follows. std :: ofstream file_ out ; file_out. open (" name_file ", ios :: in ); // open file at begining file_out << " Hello \n"; file_ out << " Hello on line 2"; file_out. close ();
4 The operator << does not need to know the type of data that is written in the file. More details are provided in the example ex42 input output stream.cc. 3.3. Read information from a file. Information can be read on a file using the operator >>. This operator reads information till meeting a blank space or a end of line. It then moves the stream position after the blank space or to the next line. Assume a file name file contains an integer and a double (either on the first line or on the two first lines), these variable can be read as follows. std :: ifstream file_ in ; file_in. open (" name_file ", ios :: out ); // open file at begining int i; double d; file_ in >> i; // assuming file_ in >> d; // assuming file_in. close (); It is possible to read multiple consecutive variable as follows. file_ in >> i >> d; The full content of the current line of a stream can be read with the function std::getline. The content is saved in a variable of type string. string line std :: getline ( myfile, line ); Note that reading information of a file require to know how the file is structured. It leads us to introduce features that allow to modify the location of a stream in the next section. 3.4. Location of stream in a file. The position of a stream in a file can be changes using the function seekg and seekp that respectively means seek put and seek get. The first function is used when a stream is used to write data (output) while the second function is used when a stream is used to read data (input). They have the following structures: seekg (offset, direction) seekp (offset, direction) where the offset if a number of bytes to skip and direction is a position in the file such as: ios::beg for the beginning of the file. ios::cur for the current position of the stream in the file. ios::end for the end of the file. Modifying the position of a stream using the above functions to read or write data in a specific position of a file is not always easy. An other way to change the position is to use the function std::getline to copy the content of the current line in a stream. Then the content of the line can be compared to a known string. It allows to read information from a data that is well structured, meaning the time step is on the line under Time Step, etc. We refer to the example ex42 input output stream.cc for more details on how to read information from a data file.
C++ PROGRAMMING LANGUAGE: INTRODUCTION. 5 3.5. Overloading stream operator. The C++ programming language allows to overload the operators << and >> such that information related to an object of a class can be written or read from a file. Unlike classic operators, like the addition or the equality operators, the left hand side of the operator is not an object of the class but a stream. As a consequence, it has to be overload via a function or a friend function if protected/private members need to be accessed. For instance, we can overload the operator << so it writes a vector of the class Vector introduced in the example ex28 class vec.cc as follows. std :: ostream & operator < <( std :: ostream & os, Vector & vector ){ int n = vector. GetLengthVector (); for ( int i =0; i<n; i ++){ os << vector. vec [i] <<std :: endl ; where ostream is the base class that is used to derive the class ofstream. Note it is possible to declare the above operator as a friend of the class Vector to give it access to private and protected members of the class. However it is not recommended as modifying private data may rise issue if other data depends of them and are not modified accordingly. The above operator can the be used with std::cout to print a vector on a terminal or with a ofstream to write it in a file. Vector vec1 ; std :: cout << vec1 ; std :: ofstream myfile ; myfile. open (" test "); myfile << vec1 ; myfile. close ();