Click here to Skip to main content
15,867,488 members
Articles / General Programming / String

StrToNum - A Header-only Library to Convert char and wchar_t Text Strings to Numbers

Rate me:
Please Sign up or sign in to vote.
4.64/5 (8 votes)
13 Mar 2024Apache1 min read 25.5K   163   14   13
String to number conversion library, for char and wchar_t strings
This article discusses StrToNum which is a Header-only library to convert char and wchar_t Text strings to numbers.

StrToNum

Introduction

StrToNum is a header-only library for converting char and wchar_t strings to numbers. The library is fully constexpr, which means that conversions can be done at compile time if a converting string is a constexpr string.

StrToNum is completely based on the Microsoft's std::from_chars implementation from the <charconv> standard header. The one significant difference though is the ability to work with wchar_t strings, because the C++ standard doesn't provide such functionality at the moment.

StrToNum features std::(w)string_view as an input, so you are no longer obliged to have only null-terminated strings, which is mandatory in all std::strto* functions family.

The library also recognizes 0x and 0X prefixes as hex strings, when iBase is 0 or 16, which std::from_chars doesn't.

As a return type StrToNum uses either std::optional (by default) or very convenient std::expected from c++23, which holds either a converted number or a from_chars_result struct in case of converting error. Both these types are very similar. To use the std::expected version use the /DSTN_USE_EXPECTED compiler flag.

template<typename IntegralT> requires std::is_integral_v<IntegralT>
[[nodiscard]] constexpr auto StrToNum(std::string_view sv, int iBase = 0)noexcept
->std::optional<IntegralT>
template<typename IntegralT> requires std::is_integral_v<IntegralT>
[[nodiscard]] constexpr auto StrToNum(std::wstring_view wsv, int iBase = 0)noexcept
->std::optional<IntegralT>
template<typename FloatingT> requires std::is_floating_point_v<FloatingT>
[[nodiscard]] constexpr auto StrToNum(std::string_view sv, chars_format fmt = chars_format::general)noexcept
->std::optional<FloatingT>
template<typename FloatingT> requires std::is_floating_point_v<FloatingT>
[[nodiscard]] constexpr auto StrToNum(std::wstring_view wsv, chars_format fmt = chars_format::general)noexcept
->std::optional<FloatingT>

Basically StrToNum is a thin wrapper over the std::from_chars machinery with the convenient interface and the ability to work with wchar_t strings. Non-allocating, non-throwing, locale-independent.

Aliases

StrToNum is the main templated method which is very easy to use. But there are also predefined wrappers for convenience for all integral and floating types:

[[nodiscard]] inline constexpr auto StrToInt8(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::int8_t>;
[[nodiscard]] inline constexpr auto StrToUInt8(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::uint8_t>;
[[nodiscard]] inline constexpr auto StrToInt16(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::int16_t>;
[[nodiscard]] inline constexpr auto StrToUInt16(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::uint16_t>;
[[nodiscard]] inline constexpr auto StrToInt32(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::int32_t>;
[[nodiscard]] inline constexpr auto StrToUInt32(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::uint32_t>;
[[nodiscard]] inline constexpr auto StrToInt64(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::int64_t>;
[[nodiscard]] inline constexpr auto StrToUInt64(std::string_view sv, int iBase = 0)noexcept
->std::optional<std::uint64_t>;
[[nodiscard]] inline constexpr auto StrToFloat(std::string_view sv, chars_format fmt = chars_format::general)noexcept
->std::optional<float>;
[[nodiscard]] inline constexpr auto StrToDouble(std::string_view sv, chars_format fmt = chars_format::general)noexcept
->std::optional<double>;

Example

#include <iomanip>
#include <iostream>
#include "StrToNum.h"

int main()
{
    constexpr auto str = "1234567890";
    constexpr auto wstr = L"1234567890";

    constexpr auto Int1 = stn::StrToInt32(std::string_view(str).substr(0, 5));
    static_assert(Int1 == 12345);
    std::cout << "Int1 = " << Int1.value_or(-1) << "\n";

    constexpr auto Int2 = stn::StrToInt32(std::wstring_view(wstr).substr(5));
    static_assert(Int2 == 67890);
    std::cout << "Int2 = " << Int2.value_or(-1) << "\n";

    constexpr auto LL1 = stn::StrToInt64("0xABCDEF");
    static_assert(LL1 == 0xABCDEF);
    std::cout << std::hex << "LL1 = " << LL1.value_or(-1) << "\n";

    constexpr auto LL2 = stn::StrToInt64(L"0xFEDCBA");
    static_assert(LL2 == 0xFEDCBA);
    std::cout << std::hex << "LL2 = " << LL2.value_or(-1) << "\n";

    constexpr auto LL3 = stn::StrToInt64(L"-0xACE987");
    static_assert(LL3 == -0xACE987);
    std::cout << std::dec << "LL3 = " << LL3.value_or(-1) << "\n";

    constexpr auto Dbl1 = stn::StrToDouble("3.14159265358979");
    static_assert(Dbl1 == 3.14159265358979);
    std::cout << std::fixed << std::setprecision(14) << "Dbl1 = " << Dbl1.value_or(-1.) << "\n";

    constexpr auto Dbl2 = stn::StrToDouble(L"-987.654321");
    static_assert(Dbl2 == -987.654321);
    std::cout << std::fixed << std::setprecision(6) << "Dbl2 = " << Dbl2.value_or(-1.) << "\n";

    constexpr auto flHex = stn::StrToFloat(L"0x1.Fp-2", stn::chars_format::hex);
    static_assert(flHex == 0x1.Fp-2);
    std::cout << std::fixed << std::setprecision(6) << "flHex = " << flHex.value_or(-1.) << "\n";
}
This article was originally posted at https://github.com/jovibor/StrToNum

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Zaire Zaire
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA27-Jan-24 18:09
professionalȘtefan-Mihai MOGA27-Jan-24 18:09 
GeneralMy vote of 5 Pin
wildcat3247-Apr-23 14:39
wildcat3247-Apr-23 14:39 
Questionon StrToD() Pin
Member 141051556-Apr-23 22:24
Member 141051556-Apr-23 22:24 
AnswerRe: on StrToD() Pin
Jovibor6-Apr-23 22:35
Jovibor6-Apr-23 22:35 
GeneralRe: on StrToD() Pin
Member 1410515515-Apr-23 10:03
Member 1410515515-Apr-23 10:03 
Questionatoi vs StrToNum Pin
jmaida3-Nov-22 17:59
jmaida3-Nov-22 17:59 
I use atoi in normal C how is this different from StrToNum
"A little time, a little trouble, your better day"
Badfinger

AnswerRe: atoi vs StrToNum Pin
Jovibor4-Nov-22 12:07
Jovibor4-Nov-22 12:07 
GeneralRe: atoi vs StrToNum Pin
jmaida4-Nov-22 12:19
jmaida4-Nov-22 12:19 
GeneralRe: atoi vs StrToNum Pin
Jovibor4-Nov-22 14:06
Jovibor4-Nov-22 14:06 
GeneralRe: atoi vs StrToNum Pin
jmaida4-Nov-22 15:33
jmaida4-Nov-22 15:33 
SuggestionCrippled example Pin
E. Papulovskiy19-Jun-22 21:05
E. Papulovskiy19-Jun-22 21:05 
GeneralRe: Crippled example Pin
Jovibor19-Jun-22 22:02
Jovibor19-Jun-22 22:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.