22 Soru: Bir std :: string ve int nasıl birleştirilir?

tarafından oluşturulan soru Mon, Jan 23, 2017 12:00 AM

Bunun gerçekten basit olacağını düşünmüştüm, ancak bazı zorluklar sunuyor. Varsa

 
std::string name = "John";
int age = 21;

Tek bir "John21" dizesini almak için bunları nasıl birleştiririm?

    
613
  1. Herb Sutter'ın bu konuda iyi bir makalesi var: " Manor Çiftliklerinin Dizge Biçimleri ". Boost::lexical_cast, std::stringstream, std::strstream (kullanımdan kaldırılmıştır) ve sprintf'a karşı snprintf’u kapsar.
    2008-10-10 16: 54: 20Z
  2. Buna ekleyeyim: 'str = "hi"; str + = 5; cout < < str;' ve hiçbir etkisi yoktu. Bu çağrıları işleci + = (char) kapatır ve yazdırılamaz bir karakter ekler.
    2014-10-25 20: 00: 18Z
    22 Yanıtlar                              22                         

    Alfabetik sıraya göre:

     
    std::string name = "John";
    int age = 21;
    std::string result;
    
    // 1. with Boost
    result = name + boost::lexical_cast<std::string>(age);
    
    // 2. with C++11
    result = name + std::to_string(age);
    
    // 3. with FastFormat.Format
    fastformat::fmt(result, "{0}{1}", name, age);
    
    // 4. with FastFormat.Write
    fastformat::write(result, name, age);
    
    // 5. with the {fmt} library
    result = fmt::format("{}{}", name, age);
    
    // 6. with IOStreams
    std::stringstream sstm;
    sstm << name << age;
    result = sstm.str();
    
    // 7. with itoa
    char numstr[21]; // enough to hold all numbers up to 64-bits
    result = name + itoa(age, numstr, 10);
    
    // 8. with sprintf
    char numstr[21]; // enough to hold all numbers up to 64-bits
    sprintf(numstr, "%d", age);
    result = name + numstr;
    
    // 9. with STLSoft's integer_to_string
    char numstr[21]; // enough to hold all numbers up to 64-bits
    result = name + stlsoft::integer_to_string(numstr, 21, age);
    
    // 10. with STLSoft's winstl::int_to_string()
    result = name + winstl::int_to_string(age);
    
    // 11. With Poco NumberFormatter
    result = name + Poco::NumberFormatter().format(age);
    
    1. güvenli, ancak yavaş; Yükseltme (yalnızca başlık) gerektirir; çoğu /tüm platformlar
    2. güvenli, C ++ 11 gerektirir ( to_string () zaten dahil #include <string>’da)
    3. güvenli ve hızlı; Derlenmesi gereken FastFormat gerektirir; çoğu /tüm platformlar
    4. güvenli ve hızlı; Derlenmesi gereken FastFormat gerektirir; çoğu /tüm platformlar
    5. güvenli ve hızlı; Derleme veya yalnızca üstbilgi modunda kullanılabilecek {fmt} kitaplığı gerektirir; çoğu /tüm platformlar
    6. güvenli, yavaş ve ayrıntılı; #include <sstream> gerektirir (standart C ++ 'dan)
    7. kırılgandır (yeterince büyük bir tampon sağlamalısınız), hızlı ve ayrıntılı; itoa () standart olmayan bir eklentidir ve tüm platformlarda kullanılacağı garanti edilmez
    8. kırılgandır (yeterince büyük bir tampon sağlamalısınız), hızlı ve ayrıntılı; hiçbir şey gerektirmez (standart C ++ 'dır); tüm platformlar
    9. kırılgandır (yeterince büyük bir arabellek sağlamalısınız), muhtemelen en hızlı dönüşüm , ayrıntılı; STLSoft (yalnızca başlık) gerektirir; çoğu /tüm platformlar
    10. safe-ish (birden fazla kullanmıyorsanız int_to_string () tek bir ifadeyle çağrı yapın), hızlı; STLSoft (yalnızca başlık) gerektirir; Windows yalnızca
    11. güvenli, ancak yavaş; Poco C ++ gerektirir; çoğu /tüm platformlar
    1045
    2018-09-05 08: 17: 05Z
    1. Verdiğiniz bağlantıdan ayrı olarak, performans yorumlarınızı neye dayandırıyorsunuz?
      2009-05-22 21: 45: 14Z
    2. Karşılaştırma için bkz. tinyurl.com/234rq9u çözümlerden bazıları
      2010-10-27 14: 08: 30Z
    3. Bu, neredeyse tüm saygınlığınızı tek bir cevaptan alıyor! Siz şanslı fasulye;) 8 standart C (tabii ki ayrıca C ++) olduğunu düşünüyorum, ancak muhtemelen farklılaşmaya değer.
      2018-08-16 11: 54: 39Z
    4. Python'un bununla doğru düştüğünü söyleyebilir miyim? "John" + str(21)
      2019-06-25 21: 47: 21Z

    C ++ 11’de std::to_string’u kullanabilirsiniz, örneğin:

     
    auto result = name + std::to_string( age );
    
        
    248
    2018-04-20 09: 12: 14Z

    Boost varsa, boost::lexical_cast<std::string>(age) kullanarak tam sayıyı bir dizeye dönüştürebilirsiniz.

    Başka bir yol, stringstreams kullanmaktır:

     
    std::stringstream ss;
    ss << age;
    std::cout << name << ss.str() << std::endl;
    

    Üçüncü bir yaklaşım C kütüphanesinden sprintf veya snprintf kullanmak olacaktır.

     
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "%s%d", name.c_str(), age);
    std::cout << buffer << std::endl;
    

    itoa kullanılarak önerilen diğer posterler. Bu standart bir fonksiyon DEĞİLDİR, bu nedenle kullanırsanız kodunuz taşınabilir olmayacak. Desteklemeyen derleyiciler var.

        
    82
    2008-10-10 15: 33: 25Z
    1. Snprintf'nin dizgiyi null sonlandırmasının garanti edilmediğine dikkat edin. İşte çalıştığından emin olmanın bir yolu: < pre > char tamponu [128]; tampon [sizeof (tampon) -1] = '\0'; snprintf (tampon, sizeof (tampon) -1, "% s% d", isim.c_str (), yaş); std :: cout < < arabellek < STD :: endl; Ve m /ön ve gt;
      2008-10-10 16: 06: 50Z
    2. Benim eğilimim hiçbir zaman sprintf kullanmak olmayacak, çünkü bu tampon taşmalarına neden olabilir. Yukarıdaki örnek, adı çok uzun olsaydı sprintf kullanmanın güvenli olmadığı durumlarda iyi bir örnektir.
      2008-10-11 18: 06: 13Z
    3. snprintf'in standart olmayan c ++ olduğuna dikkat edin (bahsettiğiniz itoa gibi). c99'dan alındı ​​
      2009-02-09 03: 36: 53Z
    4. snprintf’da bir güncelleme: C ++ 11’de var.
      2013-07-03 18: 05: 58Z
    5. @ terson: Yanıtta hiçbir sprintf oluşumu görmedim, yalnızca snprintf.
      2013-07-03 18: 07: 31Z
     
    #include <iostream>
    #include <sstream>
    
    std::ostringstream o;
    o << name << age;
    std::cout << o.str();
    
        
    74
    2019-05-16 16: 40: 14Z
    1. bu harika, BYT başlık dosyası sstreamdir
      2017-01-13 07: 48: 03Z
     
    #include <iostream>
    #include <string>
    #include <sstream>
    using namespace std;
    string itos(int i) // convert int to string
    {
        stringstream s;
        s << i;
        return s.str();
    }
    

    http://www.research.att.com/~bs adresinden utanmadan çalındı /bs_faq2.html.

        
    50
    2012-12-07 16: 20: 46Z
    1. ancak s bir yığın değişkendir, s'un belleği itos'u çağırdıktan sonra boş olacaktır. s öbekten ayrılmalı ve kullandıktan sonra free, doğru mu?
      2018-09-10 07: 29: 11Z
    2. , dize nesnesi kapsam dışına çıkmış olsa bile değere göre geri dönün, stackoverflow.com/a/3977119/5393174
      2018-09-10 08: 18: 34Z

    Bu en kolay yoldur:

     
    string s = name + std::to_string(age);
    
        
    28
    2014-12-21 21: 50: 56Z
    1. Bu bir C ++ 11 sonrası çözümdür!
      2015-05-18 03: 30: 44Z

    C ++ 11'iniz varsa, std::to_string'u kullanabilirsiniz.

    Örnek:

     
    std::string name = "John";
    int age = 21;
    
    name += std::to_string(age);
    
    std::cout << name;
    

    Çıktı:

     
    John21
    
        
    22
    2018-04-20 09: 13: 37Z
    1. Gördüğünüz gibi VC ++ 2010'da name += std::to_string(static_cast<long long>(age)); olur burada
      2014-05-27 15: 40: 11Z
    2. @ neonmate Bunun yerine name += std::to_string(age + 0LL); nasıl?
      2016-10-07 19: 22: 58Z

    Bana en basit cevabın sprintf işlevini kullanmak olduğu görünüyor:

     
    sprintf(outString,"%s%d",name,age);
    
        
    18
    2012-12-07 16: 21: 13Z
    1. snprintf aldatıcı olabilir (esas olarak belirli durumlarda boş karakter içermediğinden dolayı), ancak sprintf arabelleği taşmasının olası sorunlardan taşmasını önlemeyi tercih ederim.
      2008-10-11 18: 08: 50Z
    2. sprintf (char *, const char *, ...), bir std :: string'i% s komutuna geçirdiğinizde bazı derleyici sürümlerinde başarısız olur. Yine de hepsi değil (tanımsız davranış) ve dizenin uzunluğuna (SSO) bağlı olabilir. Lütfen .c_str ()
      kullanın
      2008-10-13 10: 42: 31Z
    3. artı sprintf arabellek taşmalarına maruz kalır, bu nedenle olası kod enjeksiyonu
      2019-05-16 16: 41: 27Z
     
    #include <string>
    #include <sstream>
    using namespace std;
    string concatenate(std::string const& name, int i)
    {
        stringstream s;
        s << name << i;
        return s.str();
    }
    
        
    15
    2008-10-10 15: 12: 52Z
     
    #include <sstream>
    
    template <class T>
    inline std::string to_string (const T& t)
    {
       std::stringstream ss;
       ss << t;
       return ss.str();
    }
    

    Öyleyse kullanımınız şuna benzer:

     
       std::string szName = "John";
       int numAge = 23;
       szName += to_string<int>(numAge);
       cout << szName << endl;
    

    Googled [ve test edildi: p]

        
    11
    2008-10-13 16: 50: 22Z

    Çıktı işleci olan herhangi bir şeyi birleştirmek için + kullanmak istiyorsanız, operator+ şablon sürümünü sağlayabilirsiniz:

     
    template <typename L, typename R> std::string operator+(L left, R right) {
      std::ostringstream os;
      os << left << right;
      return os.str();
    }
    

    Öyleyse bitiştirmelerinizi basit bir şekilde yazabilirsiniz:

     
    std::string foo("the answer is ");
    int i = 42;
    std::string bar(foo + i);    
    std::cout << bar << std::endl;
    

    Çıktı:

     
    the answer is 42
    

    Bu en etkili yol değildir, ancak bir döngü içinde çok fazla birleştirme yapmazsanız en verimli yola ihtiyacınız yoktur.

        
    7
    2011-11-03 13: 26: 07Z
    1. Bir tamsayıya veya bir tamsayıya ve bir çifte eklemeye çalışırsam, bu işlev çağrılacak mı? Merak ediyorum, bu çözüm olağan ilaveleri geçersiz kılacak mı ...
      2016-01-14 15: 30: 59Z
    2. Operatör bir std::string döndürür, bu nedenle bir dizginin gereken türe dönüştürülemeyeceği ifadelerde aday olmaz. Örneğin, bu operator+, +'da int x = 5 + 7; için kullanılamaz. Her şey göz önünde bulundurulursa, çok zorlayıcı bir sebep olmadan böyle bir işleç tanımlamam, ancak aim, diğerlerinden farklı bir cevap sunacaktı.
      2016-01-15 15: 14: 32Z
    3. Haklısın (Ben sadece test ettim ...). Ve string s = 5 + 7 gibi bir şey yapmaya çalıştığımda, ‘int’ ile t const char ’*
      arasında geçersiz dönüşüm hatası oluştu
      2016-01-15 17: 55: 56Z

    Bu sorun birçok şekilde yapılabilir. Bunu iki şekilde göstereceğim:

    1. Sayıyı to_string(i) kullanarak dizgiye dönüştürün.

    2. Dizi akışlarını kullanma.

      Kod:

       
      #include <string>
      #include <sstream>
      #include <bits/stdc++.h>
      #include <iostream>
      using namespace std;
      
      int main() {
          string name = "John";
          int age = 21;
      
          string answer1 = "";
          // Method 1). string s1 = to_string(age).
      
          string s1=to_string(age); // Know the integer get converted into string
          // where as we know that concatenation can easily be done using '+' in C++
      
          answer1 = name + s1;
      
          cout << answer1 << endl;
      
          // Method 2). Using string streams
      
          ostringstream s2;
      
          s2 << age;
      
          string s3 = s2.str(); // The str() function will convert a number into a string
      
          string answer2 = "";  // For concatenation of strings.
      
          answer2 = name + s3;
      
          cout << answer2 << endl;
      
          return 0;
      }
      
    7
    2019-03-01 09: 03: 02Z

    MFC kullanıyorsanız, bir CString kullanabilirsiniz

     
    CString nameAge = "";
    nameAge.Format("%s%d", "John", 21);
    

    Yönetilen C ++ ayrıca bir string formatter .

        
    5
    2017-08-18 15: 54: 10Z

    std :: ostringstream iyi bir yöntemdir, ancak bazen bu ek numara, biçimlendirmeyi tek bir linere dönüştürmek için kullanışlı olabilir:

     
    #include <sstream>
    #define MAKE_STRING(tokens) /****************/ \
        static_cast<std::ostringstream&>(          \
            std::ostringstream().flush() << tokens \
        ).str()                                    \
        /**/
    

    Artık dizeleri şu şekilde biçimlendirebilirsiniz:

     
    int main() {
        int i = 123;
        std::string message = MAKE_STRING("i = " << i);
        std::cout << message << std::endl; // prints: "i = 123"
    }
    
        
    4
    2008-10-10 22: 08: 27Z

    Qt ile ilgili bir soru bunun lehine kapatıldığı için, Qt kullanarak nasıl yapılacağı:

     
    QString string = QString("Some string %1 with an int somewhere").arg(someIntVariable);
    string.append(someOtherIntVariable);
    

    Dize değişkeni artık,% 1 yerine someIntVariable değerine ve sonundaki someOtherIntVariable değerine sahip.

        
    4
    2011-08-10 13: 29: 46Z
    1. QString ("Something") + QString :: number (someIntVariable) da çalışır
      2017-08-07 04: 33: 41Z

    Tamsayıyı (veya diğer sayısal nesneyi) dizeyle birleştirmek için kullanmak daha fazla seçenek vardır. Boost.Format

     
    #include <boost/format.hpp>
    #include <string>
    int main()
    {
        using boost::format;
    
        int age = 22;
        std::string str_age = str(format("age is %1%") % age);
    }
    

    ve Karma, Boost.Spirit (v2)

    'den  
    #include <boost/spirit/include/karma.hpp>
    #include <iterator>
    #include <string>
    int main()
    {
        using namespace boost::spirit;
    
        int age = 22;
        std::string str_age("age is ");
        std::back_insert_iterator<std::string> sink(str_age);
        karma::generate(sink, int_, age);
    
        return 0;
    }
    

    Boost.Spirit Karma, dizgeye tamsayı için en hızlı seçenek dönüşüm.

        
    3
    2010-10-04 10: 00: 46Z

    Yaygın Cevap: itoa ()

    Bu kötü. itoa, standart değildir; burayı belirtin.

        
    3
    2018-04-20 09: 10: 23Z
    1. 2008-10-10 15: 11: 27Z

    İşte, IOStreams kitaplığından ayrıştırma ve biçimlendirme özelliklerinin kullanıldığı bir dizgeye int ekleme yönteminin bir uygulaması.

     
    #include <iostream>
    #include <locale>
    #include <string>
    
    template <class Facet>
    struct erasable_facet : Facet
    {
        erasable_facet() : Facet(1) { }
        ~erasable_facet() { }
    };
    
    void append_int(std::string& s, int n)
    {
        erasable_facet<std::num_put<char,
                                    std::back_insert_iterator<std::string>>> facet;
        std::ios str(nullptr);
    
        facet.put(std::back_inserter(s), str,
                                         str.fill(), static_cast<unsigned long>(n));
    }
    
    int main()
    {
        std::string str = "ID: ";
        int id = 123;
    
        append_int(str, id);
    
        std::cout << str; // ID: 123
    }
    
        
    2
    2013-12-31 16: 03: 39Z
    • std :: ostringstream
     
    #include <sstream>
    
    std::ostringstream s;
    s << "John " << age;
    std::string query(s.str());
    
    • std :: to_string (C ++ 11)
     
    std::string query("John " + std::to_string(age));
    
    • boost :: lexical_cast
     
    #include <boost/lexical_cast.hpp>
    
    std::string query("John " + boost::lexical_cast<std::string>(age));
    
        
    2
    2018-08-03 07: 09: 47Z

    Yazdığım, int sayısını parametre olarak alan ve onu bir dizgeye dönüştüren bir işlev var. Bu işlev, tek bir basamağı char eşdeğerine dönüştüren başka bir işleve bağlıdır:

     
    char intToChar(int num)
    {
        if (num < 10 && num >= 0)
        {
            return num + 48;
            //48 is the number that we add to an integer number to have its character equivalent (see the unsigned ASCII table)
        }
        else
        {
            return '*';
        }
    }
    
    string intToString(int num)
    {
        int digits = 0, process, single;
        string numString;
        process = num;
    
        // The following process the number of digits in num
        while (process != 0)
        {
            single  = process % 10; // 'single' now holds the rightmost portion of the int
            process = (process - single)/10;
            // Take out the rightmost number of the int (it's a zero in this portion of the int), then divide it by 10
            // The above combination eliminates the rightmost portion of the int
            digits ++;
        }
    
        process = num;
    
        // Fill the numString with '*' times digits
        for (int i = 0; i < digits; i++)
        {
            numString += '*';
        }
    
    
        for (int i = digits-1; i >= 0; i--)
        {
            single = process % 10;
            numString[i] = intToChar ( single);
            process = (process - single) / 10;
        }
    
        return numString;
    }
    
        
    2
    2018-09-09 21: 53: 31Z

    Verilen basit hileyi kullanarak int komutunu int ile birleştirebilirsiniz, ancak bunun yalnızca tam sayı tek haneli olduğunda çalıştığını unutmayın. Aksi takdirde, tamsayıyı o dizeye rakamla ekleyin.

     
    string name = "John";
    int age = 5;
    char temp = 5 + '0';
    name = name + temp;
    cout << name << endl;
    
    Output:  John5
    
        
    2
    2018-09-09 21: 56: 52Z

    {fmt} kütüphanesi ile:

     
    auto result = fmt::format("{}{}", name, age);
    

    Kütüphanenin bir alt kümesi, P0645 Metin Biçimlendirme ve kabul edilirse standartlaştırma için önerildi , yukarıda olacak:

     
    auto result = std::format("{}{}", name, age);
    

    Feragatname : {fmt} kütüphanesinin yazarıyım.

        
    1
    2018-04-29 17: 12: 55Z
kaynak yerleştirildi İşte