# How to Use fmtlib for Character and String Presentation Types

> Learn how to use fmtlib for character and string presentation types. Discover the `'c'` and `'s'` conversions for flexible formatting with the fmt library.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-08

---

**The fmt library selects character presentation via `presentation_type::chr` when using the `'c'` conversion, and string presentation via `presentation_type::string` when using the `'s'` conversion, with both types parsed in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) and handled during final formatting in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h).**

The **fmtlib/fmt** repository provides a modern C++ formatting library that routes arguments through a strongly-typed `format_spec` structure. When you use fmtlib for character and string presentation types, the library inspects your format specifier at compile time (or runtime for dynamic strings) to determine whether to treat the argument as a single Unicode code point or as a sequence of characters.

## Understanding Presentation Types in fmtlib

Every format operation in fmtlib begins by parsing the format string into a **`format_spec`** object. This structure contains a **`presentation_type`** enum that dictates how the argument should be rendered.

According to the source code in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) (around line 654), the `presentation_type` enum defines distinct values for different formatting behaviors. For text output, two values are critical:

- **`presentation_type::chr`** – Indicates single-character formatting
- **`presentation_type::string`** – Indicates string formatting

The parser determines which type to use by examining the conversion character in your format specifier. Inside [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h), the `parse_presentation_type` function handles this logic:

```cpp
case 'c':  // character conversion
    return parse_presentation_type(presentation_type::chr, integral_set);
case 's':  // string conversion
    return parse_presentation_type(presentation_type::string,
                                   cstring_set | string_set);

```

Once parsing completes, the `format_spec` stores the selected type (accessible via `specs.type()`), which the main formatting engine in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) uses to route output through the appropriate branch in `fmt::vformat`.

## Character Presentation Type (presentation_type::chr)

### How Character Formatting Works

When you specify the **`'c'`** conversion, fmtlib treats the argument as a single Unicode code point regardless of whether you pass an integer or a character type. The `parse_presentation_type` function sets the internal type to `presentation_type::chr`, and the final output routine in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) renders the value using the appropriate character encoding (UTF-8, UTF-16, or UTF-32).

This presentation type accepts any integral value that represents a valid code point. The library performs the necessary encoding conversion automatically based on the output context.

### Character Formatting Examples

```cpp
#include <fmt/core.h>

int main() {
    // Format integer 65 as the character 'A'
    fmt::print("Char: {:c}\n", 65);          // Output: Char: A
    
    // Use width and alignment with character presentation
    fmt::print("Padded: {:>5c}\n", 'Z');      // Output: Padded:     Z
    
    // Character presentation with fill character
    fmt::print("Filled: {:*^3c}\n", 'X');     // Output: Filled: *X*
}

```

The character type respects **width**, **alignment**, and **fill** specifiers, allowing you to pad single characters within a fixed field.

## String Presentation Type (presentation_type::string)

### How String Formatting Works

The **`'s'`** conversion triggers `presentation_type::string`, which fmtlib applies to `char` pointers, `std::string`, `std::string_view`, and any type implicitly convertible to a C-style string. During parsing in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h), the parser selects this type when it encounters the `'s'` conversion or when the argument type matches the string type sets (`cstring_set | string_set`).

In [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), the `vformat` implementation checks `specs.type()` and routes string arguments through dedicated output routines that respect **precision** (maximum characters to display) and **width** (minimum field size).

### String Formatting Examples

```cpp
#include <fmt/core.h>
#include <string>

int main() {
    // Basic string presentation
    std::string name = "fmt";
    fmt::print("Library: {:s}\n", name);     // Output: Library: fmt
    
    // Truncate with precision
    fmt::print("Truncated: {:.3s}\n", "fmtlib"); 
    // Output: Truncated: fmt
    
    // Combine width, alignment, and precision
    fmt::print("|{:<10.5s}|\n", "formatted");
    // Output: |format    |
    
    // C-style string pointer
    const char* msg = "hello";
    fmt::print("Message: {:s}\n", msg);      // Output: Message: hello
}

```

## Format Specifier Reference

Both presentation types support the full fmtlib specification syntax:

| Specifier | Effect on Character (`:c`) | Effect on String (`:s`) |
|-----------|---------------------------|------------------------|
| **Width** | Minimum field width; pads with fill character | Minimum field width; pads if string is shorter |
| **Precision** | No effect (always single character) | Maximum number of characters to output |
| **Align** | `<` left, `>` right, `^` center | `<` left, `>` right, `^` center |
| **Fill** | Any character preceding align | Any character preceding align |

The [`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h) header provides C-style `printf` compatibility and maps `%c` and `%s` to these same presentation types internally.

## Summary

- **Character presentation** (`presentation_type::chr`) is selected by the `'c'` conversion in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) and renders integral values as single Unicode code points.
- **String presentation** (`presentation_type::string`) is selected by the `'s'` conversion and handles `std::string`, `std::string_view`, and C-style strings through the formatting engine in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h).
- Both types support width, alignment, and fill specifications, but only string presentation respects precision for truncation.
- The parsing logic in `parse_presentation_type` determines the presentation type at format-string compile time, while `fmt::vformat` dispatches to the appropriate output routine based on `specs.type()`.

## Frequently Asked Questions

### What is the difference between `{:c}` and `{:s}` in fmtlib?

**`{:c}` treats the argument as a single character code point**, accepting integers or character types and rendering exactly one Unicode character, while **`{:s}` treats the argument as a string sequence**, accepting pointer types, `std::string`, or `std::string_view` and rendering the full sequence (subject to precision limits). The underlying enum values `presentation_type::chr` and `presentation_type::string` in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) distinguish these behaviors.

### Can I use precision specifiers with character presentation types?

**No, precision specifiers have no effect on the `'c'` conversion.** Since `presentation_type::chr` always represents a single code point, the precision field is ignored. If you need to limit output with character types, you must handle the truncation before passing the value to the formatter, or use string presentation if the data is stored as a string.

### How does fmtlib handle Unicode when using character presentation?

**The fmt library treats character presentation as a Unicode code point** and encodes it according to the output context (UTF-8, UTF-16, or UTF-32). When you pass an integer to `{:c}`, fmtlib validates that it represents a valid code point and performs the necessary encoding conversion in the output routines defined in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), ensuring correct multi-byte character generation.

### Are these presentation types compatible with C printf-style formatting?

**Yes, fmtlib maintains compatibility through [`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h).** The `%c` conversion maps to `presentation_type::chr` and `%s` maps to `presentation_type::string`, routing through the same underlying formatting machinery as the modern `{}` syntax. However, the modern format specifiers provide additional capabilities like named arguments, compile-time checking, and more precise alignment controls that printf-style formatting cannot express.