{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "#include \n", "#include // for setw and setfill stream manipulators\n", "#include // for ostringstream class\n", "#include \n", "using namespace std;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Stream I/O" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Streams\n", "\n", "- C++ I/O occurs in streams, which are sequences of bytes\n", " - In input operations, the bytes flow from a device to main memory\n", " - In output operations, bytes flow from main memory to a device\n", "\n", "- A stream is an abstraction for input/output. You can think of it as a source (input) or destination (output) of characters of indefinite length. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## `iostream`\n", "\n", "- The iostream library provides many class templates for performing common I/O operations\n", " - `basic_istream` for stream input operations\n", " - `istream` is a `basic_istream` that enables char input, i.e. `cin`'s type\n", " - `basic_ostream` for stream output operations\n", " - `ostream` is a `basic_ostream` that enables char output, i.e. the type of `cout`, `cerr` and `clog`\n", "\n", "![iostreams](../img/iostream.gif)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Character Output\n", "\n", "- The `basic_ostream` member function put outputs one character at a time.\n", " - The put function also may be called with a numeric expression that represents an ASCII value" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A" ] } ], "source": [ "std::cout.put('A');" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A" ] } ], "source": [ "std::cout.put(65);" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## `getline`\n", "\n", "- Standard Library global function `getline` reads a line of text.\n", " - When you press `Enter` key after typing data, the system inserts a newline in the input stream\n", " - Function `getline` reads from the standard input stream object `cin` the characters the user enters, up to, but not including, the **newline**, which is discarded\n", " - Input can contain multiple words separated by a space\n", " - `getline` places the characters in its second argument" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "jkljfd fsdkjf dkdlkfldkf\n", "String 's' is \"jkljfd\"\n" ] } ], "source": [ "{\n", " std::string s;\n", " std::cin >> s;\n", " std::cout << \"String 's' is \\\"\" << s << \"\\\"\" << std::endl;\n", "}" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " lfg jgkfg kfjgkfjgfk kfjgkfjg \n", "String 's' is \" lfg jgkfg kfjgkfjgfk kfjgkfjg \"\n" ] } ], "source": [ "{\n", " std::string s;\n", " std::getline(std::cin, s);\n", " std::cout << \"String 's' is \\\"\" << s << \"\\\"\" << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Stream Manipulators\n", "\n", "- The stream manipulators provide capabilities such as\n", " - setting field widths\n", " - setting precision\n", " - setting and unsetting format state\n", " - setting the fill character in fields\n", " - flushing streams\n", " - inserting a newline into the output stream (and flushing the stream)\n", " - inserting a null character into the output stream\n", " - skipping white space in the input stream" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output:10\n" ] } ], "source": [ "std::cout << \"Output:\" << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output: 10\n" ] } ], "source": [ "#include // for setw()\n", "\n", "std::cout << \"Output: \" << std::setw(5) << 10 << std::endl;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- `setprecision(n)` sets the precision of the stream **out** or **in** to exactly **n**. " ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 petabyte is 2^50 bytes = 1125899906842624 bytes\n" ] } ], "source": [ "#include \n", "#include // for pow() \n", "#include // for setprecision()\n", "\n", "std::cout << \"1 petabyte is 2^50 bytes = \"\n", " << std::setprecision(20) \n", " << pow(2., 50) << \" bytes\" \n", " << std::endl;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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 behavior." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "std::cout << true << std::endl;" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "true\n" ] } ], "source": [ "std::cout << std::boolalpha<< true << std::endl;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- `oct`, `dec`, `hex` 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.\n", "\n", "- More example of stream library use in here: https://blog.andersonbanihirwe.dev/2018/01/20/play-interactively-with-cpp-streams.html" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000\n" ] } ], "source": [ "std::cout << 1000 << std::endl;" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1750\n" ] } ], "source": [ "std::cout << std::oct << 1000 << std::endl;" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3e8\n" ] } ], "source": [ "std::cout << std::hex << 1000 << std::endl;" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000\n" ] } ], "source": [ "std::cout << std::dec << 1000 << std::endl;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- Once the fill character is specified with `setfill`, it applies for all subsequent values that are displayed in fields wider than the value being displayed\n", "- `setfill` is a sticky setting\n", "- This is in contrast to `setw`, which applies only to the next value displayed\n", "- `setw` is a nonsticky setting" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0010\n" ] } ], "source": [ "std::cout << std::setfill('0') << std::setw(4) << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n" ] } ], "source": [ "std::cout << 10 << std::endl;" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "00000010\n" ] } ], "source": [ "std::cout << std::setw(8) << 10 << std::endl;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Stream Sticky Setting\n", "\n", "- Parameterized stream manipulator **setfill** specifies the fill character that's displayed when an integer is output in a field wider than the number of digits in the value.\n", "\n", "- Once the fill character is specified with **setfill**, it applies for all subsequent values that are displayed in fields wider than the value being displayed:\n", " - **setfill** is a sticky setting\n", " \n", "- Each sticky setting should be restored to its previous setting when it’s no longer needed. \n", " - in contrast to **setw**, which applies only to the next value displayed **setw** is a nonsticky setting" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Type-Safe I/O\n", "\n", "- C++ offers type-safe I/O. \n", "- The `<<` and `>>` operators are overloaded to accept data items of specific types.\n", "- If unexpected data is processed, various error bits are set, which the user may query to determine whether an I/O operation succeeded or failed.\n", "- If operators `<<` and `>>` have not been overloaded for a user-defined type and you attempt to use those operators to input into or output the contents of an object of that user-defined type, the compiler reports an\n", "error." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Unformatted I/O\n", "\n", "- Unformatted input/output is performed using `istream`s `read` and `ostream`s `write` member functions, respectively.\n", " - read inputs bytes to a built-in array of `char`s in memory\n", " - write outputs bytes from a built-in array of `char`s." ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "HAPPY BIRT" ] } ], "source": [ "{\n", " char buffer[]{\"HAPPY BIRTHDAY\"};\n", " std::cout.write(buffer, 10);\n", "}" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter a sentence:\n", "hello-hello\n", "\n", "The sentence entered was:\n", "hello-BIRTHDAY\n" ] } ], "source": [ "{\n", " char buffer[]{\"HAPPY BIRTHDAY\"};\n", " std::cout << \"Enter a sentence:\\n\";\n", " std::cin.read(buffer, 6);\n", " std::cout << \"\\nThe sentence entered was:\\n\";\n", " std::cout << buffer << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## String Stream Processing\n", "\n", "- `ostringstream` objects provide the same functionality as `cout`, but write their output to `string`\n", " - `ostringstream`'s `str` member function gets the formatted `string`\n", " - It's defined in the header ``" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10:03:44\n", "n: 10, c: d\n" ] } ], "source": [ "{\n", " int hour{10}, minute{3}, second{44};\n", " std::ostringstream output;\n", " output << std::setfill('0') << std::setw(2) << hour << \":\"\n", " << std::setw(2) << minute << \":\" << std::setw(2) << second;\n", " std::cout << output.str() << std::endl; // returns the formatted string\n", " std::stringstream input{\"10 d\"};\n", " char c;\n", " int n;\n", " input >> n >> c;\n", " std::cout << \"n: \" << n << \", c: \" << c << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "- We can pass an integer to the C++ Standard Library function `to_string` (from header `` ), which converts a numeric value to a `string` object." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## C++ Strings\n", "\n", "- C++ offers two types of strings\n", " - `string` class objects, and\n", " - `C`-style, pointer-based strings (**C strings**).\n", " \n", "- C++ `string` class is preferred it eliminates many of the security problems that can be caused by manipulating C strings.\n", " - Also, if you work with legacy C and C++ programs, you're likely to encounter pointer-based strings." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Characters\n", "\n", "- Characters are the fundamental building blocks of C++ source programs.\n", "- **Character constant**\n", " - An integer value represented as a character in single quotes.\n", " - The value of a character constant is the integer value of the character in the machine’s character set." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Char: 'A' is an integer: 65\n" ] } ], "source": [ "{\n", " char c = 'A';\n", " int i{c};\n", " std::cout << \"Char: '\" << c << \"' is an integer: \"<< i << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Strings\n", "\n", "- A string is a series of characters treated as a single unit.\n", " - May include letters, digits and various **special characters** such as +, −, *, /and $.\n", "- **String literals**, or string constants, in C++ are written in double quotation marks" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Some string: \"abcd3340+-\\$\"\n" ] } ], "source": [ "{\n", " std::string s{\"abcd3340+-\\\\$\"};\n", " std::cout << \"Some string: \\\"\" << s << \"\\\"\" << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Pointer-Based Strings\n", "\n", "- A pointer-based string is a built-in array of characters ending with a null character `'\\0'`.\n", "- A string is accessed via a pointer to its first character.\n", "- The `sizeof` a string literal is the length of the string including the terminating null character.\n", "- A string literal may be used as an initializer in the declaration of either a built-in array of `chars` or a variable of type `const char*`.\n", "- The characters are output until a terminating null character is encountered;\n", " - the null character is not displayed." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Some string: \"blue\"\n", "Another string: \"green\"\n" ] } ], "source": [ "{\n", " char color[]{\"blue\"};\n", " const char* colorPtr{\"green\"}; \n", " std::cout << \"Some string: \\\"\" << color << \"\\\"\" << std::endl;\n", " std::cout << \"Another string: \\\"\" << colorPtr << \"\\\"\" << std::endl; \n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Accessing Characters\n", "\n", "- Because a C string is a built-in array of characters, we can access individual characters in a string directly with array subscript notation." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Some string: \"blue\"\n", "A third character in the string is 'u'\n", "Same string: \"glue\"\n" ] } ], "source": [ "{\n", " char color[]{\"blue\"}; \n", " std::cout << \"Some string: \\\"\" << color << \"\\\"\" << std::endl;\n", " std::cout << \"A third character in the string is '\" << color[2] << \"'\" << std::endl;\n", " color[0] = 'g';\n", " std::cout << \"Same string: \\\"\" << color << \"\\\"\" << std::endl;\n", "}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## String Class\n", "\n", "- String variables can hold character string values such as `\"Jane Green\"`.\n", "- A string is actually an object of the C++ Standard Library class `string`\n", " - It's defined in the header ``.\n", " - The class name `string`, belongs to namespace `std`. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## *String* Class Operators\n", "\n", "- Class **string** has overloaded operators and several other useful member functions, including **empty**, **substr** and **at**\n", "\n", "- Class **string** has overloaded equality and relational operators perform lexicographical comparisons" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s1 is \"happy\"; s2 is \" birthday\"; s3 is \"\" and is empty: true\n", "\n", "The results of comparing s2 and s1:\n", "s2 == s1 yields false\n", "s2 != s1 yields true\n", "s2 > s1 yields false\n", "s2 < s1 yields true\n", "s2 >= s1 yields false\n", "s2 <= s1 yields true" ] } ], "source": [ "std::string s1{\"happy\"};\n", "std::string s2{\" birthday\"};\n", "std::string s3; // creates an empty string\n", "// test overloaded equality and relational operators\n", "std::cout << boolalpha\n", " << \"s1 is \\\"\" << s1 << \"\\\"; s2 is \\\"\" << s2\n", " << \"\\\"; s3 is \\\"\" << s3 << '\\\"' << \" and is empty: \" << s3.empty()\n", " << \"\\n\\nThe results of comparing s2 and s1:\"\n", " << \"\\ns2 == s1 yields \" << ( s2 == s1 )\n", " << \"\\ns2 != s1 yields \" << ( s2 != s1 )\n", " << \"\\ns2 > s1 yields \" << ( s2 > s1 )\n", " << \"\\ns2 < s1 yields \" << ( s2 < s1 )\n", " << \"\\ns2 >= s1 yields \" << ( s2 >= s1 )\n", " << \"\\ns2 <= s1 yields \" << ( s2 <= s1 );" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- Class **string** provides member function **empty** to determine whether a string is empty\n", " - Returns true if the string is empty; otherwise, it returns false.\n", "\n", "- Class **string** has overloaded **+=** operator performs string concatenation.\n", " - A string literal can be appended to a string object by using operator `+=`" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s1 += s2 yields s1 = happy birthday\n", "\n", "s1 += \" to you\" yields\n", "s1 = happy birthday to you" ] } ], "source": [ "// test overloaded string concatenation assignment operator\n", "std::cout << \"s1 += s2 yields s1 = \";\n", "s1 += s2; // test overloaded concatenation\n", "std::cout << s1;\n", "\n", "// test string concatenation with a C string\n", "std::cout << \"\\n\\ns1 += \\\" to you\\\" yields\\n\";\n", "s1 += \" to you\";\n", "std::cout << \"s1 = \" << s1;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- Class string does provide bounds checking in its member function at, which throws an exception if its argument is an invalid subscript.\n", " - If the subscript is valid, function at returns the character at the specified location as a modifiable *lvalue* or a *nonmodifiable lvalue* (e.g., a `const` reference), depending on the context in which the call appears." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s4 = happy birthday to you\n", "\n", "assigning s4 to s4\n", "s4 = happy birthday to you\n", "\n", "s1 after s1[0] = 'H' and s1[6] = 'B' is:\n", "Happy Birthday to you\n", "\n" ] } ], "source": [ "// test copy constructor\n", "std::string s4{s1};\n", "std::cout << \"s4 = \" << s4 << \"\\n\\n\";\n", "\n", "// test overloaded copy assignment (=) operator with self-assignment\n", "std::cout << \"assigning s4 to s4\\n\";\n", "s4 = s4;\n", "std::cout << \"s4 = \" << s4;\n", "\n", "// test using overloaded subscript operator to create lvalue\n", "s1[0] = 'H';\n", "s1[6] = 'B';\n", "std::cout << \"\\n\\ns1 after s1[0] = 'H' and s1[6] = 'B' is:\\n\" << s1 << \"\\n\\n\";" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "C++14", "language": "C++14", "name": "xcpp14" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".cpp", "mimetype": "text/x-c++src", "name": "c++", "version": "14" } }, "nbformat": 4, "nbformat_minor": 2 }