Cara mengonversi angka menjadi string dan sebaliknya di C ++

120

Karena pertanyaan ini ditanyakan setiap minggu, FAQ ini mungkin dapat membantu banyak pengguna.

  • Cara mengonversi integer menjadi string di C ++

  • cara mengubah string menjadi integer di C ++

  • cara mengonversi bilangan floating-point menjadi string di C ++

  • cara mengonversi string menjadi bilangan floating-point di C ++

Armen Tsirunyan
sumber
Untuk konversi seperti ini, saya memiliki bookmark converttypes.com
Firzok Nadeem

Jawaban:

129

Pembaruan untuk C ++ 11

Sebagai C++11standar, konversi string-ke-angka dan sebaliknya dibangun ke dalam pustaka standar. Semua fungsi berikut ada di <string>(sesuai paragraf 21.5).

string ke numerik

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);

Masing-masing mengambil string sebagai masukan dan akan mencoba mengubahnya menjadi angka. Jika tidak ada nomor yang valid dapat dibuat, misalnya karena tidak ada data numerik atau nomor di luar kisaran untuk tipe tersebut, pengecualian dilemparkan ( std::invalid_argumentatau std::out_of_range).

Jika konversi berhasil dan idxtidak 0,idx akan berisi indeks dari karakter pertama yang tidak digunakan untuk decoding. Ini bisa menjadi indeks di belakang karakter terakhir.

Akhirnya, tipe integral memungkinkan untuk menentukan basis, untuk angka yang lebih besar dari 9, alfabet diasumsikan ( a=10sampai z=35). Anda dapat menemukan informasi selengkapnya tentang pemformatan tepat yang dapat diuraikan di sini untuk bilangan floating-point , bilangan bulat bertanda dan bilangan bulat tak bertanda .

Terakhir, untuk setiap fungsi ada juga kelebihan beban yang menerima a std::wstringsebagai parameter pertamanya.

numerik ke string

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);

Ini lebih mudah, Anda meneruskan tipe numerik yang sesuai dan Anda mendapatkan string kembali. Untuk opsi pemformatan, Anda harus kembali ke opsi aliran string C ++ 03 dan menggunakan manipulator aliran, seperti yang dijelaskan dalam jawaban lain di sini.

Seperti dicatat dalam komentar, fungsi-fungsi ini kembali ke presisi mantissa default yang mungkin bukan presisi maksimum. Jika lebih presisi diperlukan untuk aplikasi Anda, sebaiknya kembali ke prosedur pemformatan string lainnya.

Ada juga fungsi serupa yang didefinisikan yang diberi nama to_wstring, ini akan mengembalikan a std::wstring.

KillianDS
sumber
3
std::to_stringkehilangan banyak presisi untuk tipe floating point. Misalnya double f = 23.4323897462387526; std::string f_str = std::to_string(f);mengembalikan string 23,432390. Ini membuat tidak mungkin untuk membulatkan nilai floating point menggunakan fungsi ini.
fun4jimmy
@ fun4jimmy apakah ini pembatasan yang diberlakukan oleh standar atau implementasi tertentu? Akan menambahkannya ke jawaban. Bukan berarti melayang-layang melalui string adalah ide yang bagus.
KillianDS
Standar C ++ mengatakan " Mengembalikan: Setiap fungsi mengembalikan objek string yang berisi representasi karakter dari nilai argumennya yang akan dihasilkan dengan memanggil sprintf(buf, fmt, val)dengan penentu format "% d " , "% u " , "% ld " , " % lu " , "% lld " , "% llu " , "% f " , "% f " , atau "% Lf " , masing-masing, yang bufmenunjukkan buffer karakter internal dengan ukuran yang memadai. " Saya telah melihat C99 standar untuk printf dan saya berpikir bahwa jumlah tempat desimal tergantung pada difloat.h .#define DECIMAL_DIG
fun4jimmy
Bruce Dawson memiliki beberapa artikel bagus tentang presisi yang dibutuhkan untuk bilangan floating point round tripping di blognya .
fun4jimmy
2
Semua fungsi ini dipengaruhi oleh lokal global, yang dapat menyebabkan masalah jika Anda menggunakan pustaka, dan terutama jika menggunakan utas. Lihat pertanyaan saya di sini: stackoverflow.com/questions/31977457/…
Ident
86

Cara mengubah angka menjadi string di C ++ 03

  1. Jangan gunakan pada itoaatau itoffungsi karena mereka adalah non-standar dan karena itu tidak portabel.
  2. Gunakan aliran string

     #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"  
    }

    Perhatikan bahwa Anda dapat menggunakan aliran string juga untuk mengonversi angka floating-point menjadi string, dan juga untuk memformat string sesuai keinginan, seperti dengan 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" 

    Anda dapat menggunakan manipulator aliran, seperti std::endl, std::hexdan fungsistd::setw() , std::setprecision()dll. Dengan aliran string dengan cara yang persis sama seperti dengancout

    Jangan bingung std::ostringstream denganstd::ostrstream. Yang terakhir tidak digunakan lagi

  3. Gunakan boost lexical cast . Jika Anda tidak terbiasa dengan boost, ada baiknya Anda memulai dengan pustaka kecil seperti lexical_cast ini. Untuk mengunduh dan menginstal boost dan dokumentasinya buka di sini . Meskipun peningkatan tidak ada dalam standar C ++, banyak pustaka peningkatan menjadi standar pada akhirnya dan dorongan secara luas dianggap sebagai pustaka C ++ terbaik.

    Pemeran leksikal menggunakan aliran di bawahnya, jadi pada dasarnya opsi ini sama dengan yang sebelumnya, hanya kurang bertele-tele.

    #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"
    }

Cara mengonversi string menjadi angka di C ++ 03

  1. Opsi paling ringan, diwarisi dari C, adalah fungsi atoi(untuk bilangan bulat (alfabet ke bilangan bulat)) dan atof(untuk nilai floating-point (menurut abjad ke pelampung)). Fungsi-fungsi ini mengambil string gaya-C sebagai argumen ( const char *) dan oleh karena itu penggunaannya dapat dianggap sebagai praktik C ++ yang tidak terlalu baik. cplusplus.com memiliki dokumentasi yang mudah dipahami tentang atoi dan atof termasuk bagaimana mereka berperilaku jika terjadi masukan yang buruk. Namun tautan tersebut berisi kesalahan dalam hal menurut standar jika nomor masukan terlalu besar untuk muat dalam jenis target, perilaku tidak ditentukan.

    #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*
    }
  2. Gunakan aliran string (kali ini aliran string masukan, istringstream). Sekali lagi, istringstream digunakan seperti cin. Sekali lagi, jangan bingung istringstreamdengan istrstream. Yang terakhir tidak digunakan lagi.

    #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  
    }
  3. Gunakan boost lexical cast .

    #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
    }       

    Jika ada masukan yang buruk, lexical_castakan muncul pengecualian tipeboost::bad_lexical_cast

Armen Tsirunyan
sumber
4
Dokumentasi cplusplus untuk atoitidak bagus, itu salah. Gagal menyebutkan bahwa jika nilai numerik dari string tidak dapat direpresentasikan int, maka perilakunya tidak ditentukan. Sebaliknya dikatakan bahwa nilai di luar jangkauan dijepit ke INT_MAX/ INT_MIN, yang tidak dapat saya temukan di C ++ 03 atau C89. Untuk input yang tidak tepercaya / tidak diverifikasi, atau saat menangani basis yang tidak didukung oleh aliran, Anda memerlukannya strtol, yang telah menentukan perilaku kesalahan. Dan komentar serupa untuk atof/ strtod.
Steve Jessop
2
cplusplus.com salah tentang "atoi". Ini mengatakan tentang nilai kembali "Jika tidak ada konversi valid yang dapat dilakukan, nilai nol dikembalikan. Jika nilai yang benar berada di luar rentang nilai yang dapat direpresentasikan, INT_MAX atau INT_MIN dikembalikan", tetapi spek mengatakan bahwa "Jika nilai hasil tidak dapat diwakili, perilakunya tidak ditentukan. " dan bahwa "Kecuali untuk perilaku kesalahan, mereka setara dengan (int)strtol(nptr, (char **)NULL, 10). Fungsi atoi [...] mengembalikan nilai yang dikonversi.". cplusplus.com dikenal sebagai sumber informasi buruk yang luar biasa untuk pemula.
Johannes Schaub - litb
istr >> i1 >> f >> i2;sangat merindukan cek kesuksesan.
sbi
4
Mungkin ingin menambahkanstd::to_string
Pubby
1
@ArmenTsirunyan: +10 dari akhir saya, Salah satu jawaban terbaik yang pernah saya lihat secara mendalam. Terima kasih atas jawaban anda.
Abhineet
4

Di C ++ 17, fungsi baru std :: to_chars dan std :: from_chars diperkenalkan di header charconv .

std :: to_chars bersifat lokal-independen, tidak mengalokasikan, dan tidak melempar.

Hanya sebagian kecil dari kebijakan pemformatan yang digunakan oleh pustaka lain (seperti std :: sprintf) yang disediakan.

Dari std :: to_chars , sama untuk std :: from_chars .

Jaminan bahwa std :: from_chars dapat memulihkan setiap nilai floating-point yang diformat oleh to_chars dengan tepat hanya diberikan jika kedua fungsi berasal dari implementasi yang sama

 // 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);
}

Meskipun tidak sepenuhnya diimplementasikan oleh kompiler, itu pasti akan diimplementasikan.

JiaHao Xu
sumber
0

Saya mencuri kelas nyaman ini dari suatu tempat di sini di StackOverflow untuk mengonversi apa pun yang dapat dialirkan ke string:

// 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_;
};

Dan kemudian Anda menggunakannya sebagai;

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

Cukup bagus!

Juga saya menggunakan fungsi ini untuk mengubah string menjadi apa pun yang dapat dialirkan, meskipun tidak terlalu aman jika Anda mencoba mengurai string yang tidak berisi angka; (dan itu juga tidak secerdas yang terakhir)

// 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;
}

Digunakan sebagai:

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

Anda mungkin juga menginginkan versi untuk wstrings.

Viktor Sehr
sumber
5
Inilah yang dilakukan boost :: lexical_cast. Dan boost melakukannya dalam fasion yang lebih umum.
Armen Tsirunyan
Benar, saya membaca sekilas jawaban pertama dan tidak melihat peningkatan :: lexical_casts.
Viktor Sehr