{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Streams" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A stream is an abstraction for input/output.\n", "You can think of it as a source (input) or destination (output) of \n", "characters of indefinite length." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## How do you write data to a file in C++?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "C++ provides a header filed called `` (file stream) that exports the `ifstream` and `ofstream` types, streams that perform file I/O. Input/output stream class to operate on files.\n", "\n", "Objects of this class maintain a filebuf object as their internal stream buffer, which performs input/output operations on the file they are associated with (if any).\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2018-01-20T02:23:36Z\u0000", "start_time": "2018-01-20T02:23:36Z\u0000" } }, "outputs": [], "source": [ "#include // std::fstream" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "std::fstream fs;\n", "fs.open (\"iofiles/test.txt\", std::fstream::in | std::fstream::out | std::fstream::app);\n", "\n", "fs << \"More lorem ipsum....\"; // write to the created file\n", "fs.close(); // Close the stream " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test.txt\n", "More lorem ipsum...." ] } ], "source": [ "!cd iofiles && ls && cat test.txt" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "fs.open (\"iofiles/test.txt\", std::fstream::in | std::fstream::out | std::fstream::app); // Re-open the stream \n", "fs << \"Last but not the least lorem ipsum!!\"; // Write some more to the file\n", "fs.close(); // Close the stream" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test.txt\n", "More lorem ipsum....Last but not the least lorem ipsum!!" ] } ], "source": [ "!cd iofiles && ls && cat test.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stream Manipulators" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What does the `setw` manipulator do?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`setw(n)` sets the minimum width of the input for the next stream operation. If the data doesn't meet the minimum field requirement, it is padded with the default fill character until it is proper size." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "#include " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output: 10\n" ] } ], "source": [ "std::cout << \"Output: \" << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output: 10\n" ] } ], "source": [ "std::cout << \"Output: \" << std::setw(5) << 10 << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What does the `boolalpha` manipulator do?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`boolalpha` determines whether or not the stream should output boolean values as 1 and 0 or as \"true\" and \"false\". The opposite manipulator is **`noboolalpha`**, which reverses this behaviour." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "std::cout << true << std::endl;" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "true\n" ] } ], "source": [ "std::cout << std::boolalpha<< true << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What do `hex`, `dec`, `oct` manipulator do?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "They set the radix on the stream to either octal (base 8), decimal (base 10), or hexadecimal (base 16). This can be used either to format output or change the base for input." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n" ] } ], "source": [ "std::cout << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n" ] } ], "source": [ "std::cout << std::dec << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "12\n" ] } ], "source": [ "std::cout << std::oct << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a\n" ] } ], "source": [ "std::cout << std::hex << 10 << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What is stream failure? How do you check for it?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because stream operations often involved transforming data from one form into another, stream operations are not always guaranteed to succeed.\n", "\n", "Let's use the previously created `test.txt` file to demonstrate stream failure.\n", "\n", "For the following program: \n", "- If the file `test.txt` contains `NUM_INTS` consecutive integer values, then this code will work correctly.\n", "- If we try to read stream data of one type into a variable of another type, rather than crashing the program or filling the variable with garbage data, the stream fails by entering an **error state** and the value of the variable will not change. Once the stream is in this error state, any subsequent read or write operations will automatically and silently fail which can be a serious problem . \n", "\n", "To check if a stream is in an erroneous state, we use the `.fail()` member function." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "#include " ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "fs.open (\"iofiles/test.txt\", std::fstream::in | std::fstream::out | std::fstream::app);" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "int NUM_INTS = 5;" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "\n", "for(int i = 0; i < NUM_INTS; i++){\n", " int value;\n", " fs >> value;\n", " /*..... Do something Here ....*/\n", " if(fs.fail()) break;\n", " std::cout << value << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, when the program realizes that the file contains text and not integers, it breaks out of the loop without doing any subsequent operation. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What is a `stringstream`?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In C++, you can't add numbers to strings and when you can, it's almost certainly won't do what you expected. \n", "\n", "One solution to this problem is to use another kind of stream object known as a **`stringstream`**, exported by `` header. Like console streams and file streams, **stringstream**s are stream objects. Instead of reading or writing data to an external source, **stringstream**s store data in temporary string buffers. " ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "#include // std::stringstream, std::stringbuf" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "std::stringstream ss;\n", "ss << \"Hello World! It's \" << 135 << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once you have put data into a **stringstream**, you can retrieve the string you have created using the `.str()` member function." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World! It's 135\n", "\n" ] } ], "source": [ "std::string s = ss.str();\n", "std:: cout << s << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**stringstream**s are an example of an **iostream**, a stream that can perform both input and output, You can both insert data inot a **stringstream** to convert the data to string and extract data from a **stringstream** to convert string data into a different format. For example:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "std::stringstream myConverter;\n", "int myInt;\n", "std::string myString;\n", "double myDouble;" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "\n", "0\n" ] } ], "source": [ "std::cout << myInt << std::endl;\n", "std::cout << myString << std::endl;\n", "std::cout << myDouble << std::endl;" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "myConverter << \"5 World 3.14\"; // Insert string data" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "myConverter >> myInt >> myString >> myDouble; // Extract mixed data" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "World\n", "3.14\n" ] } ], "source": [ "std::cout << myInt << std::endl;\n", "std::cout << myString << std::endl;\n", "std::cout << myDouble << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write a function that converts an `int` into a `string`" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "std::string intToStr(int myInt){\n", " std::stringstream ss;\n", " ss << myInt;\n", " std::string s = ss.str();\n", " return s;\n", "}" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "std::string str = intToStr(5);\n", "std::cout << str << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Draw a tringle by drawing a single character on one line, then three on the next, ..." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "void DrawTriangle(int numRows){\n", " \n", " for(int i = 1 ; i <= numRows; i++) {\n", " //Print a field of spaces equal to the number of rows minus half the width of the triangle, plus 2 spaces\n", " //between the row number and the triangle,\n", " std::cout << std::setfill(' ') << std::setw(numRows - i + 2) << \" \";\n", " \n", " //Print a field of pipes equal to the number of row number*2 then subtract 1 to keep the width odd and centered.\n", " std::cout << std::setfill('#') << std::setw((i * 2 - 1)) << \"#\";\n", " std::cout << std::endl;\n", " }\n", " \n", "}" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " #\n", " ###\n", " #####\n", " #######\n", " #########\n" ] } ], "source": [ "DrawTriangle(5)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " #\n", " ###\n", " #####\n", " #######\n", " #########\n", " ###########\n", " #############\n", " ###############\n" ] } ], "source": [ "DrawTriangle(8)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " #\n", " ###\n", " #####\n", " #######\n", " #########\n", " ###########\n", " #############\n", " ###############\n", " #################\n", " ###################\n", " #####################\n", " #######################\n", " #########################\n", " ###########################\n", " #############################\n" ] } ], "source": [ "DrawTriangle(15);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Next Time Sequential Containers

" ] } ], "metadata": { "kernelspec": { "display_name": "xeus C++14", "language": "", "name": "xeus-cling-cpp14" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".cpp", "mimetype": "text/x-c++src", "name": "c++", "version": "" }, "toc": { "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "toc_cell": true, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }