std::from_chars în C++

Citește un număr dintr-un text, foarte rapid, fără excepții, cu raport exact despre erori.

Sintaxă
#include <charconv>
std::from_chars_result from_chars(const char* inceput, const char* sfarsit, int& valoare, int baza = 10);
std::from_chars_result from_chars(const char* inceput, const char* sfarsit, double& valoare);

Ce face std::from_chars

std::from_chars citește un număr de la începutul zonei [inceput, sfarsit) și îl pune în variabila dată. Nu aruncă excepții și nu alocă memorie; rezultatul spune unde s-a oprit (ptr) și dacă a reușit (ec).

Este mai strict decât stoi: nu sare peste spații și nu acceptă semnul +. La eroare, ec este std::errc::invalid_argument (nu e număr) sau std::errc::result_out_of_range (prea mare), iar variabila rămâne neschimbată.

Merge foarte bine cu std::string_view: std::from_chars(v.data(), v.data() + v.size(), x).

Parametri

Parametru Descriere
inceput, sfarsit Textul de citit.
valoare Variabila în care se pune numărul (int, long, double etc.).
baza Pentru întregi: baza (2–36).

Ce returnează

Un std::from_chars_result cu câmpurile ptr și ec.

Exemple

Exemplul 1: Număr urmat de text

#include <charconv>
#include <iostream>
#include <string_view>

int main() {
    std::string_view text = "250 lei";
    int suma = 0;
    auto [ptr, ec] = std::from_chars(text.data(), text.data() + text.size(), suma);
    if (ec == std::errc{}) {
        std::cout << "Suma: " << suma << '\n';
        std::cout << "Rest: [" << std::string_view(ptr, text.data() + text.size()) << "]\n";
    }
}

Rezultat

Suma: 250
Rest: [ lei]

Exemplul 2: Erori raportate, fără excepții

#include <charconv>
#include <iostream>
#include <string_view>
#include <system_error>

void citeste(std::string_view s) {
    int x = -1;
    auto r = std::from_chars(s.data(), s.data() + s.size(), x);
    std::cout << "\"" << s << "\": ";
    if (r.ec == std::errc::invalid_argument) std::cout << "nu este număr";
    else if (r.ec == std::errc::result_out_of_range) std::cout << "prea mare";
    else std::cout << x;
    std::cout << " (x = " << x << ")\n";
}

int main() {
    citeste("42");
    citeste("abc");
    citeste(" 42");
    citeste("99999999999");
}

Rezultat

"42": 42 (x = 42)
"abc": nu este număr (x = -1)
" 42": nu este număr (x = -1)
"99999999999": prea mare (x = -1)

Exemplul 3: Numere reale și hexazecimale

#include <charconv>
#include <iostream>
#include <string_view>

int main() {
    std::string_view pret = "19.99";
    double p = 0;
    std::from_chars(pret.data(), pret.data() + pret.size(), p);
    std::cout << p * 2 << '\n';

    std::string_view culoare = "ff8800";
    int rgb = 0;
    std::from_chars(culoare.data(), culoare.data() + culoare.size(), rgb, 16);
    std::cout << rgb << '\n';
}

Rezultat

39.98
16746496

Greșeli frecvente

  • Te aștepți să sară peste spațiile de la început ca stoi: " 42" dă invalid_argument.
  • Nu verifici ec și folosești variabila: la eroare ea are valoarea veche, nu 0.

Comenzi înrudite

  • std::to_chars: Scrie un număr ca text într-un tablou de char, foarte rapid, fără alocări și fără excepții.
  • std::stoi: Transformă un text în număr întreg (int, long, long long, unsigned long), cu excepții la erori.
  • std::stod: Transformă un text într-un număr real: stod în double, stof în float.
  • std::string_view: Vedere doar pentru citire asupra unui text existent, fără copiere; se poate micșora la capete.