Blog

  • Data Types

    For using any language, you need to understand the basic data types the language supports. In this chapter, we will discuss 7 basic data types supported by the elixir language: integers, floats, Booleans, atoms, strings, lists and tuples.

    Numerical Types

    Elixir, like any other programming language, supports both integers and floats. If you open your elixir shell and input any integer or float as input, it’ll return its value. For example,

    42
    

    When the above program is run, it produces the following result −

    42
    

    You can also define numbers in octal, hex and binary bases.

    Octal

    To define a number in octal base, prefix it with ‘0o’. For example, 0o52 in octal is equivalent to 42 in decimal.

    Hexadecimal

    To define a number in decimal base, prefix it with ‘0x’. For example, 0xF1 in hex is equivalent to 241 in decimal.

    Binary

    To define a number in binary base, prefix it with ‘0b’. For example, 0b1101 in binary is equivalent to 13 in decimal.

    Elixir supports 64bit double precision for floating point numbers. And they can also be defined using an exponentiation style. For example, 10145230000 can be written as 1.014523e10

    Atoms

    Atoms are constants whose name is their value. They can be created using the color(:) symbol. For example,

    :hello

    Booleans

    Elixir supports true and false as Booleans. Both these values are in fact attached to atoms :true and :false respectively.

    Strings

    Strings in Elixir are inserted between double quotes, and they are encoded in UTF-8. They can span multiple lines and contain interpolations. To define a string simply enter it in double quotes −

    "Hello world"

    To define multiline strings, we use a syntax similar to python with triple double quotes −

    """
    Hello
    World!
    """

    We’ll learn about strings, binaries and char lists(similar to strings) in depth in the strings chapter.

    Binaries

    Binaries are sequences of bytes enclosed in << >> separated with a comma. For example,

    << 65, 68, 75>>

    Binaries are mostly used to handle bits and bytes related data, if you have any. They can, by default, store 0 to 255 in each value. This size limit can be increased by using the size function that says how many bits it should take to store that value. For example,

    <<65, 255, 289::size(15)>>
    

    Lists

    Elixir uses square brackets to specify a list of values. Values can be of any type. For example,

    [1, "Hello", :an_atom, true]
    

    Lists come with inbuilt functions for head and tail of the list named hd and tl which return the head and tail of the list respectively. Sometimes when you create a list, it’ll return a char list. This is because when elixir sees a list of printable ASCII characters, it prints it as a char list. Please note that strings and char lists are not equal. We’ll discuss lists further in later chapters.

    Tuples

    Elixir uses curly brackets to define tuples. Like lists, tuples can hold any value.

    { 1, "Hello", :an_atom, true 

    A question arises here, – why provide both lists and tuples when they both work in the same way? Well they have different implementations.

    • Lists are actually stored as linked lists, so insertions, deletions are very fast in lists.
    • Tuples on the other hand, are stored in contiguous memory block, which make accessing them faster but adds an additional cost on insertions and deletions.
  • Data Types

    One of the most fundamental characteristics of a programming language is the set of data types it supports. These are the type of values that can be represented and manipulated in a programming language.

    The Dart language supports the following types−

    • Numbers
    • Strings
    • Booleans
    • Lists
    • Maps

    Numbers

    Numbers in Dart are used to represent numeric literals. The Number Dart come in two flavours −

    • Integer − Integer values represent non-fractional values, i.e., numeric values without a decimal point. For example, the value “10” is an integer. Integer literals are represented using the int keyword.
    • Double − Dart also supports fractional numeric values i.e. values with decimal points. The Double data type in Dart represents a 64-bit (double-precision) floating-point number. For example, the value “10.10”. The keyword double is used to represent floating point literals.

    Strings

    Strings represent a sequence of characters. For instance, if you were to store some data like name, address etc. the string data type should be used. A Dart string is a sequence of UTF-16 code units. Runes are used to represent a sequence of UTF-32 code units.

    The keyword String is used to represent string literals. String values are embedded in either single or double quotes.

    Boolean

    The Boolean data type represents Boolean values true and false. Dart uses the bool keyword to represent a Boolean value.

    List and Map

    The data types list and map are used to represent a collection of objects. A List is an ordered group of objects. The List data type in Dart is synonymous to the concept of an array in other programming languages. The Map data type represents a set of values as key-value pairs. The dart: core library enables creation and manipulation of these collections through the predefined List and Map classes respectively.

    The Dynamic Type

    Dart is an optionally typed language. If the type of a variable is not explicitly specified, the variable’s type is dynamic. The dynamic keyword can also be used as a type annotation explicitly.

  • Basic Syntax

    We will start with the customary ‘Hello World’ program.

    To start the Elixir interactive shell, enter the following command.

    iex
    

    After the shell starts, use the IO.puts function to “put” the string on the console output. Enter the following in your Elixir shell −

    IO.puts "Hello world"

    In this tutorial, we will use the Elixir script mode where we will keep the Elixir code in a file with the extension .ex. Let us now keep the above code in the test.ex file. In the succeeding step, we will execute it using elixirc

    IO.puts "Hello world"

    Let us now try to run the above program as follows −

    $elixirc test.ex

    The above program generates the following result −

    Hello World
    

    Here we are calling a function IO.puts to generate a string to our console as output. This function can also be called the way we do in C, C++, Java, etc., providing arguments in parentheses following the function name −

    IO.puts("Hello world") 
    

    Comments

    Single line comments start with a ‘#’ symbol. There’s no multi-line comment, but you can stack multiple comments. For example −

    #This is a comment in Elixir
    

    Line Endings

    There are no required line endings like ‘;’ in Elixir. However, we can have multiple statements in the same line, using ‘;’. For example,

    IO.puts("Hello"); IO.puts("World!")

    The above program generates the following result −

    Hello 
    World!
    

    Identifiers

    Identifiers like variables, function names are used to identify a variable, function, etc. In Elixir, you can name your identifiers starting with a lower case alphabet with numbers, underscores and upper case letters thereafter. This naming convention is commonly known as snake_case. For example, following are some valid identifiers in Elixir −

    var1       variable_2      one_M0r3_variable
    

    Please note that variables can also be named with a leading underscore. A value that is not meant to be used must be assigned to _ or to a variable starting with underscore −

    _some_random_value = 42
    

    Also elixir relies on underscores to make functions private to modules. If you name a function with a leading underscore in a module, and import that module, this function will not be imported.

    There are many more intricacies related to function naming in Elixir which we will discuss in coming chapters.

    Reserved Words

    Following words are reserved and cannot be used as variables, module or function names.

    after     and     catch     do     inbits     inlist     nil     else     end 
    not     or     false     fn     in     rescue     true     when     xor 
    __MODULE__    __FILE__    __DIR__    __ENV__    __CALLER__ 
    
  • Syntax

    Syntax defines a set of rules for writing programs. Every language specification defines its own syntax. A Dart program is composed of −

    • Variables and Operators
    • Classes
    • Functions
    • Expressions and Programming Constructs
    • Decision Making and Looping Constructs
    • Comments
    • Libraries and Packages
    • Typedefs
    • Data structures represented as Collections / Generics

    Your First Dart Code

    Let us start with the traditional “Hello World” example −

    main() { 
       print("Hello World!"); 
    }

    The main() function is a predefined method in Dart. This method acts as the entry point to the application. A Dart script needs the main() method for execution. print() is a predefined function that prints the specified string or value to the standard output i.e. the terminal.

    The output of the above code will be −

    Hello World!
    

    Execute a Dart Program

    You can execute a Dart program in two ways −

    • Via the terminal
    • Via the WebStorm IDE

    Via the Terminal

    To execute a Dart program via the terminal −

    • Navigate to the path of the current project
    • Type the following command in the Terminal window
    dart file_name.dart
    

    Via the WebStorm IDE

    To execute a Dart program via the WebStorm IDE −

    • Right-click the Dart script file on the IDE. (The file should contain the main() function to enable execution)
    • Click on the ‘Run <file_name>’ option. A screenshot of the same is given below −
    Run Test1 Dart

    One can alternatively click theRun Buttonbutton or use the shortcut Ctrl+Shift+F10 to execute the Dart Script.

    Dart Command-Line Options

    Dart command-line options are used to modify Dart Script execution. Common commandline options for Dart include the following −

    Sr.NoCommand-Line Option & Description
    1-c or –cEnables both assertions and type checks (checked mode).
    2–versionDisplays VM version information.
    3–packages <path>Specifies the path to the package resolution configuration file.
    4-p <path>Specifies where to find imported libraries. This option cannot be used with –packages.
    5-h or –helpDisplays help.

    Enabling Checked Mode

    Dart programs run in two modes namely −

    • Checked Mode
    • Production Mode (Default)

    It is recommended to run the Dart VM in checked mode during development and testing, since it adds warnings and errors to aid development and debugging process. The checked mode enforces various checks like type-checking etc. To turn on the checked mode, add the -c or –-checked option before the script-file name while running the script.

    However, to ensure performance benefit while running the script, it is recommended to run the script in the production mode.

    Consider the following Test.dart script file −

    void main() { 
       int n = "hello"; 
       print(n); 
    } 

    Run the script by entering −

    dart Test.dart
    

    Though there is a type-mismatch the script executes successfully as the checked mode is turned off. The script will result in the following output −

    hello
    

    Now try executing the script with the “- – checked” or the “-c” option −

    dart -c Test.dart 
    

    Or,

    dart - - checked Test.dart
    

    The Dart VM will throw an error stating that there is a type mismatch.

    Unhandled exception: 
    type 'String' is not a subtype of type 'int' of 'n' where 
       String is from dart:core 
       int is from dart:core 
    #0  main (file:///C:/Users/Administrator/Desktop/test.dart:3:9) 
    #1  _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart :261) 
    #2  _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

    Identifiers in Dart

    Identifiers are names given to elements in a program like variables, functions etc. The rules for identifiers are −

    Identifiers can include both, characters and digits. However, the identifier cannot begin with a digit.

    • Identifiers cannot include special symbols except for underscore (_) or a dollar sign ($).
    • Identifiers cannot be keywords.
    • They must be unique.
    • Identifiers are case-sensitive.
    • Identifiers cannot contain spaces.

    The following tables lists a few examples of valid and invalid identifiers −

    Valid identifiersInvalid identifiers
    firstNameVar
    first_namefirst name
    num1first-name
    $result1number

    Keywords in Dart

    Keywords have a special meaning in the context of a language. The following table lists some keywords in Dart.

    abstract 1continuefalsenewthis
    as 1defaultfinalnullthrow
    assertdeferred 1finallyoperator 1true
    async 2doforpart 1try
    async* 2dynamic 1get 1rethrowtypedef 1
    await 2elseifreturnvar
    breakenumimplements 1set 1void
    caseexport 1import 1static 1while
    catchexternal 1insuperwith
    classextendsisswitchyield 2
    constfactory 1library 1sync* 2yield* 2

    Whitespace and Line Breaks

    Dart ignores spaces, tabs, and newlines that appear in programs. You can use spaces, tabs, and newlines freely in your program and you are free to format and indent your programs in a neat and consistent way that makes the code easy to read and understand.

    Dart is Case-sensitive

    Dart is case-sensitive. This means that Dart differentiates between uppercase and lowercase characters.

    Statements end with a Semicolon

    Each line of instruction is called a statement. Each dart statement must end with a semicolon (;). A single line can contain multiple statements. However, these statements must be separated by a semicolon.

    Comments in Dart

    Comments are a way to improve the readability of a program. Comments can be used to include additional information about a program like author of the code, hints about a function/ construct etc. Comments are ignored by the compiler.

    Dart supports the following types of comments −

    • Single-line comments ( // ) − Any text between a “//” and the end of a line is treated as a comment
    • Multi-line comments (/* */) − These comments may span multiple lines.

    Example

    // this is single line comment  
      
    /* This is a   
       Multi-line comment  
    */ 

    Object-Oriented Programming in Dart

    Dart is an Object-Oriented language. Object Orientation is a software development paradigm that follows real-world modelling. Object Orientation considers a program as a collection of objects that communicate with each other via mechanism called methods.

    • Object − An object is a real-time representation of any entity. As per Grady Brooch, every object must have three features −
      • State − described by the attributes of an object.
      • Behavior − describes how the object will act.
      • Identity − a unique value that distinguishes an object from a set of similar such objects.
    • Class − A class in terms of OOP is a blueprint for creating objects. A class encapsulates data for the object.
    • Method − Methods facilitate communication between objects.

    Example: Dart and Object Orientation

    class TestClass {   
       void disp() {     
    
      print("Hello World"); 
    } } void main() { TestClass c = new TestClass(); c.disp(); }

    The above example defines a class TestClass. The class has a method disp(). The method prints the string “Hello World” on the terminal. The new keyword creates an object of the class. The object invokes the method disp().

    The code should produce the following output −

    Hello World
    
  • Environment

    This chapter discusses setting up the execution environment for Dart on the Windows platform.

    Executing Script Online with DartPad

    You may test your scripts online by using the online editor at https://dartpad.dev/. The Dart Editor executes the script and displays both HTML as well as console output. The online editor is shipped with a set of preset code samples.

    A screenshot of the Dartpad editor is given below −

    Dartpad

    Dartpad also enables to code in a more restrictive fashion. This can be achieved by checking the Strong mode option on the bottom right of the editor. Strong mode helps with −

    • Stronger static and dynamic checking
    • Idiomatic JavaScript code generation for better interoperability.

    You may try the following example using Dartpad

    void main() { 
       print('hello world'); 
    }

    The code will display the following output

    hello world
    

    Setting Up the Local Environment

    In this section, let us see how to set up the local environment.

    Using the Text Editor

    Examples of a few editors include Windows Notepad, Notepad++, Emacs, vim or vi, etc. Editors may vary from one Operating System to another. The source files are typically named with the extension “.dart”.

    Installing the Dart SDK

    The current stable version of Dart is 1.21.0. The dart sdk can be downloaded from −

    • https://www.dartlang.org/install/archive
    • http://www.gekorm.com/dart-windows/

    A screenshot of the Dart SDK installation is given below −

    Dart Installation

    On completion of the SDK installation, set the PATH environment variable to −

    <dart-sdk-path>\bin 
    

    Verifying the Installation

    To verify if Dart has been successfully installed, open the command prompt and enter the following command −

    Dart 
    

    If installation is successful, it will show the dart runtime.

    IDE Support

    A plethora of IDEs support scripting in Dart. Examples include Eclipse, IntelliJ, and WebStorm from Jet brains.

    Given below are the steps for configuring the Dart environment using WebStrom IDE.

    Installing WebStorm

    The installation file for WebStorm can be downloaded from https://www.jetbrains.com/webstorm/download/#section=windows-version.

    The WebStorm installation file is available for Mac OS, Windows and Linux.

    After downloading the installation files, follow the steps given below −

    • Install the Dart SDK: Refer to the steps listed above
    • Create a new Dart project and configure Dart support
    • To create a new Dart project,
      • Click Create New Project from the Welcome Screen
      • In the next dialog box, click Dart
    • If there is no value specified for the Dart SDK path, then provide the SDK path. For example, the SDK path may be <dart installation directory>/dart/dartsdk.

    Add a Dart File to the Project

    To add a Dart file to the Project −

    • Right-click on the Project
    • New → Dart File
    • Enter the name of the Dart Script

    A screenshot of the WebStorm Editor is given below −

    Dart File

    The dart2js Tool

    The dart2js tool compiles Dart code to JavaScript. Compiling Dart code to JS enables running the Dart script on browsers that do not support the Dart VM.

    The dart2js tool is shipped as a part of the Dart SDK and can be found in the /dartsdk/bin folder.

    To compile Dart to JavaScript, type the following command in the terminal

    dart2js - - out = <output_file>.js  <dart_script>.dart
    

    This command produces a file that contains the JavaScript equivalent of your Dart code. A complete tutorial on using this utility can be found on the official Dart website.

  • Environment

    In order to run Elixir, you need to set it up locally on your system.

    To install Elixir, you will first require Erlang. On some platforms, Elixir packages come with Erlang in them.

    Installing Elixir

    Let us now understand the installation of Elixir in different Operating Systems.

    Windows Setup

    To install Elixir on windows, download installer from https://elixir-lang.org/install.html#windows and simply click Next to proceed through all steps. You will have it on your local system.

    If you have any problems while installing it, you can check this page for more info.

    Mac Setup

    If you have Homebrew installed, make sure that it is the latest version. For updating, use the following command −

    brew update
    

    Now, install Elixir using the command given below −

    brew install elixir
    

    Ubuntu/Debian Setup

    The steps to install Elixir in an Ubuntu/Debian setup is as follows −

    Add Erlang Solutions repo −

    wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo 
    dpkg -i erlang-solutions_1.0_all.deb 
    sudo apt-get update 
    

    Install the Erlang/OTP platform and all of its applications −

    sudo apt-get install esl-erlang 
    

    Install Elixir −

    sudo apt-get install elixir
    

    Other Linux Distros

    If you have any other Linux distribution, please visit this page to set up elixir on your local system.

    Testing the Setup

    To test the Elixir setup on your system, open your terminal and enter iex in it. It will open the interactive elixir shell like the following −

    Erlang/OTP 19 [erts-8.0] [source-6dc93c1] [64-bit] 
    [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]  
    
    Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help) 
    iex(1)>
    

    Elixir is now successfully set up on your system.

  • Overview

    Dart is an object-oriented language with C-style syntax which can optionally trans compile into JavaScript. It supports a varied range of programming aids like interfaces, classes, collections, generics, and optional typing.

    Dart can be extensively used to create single-page applications. Single-page applications apply only to websites and web applications. Single-page applications enable navigation between different screens of the website without loading a different webpage in the browser. A classic example is GMail ─ when you click on a message in your inbox, browser stays on the same webpage, but JavaScript code hides the inbox and brings the message body on screen.

    Google has released a special build of Chromium – the Dart VM. Using Dartium means you don’t have to compile your code to JavaScript until you’re ready to test on other browsers.

    The following table compares the features of Dart and JavaScript.

    FeatureDartJavaScript
    Type systemOptional, dynamicWeak, dynamic
    ClassesYes, single inheritancePrototypical
    InterfacesYes, multiple interfacesNo
    ConcurrencyYes, with isolatesYes, with HTML5 web workers

    This tutorial provides a basic level understanding of the Dart programming language.

  • Overview

    Elixir is a dynamic, functional language designed for building scalable and maintainable applications. It leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain.

    Elixir is a functional, dynamic language built on top of Erlang and the Erlang VM. Erlang is a language that was originally written in 1986 by Ericsson to help solve telephony problems like distribution, fault-tolerance, and concurrency. Elixir, written by José Valim, extends Erlang and provides a friendlier syntax into the Erlang VM. It does this while keeping the performance of the same level as Erlang.

    Features of Elixir

    Let us now discuss a few important features of Elixir −

    • Scalability − All Elixir code runs inside lightweight processes that are isolated and exchange information via messages.
    • Fault Tolerance − Elixir provides supervisors which describe how to restart parts of your system when things go wrong, going back to a known initial state that is guaranteed to work. This ensures your application/platform is never down.
    • Functional Programming − Functional programming promotes a coding style that helps developers write code that is short, fast, and maintainable.
    • Build tools − Elixir ships with a set of development tools. Mix is one such tool that makes it easy to create projects, manage tasks, run tests, etc. It also has its own package manager − Hex.
    • Erlang Compatibility − Elixir runs on the Erlang VM giving developers complete access to Erlang’s ecosystem.
  • C++ Data Structures

    C/C++ arrays allow you to define variables that combine several data items of the same kind, but structure is another user defined data type which allows you to combine data items of different kinds.

    Structures are used to represent a record, suppose you want to keep track of your books in a library. You might want to track the following attributes about each book −

    • Title
    • Author
    • Subject
    • Book ID

    Defining a Structure

    To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member, for your program. The format of the struct statement is this −

    struct [structure tag] {
       member definition;
       member definition;
       ...
       member definition;
    } [one or more structure variables];  
    

    The structure tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the structure’s definition, before the final semicolon, you can specify one or more structure variables but it is optional. Here is the way you would declare the Book structure −

    struct Books {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    } book;  
    

    Accessing Structure Members

    To access any member of a structure, we use the member access operator (.). The member access operator is coded as a period between the structure variable name and the structure member that we wish to access. You would use struct keyword to define variables of structure type. Following is the example to explain usage of structure −

    #include <iostream>
    #include <cstring>
     
    using namespace std;
     
    struct Books {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    };
     
    int main() {
       struct Books Book1;        // Declare Book1 of type Book
       struct Books Book2;        // Declare Book2 of type Book
     
       // book 1 specification
       strcpy( Book1.title, "Learn C++ Programming");
       strcpy( Book1.author, "Chand Miyan"); 
       strcpy( Book1.subject, "C++ Programming");
       Book1.book_id = 6495407;
    
       // book 2 specification
       strcpy( Book2.title, "Telecom Billing");
       strcpy( Book2.author, "Yakit Singha");
       strcpy( Book2.subject, "Telecom");
       Book2.book_id = 6495700;
     
       // Print Book1 info
       cout << "Book 1 title : " << Book1.title <<endl;
       cout << "Book 1 author : " << Book1.author <<endl;
       cout << "Book 1 subject : " << Book1.subject <<endl;
       cout << "Book 1 id : " << Book1.book_id <<endl;
    
       // Print Book2 info
       cout << "Book 2 title : " << Book2.title <<endl;
       cout << "Book 2 author : " << Book2.author <<endl;
       cout << "Book 2 subject : " << Book2.subject <<endl;
       cout << "Book 2 id : " << Book2.book_id <<endl;
    
       return 0;
    }

    When the above code is compiled and executed, it produces the following result −

    Book 1 title : Learn C++ Programming
    Book 1 author : Chand Miyan
    Book 1 subject : C++ Programming
    Book 1 id : 6495407
    Book 2 title : Telecom Billing
    Book 2 author : Yakit Singha
    Book 2 subject : Telecom
    Book 2 id : 6495700
    

    Structures as Function Arguments

    You can pass a structure as a function argument in very similar way as you pass any other variable or pointer. You would access structure variables in the similar way as you have accessed in the above example −

    #include <iostream>
    #include <cstring>
     
    using namespace std;
    void printBook( struct Books book );
    
    struct Books {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    };
     
    int main() {
       struct Books Book1;        // Declare Book1 of type Book
       struct Books Book2;        // Declare Book2 of type Book
     
       // book 1 specification
       strcpy( Book1.title, "Learn C++ Programming");
       strcpy( Book1.author, "Chand Miyan"); 
       strcpy( Book1.subject, "C++ Programming");
       Book1.book_id = 6495407;
    
       // book 2 specification
       strcpy( Book2.title, "Telecom Billing");
       strcpy( Book2.author, "Yakit Singha");
       strcpy( Book2.subject, "Telecom");
       Book2.book_id = 6495700;
     
       // Print Book1 info
       printBook( Book1 );
    
       // Print Book2 info
       printBook( Book2 );
    
       return 0;
    }
    void printBook( struct Books book ) {
       cout << "Book title : " << book.title <<endl;
       cout << "Book author : " << book.author <<endl;
       cout << "Book subject : " << book.subject <<endl;
       cout << "Book id : " << book.book_id <<endl;
    }

    When the above code is compiled and executed, it produces the following result −

    Book title : Learn C++ Programming
    Book author : Chand Miyan
    Book subject : C++ Programming
    Book id : 6495407
    Book title : Telecom Billing
    Book author : Yakit Singha
    Book subject : Telecom
    Book id : 6495700
    

    Pointers to Structures

    You can define pointers to structures in very similar way as you define pointer to any other variable as follows −

    struct Books *struct_pointer;
    

    Now, you can store the address of a structure variable in the above defined pointer variable. To find the address of a structure variable, place the & operator before the structure’s name as follows −

    struct_pointer = &Book1;
    

    To access the members of a structure using a pointer to that structure, you must use the -> operator as follows −

    struct_pointer->title;
    

    Let us re-write above example using structure pointer, hope this will be easy for you to understand the concept −

    #include <iostream>
    #include <cstring>
     
    using namespace std;
    void printBook( struct Books *book );
    
    struct Books {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    };
    int main() {
       struct Books Book1;        // Declare Book1 of type Book
       struct Books Book2;        // Declare Book2 of type Book
     
       // Book 1 specification
       strcpy( Book1.title, "Learn C++ Programming");
       strcpy( Book1.author, "Chand Miyan"); 
       strcpy( Book1.subject, "C++ Programming");
       Book1.book_id = 6495407;
    
       // Book 2 specification
       strcpy( Book2.title, "Telecom Billing");
       strcpy( Book2.author, "Yakit Singha");
       strcpy( Book2.subject, "Telecom");
       Book2.book_id = 6495700;
     
       // Print Book1 info, passing address of structure
       printBook( &Book1 );
    
       // Print Book1 info, passing address of structure
       printBook( &Book2 );
    
       return 0;
    }
    
    // This function accept pointer to structure as parameter.
    void printBook( struct Books *book ) {
       cout << "Book title : " << book->title <<endl;
       cout << "Book author : " << book->author <<endl;
       cout << "Book subject : " << book->subject <<endl;
       cout << "Book id : " << book->book_id <<endl;
    }

    When the above code is compiled and executed, it produces the following result −

    Book title : Learn C++ Programming
    Book author : Chand Miyan
    Book subject : C++ Programming
    Book id : 6495407
    Book title : Telecom Billing
    Book author : Yakit Singha
    Book subject : Telecom
    Book id : 6495700
    

    The typedef Keyword

    There is an easier way to define structs or you could “alias” types you create. For example −

    typedef struct {
       char  title[50];
       char  author[50];
       char  subject[100];
       int   book_id;
    } Books;
    

    Now, you can use Books directly to define variables of Books type without using struct keyword. Following is the example −

    Books Book1, Book2;
    

    You can use typedef keyword for non-structs as well as follows −

    typedef long int *pint32;
     
    pint32 x, y, z;
    

    x, y and z are all pointers to long ints.

  • C++ Basic Input/Output

    The C++ standard libraries provide an extensive set of input/output capabilities which we will see in subsequent chapters. This chapter will discuss very basic and most common I/O operations required for C++ programming.

    C++ I/O occurs in streams, which are sequences of bytes. If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main memory, this is called input operation and if bytes flow from main memory to a device like a display screen, a printer, a disk drive, or a network connection, etc., this is called output operation.

    I/O Library Header Files

    There are following header files important to C++ programs −

    Sr.NoHeader File & Function and Description
    1<iostream>This file defines the cin, cout, cerr and clog objects, which correspond to the standard input stream, the standard output stream, the un-buffered standard error stream and the buffered standard error stream, respectively.
    2<iomanip>This file declares services useful for performing formatted I/O with so-called parameterized stream manipulators, such as setw and setprecision.
    3<fstream>This file declares services for user-controlled file processing. We will discuss about it in detail in File and Stream related chapter.

    The Standard Output Stream (cout)

    The predefined object cout is an instance of ostream class. The cout object is said to be “connected to” the standard output device, which usually is the display screen. The cout is used in conjunction with the stream insertion operator, which is written as << which are two less than signs as shown in the following example.

    #include <iostream>
     
    using namespace std;
     
    int main() {
       char str[] = "Hello C++";
     
       cout << "Value of str is : " << str << endl;
    }

    When the above code is compiled and executed, it produces the following result −

    Value of str is : Hello C++
    

    The C++ compiler also determines the data type of variable to be output and selects the appropriate stream insertion operator to display the value. The << operator is overloaded to output data items of built-in types integer, float, double, strings and pointer values.

    The insertion operator << may be used more than once in a single statement as shown above and endl is used to add a new-line at the end of the line.

    The Standard Input Stream (cin)

    The predefined object cin is an instance of istream class. The cin object is said to be attached to the standard input device, which usually is the keyboard. The cin is used in conjunction with the stream extraction operator, which is written as >> which are two greater than signs as shown in the following example.

    #include <iostream>
     
    using namespace std;
     
    int main() {
       char name[50];
     
       cout << "Please enter your name: ";
       cin >> name;
       cout << "Your name is: " << name << endl;
     
    }

    When the above code is compiled and executed, it will prompt you to enter a name. You enter a value and then hit enter to see the following result −

    Please enter your name: cplusplus
    Your name is: cplusplus
    

    The C++ compiler also determines the data type of the entered value and selects the appropriate stream extraction operator to extract the value and store it in the given variables.

    The stream extraction operator >> may be used more than once in a single statement. To request more than one datum you can use the following −

    cin >> name >> age;
    

    This will be equivalent to the following two statements −

    cin >> name;
    cin >> age;
    

    The Standard Error Stream (cerr)

    The predefined object cerr is an instance of ostream class. The cerr object is said to be attached to the standard error device, which is also a display screen but the object cerr is un-buffered and each stream insertion to cerr causes its output to appear immediately.

    The cerr is also used in conjunction with the stream insertion operator as shown in the following example.

    #include <iostream>
     
    using namespace std;
     
    int main() {
       char str[] = "Unable to read....";
     
       cerr << "Error message : " << str << endl;
    }

    When the above code is compiled and executed, it produces the following result −

    Error message : Unable to read....
    

    The Standard Log Stream (clog)

    The predefined object clog is an instance of ostream class. The clog object is said to be attached to the standard error device, which is also a display screen but the object clog is buffered. This means that each insertion to clog could cause its output to be held in a buffer until the buffer is filled or until the buffer is flushed.

    The clog is also used in conjunction with the stream insertion operator as shown in the following example.

    #include <iostream>
     
    using namespace std;
     
    int main() {
       char str[] = "Unable to read....";
     
       clog << "Error message : " << str << endl;
    }

    When the above code is compiled and executed, it produces the following result −

    Error message : Unable to read....
    

    You would not be able to see any difference in cout, cerr and clog with these small examples, but while writing and executing big programs the difference becomes obvious. So it is good practice to display error messages using cerr stream and while displaying other log messages then clog should be used.