Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MicrosoftDocs/cpp-docs/llms.txt

Use this file to discover all available pages before exploring further.

The C++ Standard Library offers a rich set of facilities for text manipulation and input/output. At the core are std::string (narrow characters) and std::wstring (wide characters), backed by the basic_string class template. For non-owning string references there is std::string_view (C++17). I/O is handled through a hierarchy of stream objects — cin/cout/cerr for console I/O, ifstream/ofstream for file I/O, and stringstream for in-memory I/O. C++20 adds std::format, a type-safe, positional formatting facility that supersedes printf-style format strings.

String Types

The <string> header provides four standard string typedefs, each a specialization of basic_string<CharT>:
TypedefElement typeTypical use
std::stringchar (UTF-8 / ANSI)General-purpose narrow strings
std::wstringwchar_t (UTF-16 on Windows)Windows API interop
std::u16stringchar16_t (UTF-16)Explicit UTF-16 encoding
std::u32stringchar32_t (UTF-32)Explicit UTF-32 encoding

Basic std::string Operations

#include <string>
#include <iostream>

int main()
{
    std::string s = "Hello, World!";

    // Length and access
    std::cout << "length: "  << s.length() << "\n"; // 13
    std::cout << "char[0]: " << s[0]       << "\n"; // H
    std::cout << "back: "    << s.back()   << "\n"; // !

    // Concatenation
    std::string greeting = "Hello";
    greeting += ", C++!";        // append with +=
    greeting.append(" How are you?");

    // Comparison (lexicographic)
    std::string a = "apple", b = "banana";
    std::cout << (a < b ? "apple < banana" : "apple >= banana") << "\n"; // apple < banana

    // Substring
    std::string sub = s.substr(7, 5); // start=7, len=5
    std::cout << "substr: " << sub << "\n"; // World

    // Find (returns std::string::npos if not found)
    auto pos = s.find("World");
    if (pos != std::string::npos)
        std::cout << "'World' at index " << pos << "\n"; // 7

    // Replace
    s.replace(7, 5, "C++");
    std::cout << s << "\n"; // Hello, C++!

    // Erase
    s.erase(5, 1); // remove comma
    std::cout << s << "\n"; // Hello C++!

    // Insert
    s.insert(5, ",");
    std::cout << s << "\n"; // Hello, C++!
}

Numeric Conversions

The <string> header provides free functions to convert between strings and numeric types:
#include <string>
#include <iostream>

int main()
{
    // Numeric → string
    std::string si  = std::to_string(42);
    std::string sd  = std::to_string(3.14159);
    std::cout << si << " " << sd << "\n"; // 42 3.141590

    // String → numeric
    int    i  = std::stoi("123");
    long   l  = std::stol("456789");
    double d  = std::stod("3.14");
    float  f  = std::stof("2.72");
    std::cout << i << " " << l << " " << d << " " << f << "\n";

    // stoi with a base
    int hex = std::stoi("FF", nullptr, 16);
    std::cout << "0xFF = " << hex << "\n"; // 255
}
std::stoi and friends throw std::invalid_argument if the string cannot be converted, and std::out_of_range if the value overflows the target type. Always wrap them in a try/catch when parsing user input.

std::string_view (C++17)

string_view (from <string_view>) is a non-owning, read-only reference to a character sequence. It avoids copies when passing string data to functions that only need to read it.
#include <string_view>
#include <string>
#include <iostream>

// Accept any string-like object without copying
void print_first_word(std::string_view sv)
{
    auto end = sv.find(' ');
    std::cout << sv.substr(0, end) << "\n";
}

int main()
{
    std::string s      = "Hello World";
    const char* cstr   = "Hello C++";
    std::string_view sv = "Hello string_view"; // points to string literal

    print_first_word(s);    // works — no copy of std::string
    print_first_word(cstr); // works — no copy of C string
    print_first_word(sv);   // works — already a view

    // string_view does not own the data — never store a view
    // to a temporary string that will be destroyed
}
A string_view does not null-terminate its data. Never pass sv.data() to a C API that expects a null-terminated const char* unless you are certain the underlying buffer is null-terminated.

Console I/O (<iostream>)

The <iostream> header declares four standard byte-oriented stream objects and their wide-character counterparts:
ObjectDirectionBufferedWide equivalent
std::cinInputYesstd::wcin
std::coutOutputYesstd::wcout
std::cerrError outputNostd::wcerr
std::clogError logYesstd::wclog
#include <iostream>
#include <string>

int main()
{
    // Output
    std::cout << "Enter your name: ";

    // Input
    std::string name;
    std::cin >> name; // reads one whitespace-delimited token

    std::cout << "Hello, " << name << "!\n";

    // Read a full line (including spaces)
    std::cin.ignore(); // discard leftover newline from previous >>
    std::string line;
    std::getline(std::cin, line);
    std::cout << "Line: " << line << "\n";

    // Error output (unbuffered — always visible)
    std::cerr << "This goes to stderr\n";

    // Logging (buffered stderr)
    std::clog << "This is a log message\n";
}

Stream Formatting

#include <iostream>
#include <iomanip>

int main()
{
    double pi = 3.14159265358979;

    // Precision
    std::cout << std::fixed    << std::setprecision(4) << pi << "\n"; // 3.1416
    std::cout << std::scientific << std::setprecision(3) << pi << "\n"; // 3.142e+00

    // Width and fill
    std::cout << std::setw(10) << std::setfill('0') << 42 << "\n"; // 0000000042

    // Hex, octal, decimal
    int n = 255;
    std::cout << std::hex   << n << "\n"; // ff
    std::cout << std::oct   << n << "\n"; // 377
    std::cout << std::dec   << n << "\n"; // 255

    // Boolean
    std::cout << std::boolalpha << true << " " << false << "\n"; // true false
}

File Streams (<fstream>)

#include <fstream>
#include <string>
#include <iostream>
#include <stdexcept>
#include <vector>

int main()
{
    // Write to a file
    {
        std::ofstream ofs("data.txt");
        if (!ofs)
            throw std::runtime_error("Cannot open data.txt for writing");

        ofs << "Line 1\n";
        ofs << "Line 2\n";
        ofs << "Line 3\n";
    } // ofs goes out of scope — file is flushed and closed automatically

    // Read from a file
    {
        std::ifstream ifs("data.txt");
        if (!ifs)
            throw std::runtime_error("Cannot open data.txt for reading");

        std::string line;
        while (std::getline(ifs, line))
            std::cout << line << "\n";
    }

    // Append to a file
    {
        std::ofstream ofs("data.txt", std::ios::app);
        ofs << "Line 4 (appended)\n";
    }

    // Binary I/O
    {
        std::vector<int> data = {1, 2, 3, 4, 5};
        std::ofstream bin("data.bin", std::ios::binary);
        bin.write(reinterpret_cast<const char*>(data.data()),
                  data.size() * sizeof(int));
    }
}
Always check that a file stream opened successfully with if (!ifs) or ifs.is_open() before performing I/O. Use RAII — let the stream destructor close the file rather than calling close() explicitly.

String Streams (<sstream>)

std::stringstream (and the read-only istringstream / write-only ostringstream) treat an in-memory string as a stream. They are ideal for parsing, formatting, and serialization.
#include <sstream>
#include <string>
#include <vector>
#include <iostream>

int main()
{
    // Build a formatted string using ostringstream
    std::ostringstream oss;
    oss << "Name: " << "Alice" << ", Age: " << 30 << ", Score: " << 98.5;
    std::string result = oss.str();
    std::cout << result << "\n"; // Name: Alice, Age: 30, Score: 98.5

    // Parse a CSV line using istringstream
    std::string csv = "10,20,30,40,50";
    std::istringstream iss(csv);
    std::vector<int> nums;
    std::string token;
    while (std::getline(iss, token, ','))
        nums.push_back(std::stoi(token));

    for (int n : nums) std::cout << n << ' '; // 10 20 30 40 50
    std::cout << "\n";

    // Round-trip: write values into stringstream, read them back
    std::stringstream ss;
    ss << 3.14 << " " << 42 << " " << "hello";
    double d; int i; std::string s;
    ss >> d >> i >> s;
    std::cout << d << " " << i << " " << s << "\n"; // 3.14 42 hello
}

std::format — Type-Safe Formatting (C++20)

std::format (from <format>) provides printf-style brevity with full type safety and extensibility. The format string is a Python-like {} placeholder syntax checked at compile time (in C++20 with std::format; fully constexpr-checked in C++23).
#include <format>
#include <string>
#include <iostream>
#include <vector>

int main()
{
    // Basic substitution
    std::string s1 = std::format("Hello, {}!", "world");
    std::cout << s1 << "\n"; // Hello, world!

    // Positional arguments
    std::string s2 = std::format("{0} + {1} = {2}", 1, 2, 3);
    std::cout << s2 << "\n"; // 1 + 2 = 3

    // Numeric formatting
    double pi = 3.14159265;
    std::cout << std::format("pi = {:.4f}\n", pi);           // pi = 3.1416
    std::cout << std::format("pi = {:e}\n",   pi);           // pi = 3.141593e+00
    std::cout << std::format("hex: {:x}\n",   255);          // hex: ff
    std::cout << std::format("HEX: {:08X}\n", 255);          // HEX: 000000FF

    // Width and alignment
    std::cout << std::format("{:>10}\n", "right");  //      right
    std::cout << std::format("{:<10}\n", "left");   // left
    std::cout << std::format("{:^10}\n", "center"); //   center

    // Print to stdout directly (C++23 std::print / std::println)
    // std::println("Value = {}", 42); // C++23

    // Format into a stream
    std::cout << std::format("Items: {:d}\n", 42);
}
std::format requires /std:c++20 or /std:c++latest. Visual Studio 2019 16.10+ and Visual Studio 2022 both ship a complete <format> implementation. Use std::vformat and std::make_format_args for runtime-variable format strings.

Wide-Character and Unicode I/O

Windows applications often need to handle wide characters. The <iostream> wide counterparts (wcin, wcout, wcerr) handle wchar_t streams:
#include <iostream>
#include <string>

int main()
{
    std::wstring name = L"Ångström";
    std::wcout << L"Name: " << name << L"\n";

    // Read a wide line
    std::wstring line;
    std::getline(std::wcin, line);
}
You cannot mix narrow (cin/cout) and wide (wcin/wcout) operations on the same stream after the orientation is set. Determine which orientation you need at the start of the program and stick with it.

Choosing the Right String/IO Facility

Use std::string for most text. Use std::wstring when interfacing with Windows APIs that require wchar_t. Use std::string_view (C++17) for read-only access to string data without copying — particularly in function parameters.
Prefer std::format (C++20) for new code: it is type-safe, locale-aware by default, and more readable than printf-family functions. Use ostringstream when targeting C++17 or earlier. Avoid sprintf/printf in C++ code — they have no type safety.
Use std::format for building a single formatted string. Use std::stringstream for more complex parsing tasks (tokenizing, reading structured input) where the stream extraction operators (>>) are convenient.

See Also

Build docs developers (and LLMs) love