Как преобразовать число в строку и наоборот в С++

Поскольку этот вопрос задается каждую неделю, этот FAQ может помочь многим пользователям.

  • Как преобразовать целое число в строку в С++

  • как преобразовать строку в целое число в С++

  • как преобразовать число с плавающей запятой в строку в С++

  • как преобразовать строку в число с плавающей запятой в С++

Ответ 1

Обновление для С++ 11

Как и в стандарте C++11, преобразование строк в число и наоборот встроены в стандартную библиотеку. Все следующие функции присутствуют в <string> (согласно параграфу 21.5).

строка в числовой

float              stof(const string& str, size_t *idx = 0);
double             stod(const string& str, size_t *idx = 0);
long double        stold(const string& str, size_t *idx = 0);
int                stoi(const string& str, size_t *idx = 0, int base = 10);
long               stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long      stoul(const string& str, size_t *idx = 0, int base = 10);
long long          stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);

Каждый из них берет строку как ввод и пытается преобразовать ее в число. Если допустимый номер не может быть сконструирован, например, потому что нет числовых данных или число выходит за пределы диапазона для этого типа, генерируется исключение (std::invalid_argument или std::out_of_range).

Если преобразование выполнено успешно, а idx не 0, idx будет содержать индекс первого символа, который не использовался для декодирования. Это может быть индекс за последним символом.

Наконец, интегральные типы позволяют указать базу, для цифр больше 9, предполагается, что алфавит (a=10 до z=35). Вы можете найти более подробную информацию о точном форматировании, которое можно проанализировать здесь для чисел с плавающей запятой, целых чисел со знаком и целые числа без знака.

Наконец, для каждой функции есть также перегрузка, которая принимает std::wstring как первый параметр.

числовое значение в строке

string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);

Это более прямолинейно, вы передаете соответствующий числовой тип, и вы возвращаете строку. Для параметров форматирования вы должны вернуться к опции stringsream С++ 03 и использовать манипуляторы потока, как объясняется в другом ответе здесь.

Как отмечено в комментариях, эти функции возвращаются к заданной по умолчанию точности мантиссы, которая, вероятно, не является максимальной точностью. Если для вашего приложения требуется более высокая точность, лучше также вернуться к другим процедурам форматирования строк.

Существуют также аналогичные функции, которые называются to_wstring, они возвращают std::wstring.

Ответ 2

Как преобразовать число в строку в С++ 03

  • Не используйте функции itoa или itof, потому что они нестандартны и поэтому не переносятся.
  • Использовать строковые потоки

     #include <sstream>  //include this to use string streams
     #include <string> 
    
    int main()
    {    
        int number = 1234;
    
        std::ostringstream ostr; //output string stream
        ostr << number; //use the string stream just like cout,
        //except the stream prints not to stdout but to a string.
    
        std::string theNumberString = ostr.str(); //the str() function of the stream 
        //returns the string.
    
        //now  theNumberString is "1234"  
    }
    

    Обратите внимание, что вы можете использовать строковые потоки также для преобразования чисел с плавающей запятой в строку, а также для форматирования строки по вашему желанию, точно так же, как с помощью cout

    std::ostringstream ostr;
    float f = 1.2;
    int i = 3;
    ostr << f << " + " i << " = " << f + i;   
    std::string s = ostr.str();
    //now s is "1.2 + 3 = 4.2" 
    

    Вы можете использовать манипуляторы потоков, такие как std::endl, std::hex и функции std::setw(), std::setprecision() и т.д. со строковыми потоками точно так же, как с cout

    Не путайте std::ostringstream с помощью std::ostrstream. Последнее устарело

  • Используйте повысить лексический листинг. Если вы не знакомы с повышением, неплохо начать с небольшой библиотеки, такой как lexical_cast. Чтобы загрузить и установить boost и его документацию перейдите сюда. Хотя повышение не в стандарте С++, многие библиотеки boost становятся стандартизованными в конечном итоге, а boost широко рассматривается в лучших библиотеках С++.

    Лексический лит использует потоки снизу, поэтому в основном эта опция такая же, как и предыдущая, только немного подробней.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       float f = 1.2;
       int i = 42;
       std::string sf = boost::lexical_cast<std::string>(f); //sf is "1.2"
       std::string si = boost::lexical_cast<std::string>(i); //sf is "42"
    }
    

Как преобразовать строку в число в С++ 03

  • Самый легкий вариант, унаследованный от C, - это функции atoi (для целых чисел (от алфавита до целого)) и atof (для значений с плавающей запятой (в алфавитном порядке для float)). Эти функции принимают строку C-стиля в качестве аргумента (const char *), и поэтому их использование может считаться не совсем хорошей практикой на С++. cplusplus.com имеет легкую для понимания документацию на atoi и atof, включая то, как они ведут себя в случае плохого ввода. Однако ссылка содержит ошибку в том, что согласно стандарту, если входной номер слишком велик, чтобы соответствовать целевому типу, поведение undefined.

    #include <cstdlib> //the standard C library header
    #include <string>
    int main()
    {
        std::string si = "12";
        std::string sf = "1.2";
        int i = atoi(si.c_str()); //the c_str() function "converts" 
        double f = atof(sf.c_str()); //std::string to const char*
    }
    
  • Используйте строковые потоки (на этот раз поток входных строк, istringstream). Опять же, istringstream используется так же, как cin. Опять же, не путайте istringstream с istrstream. Последнее устарело.

    #include <sstream>
    #include <string>
    int main()
    {
       std::string inputString = "1234 12.3 44";
       std::istringstream istr(inputString);
       int i1, i2;
       float f;
       istr >> i1 >> f >> i2;
       //i1 is 1234, f is 12.3, i2 is 44  
    }
    
  • Используйте повысить лексический листинг.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       std::string sf = "42.2"; 
       std::string si = "42";
       float f = boost::lexical_cast<float>(sf); //f is 42.2
       int i = boost::lexical_cast<int>(si);  //i is 42
    }       
    

    В случае плохого ввода lexical_cast выдает исключение типа boost::bad_lexical_cast

Ответ 3

В С++ 17 новые функции std :: to_chars и std :: from_chars введены в заголовок charconv.

std :: to_chars не зависит от локали, не выделяется и не выбрасывает.

Предоставляется только небольшое подмножество политик форматирования, используемых другими библиотеками (такими как std :: sprintf).

Из std :: to_chars, то же самое для std :: from_chars.

Гарантия того, что std :: from_chars может восстановить каждое значение с плавающей запятой, отформатированное с помощью to_chars, предоставляется только в том случае, если обе функции имеют одну и ту же реализацию

 // See en.cppreference.com for more information, including format control.
#include <cstdio>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <charconv>

using Type =  /* Any fundamental type */ ;
std::size_t buffer_size = /* ... */ ;

[[noreturn]] void report_and_exit(int ret, const char *output) noexcept 
{
    std::printf("%s\n", output);
    std::exit(ret);
}
void check(const std::errc &ec) noexcept
{
    if (ec ==  std::errc::value_too_large)
        report_and_exit(1, "Failed");
}
int main() {
    char buffer[buffer_size];        
    Type val_to_be_converted, result_of_converted_back;

    auto result1 = std::to_chars(buffer, buffer + buffer_size,  val_to_be_converted);
    check(result1.ec);
    *result1.ptr = '\0';

    auto result2 = std::from_chars(buffer, result1.ptr, result_of_converted_back);
    check(result2.ec);

    assert(val_to_be_converted == result_of_converted_back);
    report_and_exit(0, buffer);
}

Хотя это не полностью реализовано компиляторами, оно определенно будет реализовано.

Ответ 4

Я украл этот класс convienent от где-то здесь, в StackOverflow, чтобы преобразовать все, что можно передать в строку:

// make_string
class make_string {
public:
  template <typename T>
  make_string& operator<<( T const & val ) {
    buffer_ << val;
    return *this;
  }
  operator std::string() const {
    return buffer_.str();
  }
private:
  std::ostringstream buffer_;
};

И затем вы используете его как:

string str = make_string() << 6 << 8 << "hello";

Совершенно изящный!

Кроме того, я использую эту функцию для преобразования строк в любые потоки данных, поскольку это не очень безопасно, если вы пытаетесь проанализировать строку, не содержащую число; (и его не так умно, как последний)

// parse_string
template <typename RETURN_TYPE, typename STRING_TYPE>
RETURN_TYPE parse_string(const STRING_TYPE& str) {
  std::stringstream buf;
  buf << str;
  RETURN_TYPE val;
  buf >> val;
  return val;
}

Использовать как:

int x = parse_string<int>("78");

Вам также могут понадобиться версии для wstrings.